aboutsummaryrefslogtreecommitdiff
path: root/src/object.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/object.rs')
-rw-r--r--src/object.rs87
1 files changed, 85 insertions, 2 deletions
diff --git a/src/object.rs b/src/object.rs
index 9875517..5ad1441 100644
--- a/src/object.rs
+++ b/src/object.rs
@@ -1,4 +1,87 @@
+use crate::helper::{AlignExt, Endianness, ReadExt};
use crate::serialized_file::TypeTreeNode;
-use std::io::Read;
+use anyhow::Result;
+use log::debug;
+use std::io::Seek;
+use std::{collections::BTreeMap, io::Read};
-pub fn read_value(ty: TypeTreeNode, data: &mut impl Read) {}
+#[derive(Debug)]
+pub enum Value {
+ Bool(bool),
+ U8(u8),
+ U16(u16),
+ U32(u32),
+ I32(i32),
+ F32(f32),
+ I64(i64),
+ F64(f64),
+ Array(Vec<Value>),
+ Object {
+ class: String,
+ fields: BTreeMap<String, Value>,
+ },
+ String(String),
+}
+
+pub fn read_value(
+ ty: &TypeTreeNode,
+ e: Endianness,
+ data: &mut (impl Read + Seek),
+) -> Result<Value> {
+ match ty.type_string.as_str() {
+ "char" => Ok(Value::U8(data.read_u8()?)),
+ "int" => Ok(Value::I32(data.read_i32(e)?)),
+ "unsigned int" => Ok(Value::U32(data.read_u32(e)?)),
+ "UInt16" => Ok(Value::U16(data.read_u16(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| {
+ if let Value::U8(x) = e {
+ x
+ } else {
+ unreachable!()
+ }
+ })
+ .collect::<Vec<_>>();
+ Ok(Value::String(String::from_utf8(bytes)?))
+ }
+ "Array" => {
+ let Value::I32(size) = read_value(&ty.children[0], e, data)? else {
+ unreachable!()
+ };
+ debug!("array of size {size}");
+ let mut elems = Vec::new();
+ for _ in 0..size {
+ elems.push(read_value(&ty.children[1], e, data)?);
+ }
+ Ok(Value::Array(elems))
+ }
+ _ => {
+ if ty.children.is_empty() && ty.byte_size != -1 {
+ todo!("need type {:?}", ty.type_string);
+ }
+ let mut fields = BTreeMap::new();
+ for c in &ty.children {
+ fields.insert(c.name_string.clone(), read_value(&c, e, data)?);
+ }
+ Ok(Value::Object {
+ fields,
+ class: ty.type_string.clone(),
+ })
+ }
+ }
+}