aboutsummaryrefslogtreecommitdiff
path: root/src/object
diff options
context:
space:
mode:
authormetamuffin <metamuffin@disroot.org>2025-03-13 20:10:32 +0100
committermetamuffin <metamuffin@disroot.org>2025-03-13 20:10:32 +0100
commit8f80baff4d18b67859eded67b8c5097324693862 (patch)
tree380c5a9bfbd427c8363032a231b1da1fb30db960 /src/object
parentd3006b6d05f7995c6a49d67401293f1266b3ea1f (diff)
downloadunity-tools-8f80baff4d18b67859eded67b8c5097324693862.tar
unity-tools-8f80baff4d18b67859eded67b8c5097324693862.tar.bz2
unity-tools-8f80baff4d18b67859eded67b8c5097324693862.tar.zst
read object abstraction
Diffstat (limited to 'src/object')
-rw-r--r--src/object/read.rs170
1 files changed, 84 insertions, 86 deletions
diff --git a/src/object/read.rs b/src/object/read.rs
index 5adbe3f..641bdcc 100644
--- a/src/object/read.rs
+++ b/src/object/read.rs
@@ -6,95 +6,93 @@ use log::trace;
use std::io::Seek;
use std::{collections::BTreeMap, io::Read};
-pub fn read_value(
- ty: &TypeTreeNode,
- e: Endianness,
- data: &mut (impl Read + Seek),
-) -> Result<Value> {
- let mut align = false;
- let pos_before = data.stream_position()?;
- let r = match ty.type_string.as_str() {
- "char" => {
- assert_eq!(ty.byte_size, 1);
- Ok(Value::U8(data.read_u8()?))
- }
- "Type*" => Ok(Value::U32(data.read_u32(e)?)),
- "int" => Ok(Value::I32(data.read_i32(e)?)),
- "unsigned int" => Ok(Value::U32(data.read_u32(e)?)),
- "UInt8" => Ok(Value::U8(data.read_u8()?)),
- "UInt16" => Ok(Value::U16(data.read_u16(e)?)),
- "UInt32" => Ok(Value::U32(data.read_u32(e)?)),
- "UInt64" => Ok(Value::U64(data.read_u64(e)?)),
- "SInt8" => Ok(Value::I8(data.read_i8()?)),
- "SInt16" => Ok(Value::I16(data.read_i16(e)?)),
- "SInt32" => Ok(Value::I32(data.read_i32(e)?)),
- "SInt64" => Ok(Value::I64(data.read_i64(e)?)),
- "bool" => Ok(Value::Bool(data.read_u8()? != 0)),
- "float" => {
- data.align(4)?;
- Ok(Value::F32(data.read_f32(e)?))
- }
- "double" => {
- data.align(4)?;
- Ok(Value::F64(data.read_f64(e)?))
- }
- "string" => {
- let Value::Array(arr) = read_value(&ty.children[0], e, data)? else {
- unreachable!()
- };
- let bytes = arr
- .into_iter()
- .map(|e| match e {
- Value::U8(x) => x,
- _ => unreachable!(),
- })
- .collect::<Vec<_>>();
- Ok(Value::String(String::from_utf8(bytes)?))
- }
- "Array" => {
- align |= ty.children[0].post_align();
- assert_eq!(ty.byte_size, -1);
- let Value::I32(size) = read_value(&ty.children[0], e, data)? else {
- unreachable!()
- };
- trace!("array of size {size}");
- let mut elems = Vec::new();
- for _ in 0..size {
- elems.push(read_value(&ty.children[1], e, data)?);
+impl Value {
+ pub fn read(ty: &TypeTreeNode, e: Endianness, data: &mut (impl Read + Seek)) -> Result<Value> {
+ let mut align = false;
+ let pos_before = data.stream_position()?;
+ let r = match ty.type_string.as_str() {
+ "char" => {
+ assert_eq!(ty.byte_size, 1);
+ Ok(Value::U8(data.read_u8()?))
}
- Ok(Value::Array(elems))
- }
- "TypelessData" => {
- let len = data.read_u32(e)?;
- let mut buf = vec![0u8; len as usize];
- data.read_exact(&mut buf)?;
- Ok(Value::Typeless(buf))
- }
- _ => {
- if ty.children.is_empty() && ty.byte_size != 0 {
- todo!("need type {:?}", ty.type_string);
+ "Type*" => Ok(Value::U32(data.read_u32(e)?)),
+ "int" => Ok(Value::I32(data.read_i32(e)?)),
+ "unsigned int" => Ok(Value::U32(data.read_u32(e)?)),
+ "UInt8" => Ok(Value::U8(data.read_u8()?)),
+ "UInt16" => Ok(Value::U16(data.read_u16(e)?)),
+ "UInt32" => Ok(Value::U32(data.read_u32(e)?)),
+ "UInt64" => Ok(Value::U64(data.read_u64(e)?)),
+ "SInt8" => Ok(Value::I8(data.read_i8()?)),
+ "SInt16" => Ok(Value::I16(data.read_i16(e)?)),
+ "SInt32" => Ok(Value::I32(data.read_i32(e)?)),
+ "SInt64" => Ok(Value::I64(data.read_i64(e)?)),
+ "bool" => Ok(Value::Bool(data.read_u8()? != 0)),
+ "float" => {
+ data.align(4)?;
+ Ok(Value::F32(data.read_f32(e)?))
}
- let mut fields = BTreeMap::new();
- for c in &ty.children {
- fields.insert(c.name_string.clone(), read_value(&c, e, data)?);
+ "double" => {
+ data.align(4)?;
+ Ok(Value::F64(data.read_f64(e)?))
}
- Ok(Value::Object {
- fields,
- class: ty.type_string.clone(),
- })
+ "string" => {
+ let Value::Array(arr) = Value::read(&ty.children[0], e, data)? else {
+ unreachable!()
+ };
+ let bytes = arr
+ .into_iter()
+ .map(|e| match e {
+ Value::U8(x) => x,
+ _ => unreachable!(),
+ })
+ .collect::<Vec<_>>();
+ Ok(Value::String(String::from_utf8(bytes)?))
+ }
+ "Array" => {
+ align |= ty.children[0].post_align();
+ assert_eq!(ty.byte_size, -1);
+ let Value::I32(size) = Value::read(&ty.children[0], e, data)? else {
+ unreachable!()
+ };
+ trace!("array of size {size}");
+ let mut elems = Vec::new();
+ for _ in 0..size {
+ elems.push(Value::read(&ty.children[1], e, data)?);
+ }
+ Ok(Value::Array(elems))
+ }
+ "TypelessData" => {
+ let len = data.read_u32(e)?;
+ let mut buf = vec![0u8; len as usize];
+ data.read_exact(&mut buf)?;
+ Ok(Value::Typeless(buf))
+ }
+ _ => {
+ if ty.children.is_empty() && ty.byte_size != 0 {
+ todo!("need type {:?}", ty.type_string);
+ }
+ let mut fields = BTreeMap::new();
+ for c in &ty.children {
+ fields.insert(c.name_string.clone(), Value::read(&c, e, data)?);
+ }
+ Ok(Value::Object {
+ fields,
+ class: ty.type_string.clone(),
+ })
+ }
+ };
+ let pos_after = data.stream_position()?;
+ if ty.byte_size != -1 && pos_after - pos_before < ty.byte_size as u64 {
+ bail!(
+ "did not read enough data ({} expected, {} actual)",
+ ty.byte_size,
+ pos_after - pos_before
+ );
}
- };
- let pos_after = data.stream_position()?;
- if ty.byte_size != -1 && pos_after - pos_before < ty.byte_size as u64 {
- bail!(
- "did not read enough data ({} expected, {} actual)",
- ty.byte_size,
- pos_after - pos_before
- );
- }
- if align || ty.post_align() {
- trace!("post align");
- data.align(4)?;
+ if align || ty.post_align() {
+ trace!("post align");
+ data.align(4)?;
+ }
+ r
}
- r
}