diff options
Diffstat (limited to 'src/object.rs')
-rw-r--r-- | src/object.rs | 246 |
1 files changed, 0 insertions, 246 deletions
diff --git a/src/object.rs b/src/object.rs deleted file mode 100644 index 92415e1..0000000 --- a/src/object.rs +++ /dev/null @@ -1,246 +0,0 @@ -use crate::helper::{AlignExt, Endianness, ReadExt}; -use crate::serialized_file::TypeTreeNode; -use anyhow::{Result, bail}; -use log::trace; -use serde::Serialize; -use std::io::Seek; -use std::{collections::BTreeMap, io::Read}; - -#[derive(Debug, Clone, Serialize)] -pub enum Value { - Bool(bool), - U8(u8), - I8(i8), - U16(u16), - I16(i16), - U32(u32), - I32(i32), - F32(f32), - U64(u64), - I64(i64), - F64(f64), - Array(Vec<Value>), - Object { - class: String, - fields: BTreeMap<String, Value>, - }, - Typeless(Vec<u8>), - String(String), -} - -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)?); - } - 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(), read_value(&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 - ); - } - if align || ty.post_align() { - trace!("post align"); - data.align(4)?; - } - r -} - -impl Value { - pub fn class_name(&self) -> Option<&String> { - if let Value::Object { class, .. } = self { - Some(class) - } else { - None - } - } - pub fn as_class(self, name: &str) -> Option<BTreeMap<String, Value>> { - if let Value::Object { class, fields } = self { - if class == name { Some(fields) } else { None } - } else { - None - } - } - pub fn as_string(self) -> Option<String> { - if let Value::String(s) = self { - Some(s) - } else { - None - } - } - pub fn as_i64(&self) -> Option<i64> { - if let Value::I64(s) = self { - Some(*s) - } else { - None - } - } - pub fn as_i32(&self) -> Option<i32> { - if let Value::I32(s) = self { - Some(*s) - } else { - None - } - } - pub fn as_u32(&self) -> Option<u32> { - if let Value::U32(s) = self { - Some(*s) - } else { - None - } - } - pub fn as_u64(&self) -> Option<u64> { - match self { - Self::U64(x) => Some(*x), - Self::U32(x) => Some(*x as u64), - _ => None, - } - } - pub fn as_f32(&self) -> Option<f32> { - if let Value::F32(s) = self { - Some(*s) - } else { - None - } - } - pub fn as_u16(&self) -> Option<u16> { - if let Value::U16(s) = self { - Some(*s) - } else { - None - } - } - pub fn as_bool(&self) -> Option<bool> { - if let Value::Bool(s) = self { - Some(*s) - } else { - None - } - } - pub fn as_array(self) -> Option<Vec<Value>> { - if let Value::Array(s) = self { - Some(s) - } else { - None - } - } - pub fn as_typeless(self) -> Option<Vec<u8>> { - if let Value::Typeless(s) = self { - Some(s) - } else { - None - } - } - pub fn to_json(self) -> serde_json::Value { - match self { - Value::Bool(x) => serde_json::Value::Bool(x), - Value::U8(x) => serde_json::Value::Number(x.into()), - Value::I8(x) => serde_json::Value::Number(x.into()), - Value::U16(x) => serde_json::Value::Number(x.into()), - Value::I16(x) => serde_json::Value::Number(x.into()), - Value::U32(x) => serde_json::Value::Number(x.into()), - Value::U64(x) => serde_json::Value::Number(x.into()), - Value::I32(x) => serde_json::Value::Number(x.into()), - Value::F32(x) => serde_json::Value::Number( - serde_json::Number::from_f64(x as f64).unwrap_or(0.into()), - ), - Value::I64(x) => serde_json::Value::Number(x.into()), - Value::F64(x) => serde_json::Value::Number(serde_json::Number::from_f64(x).unwrap()), - Value::String(x) => serde_json::Value::String(x), - Value::Typeless(values) => serde_json::Value::Array( - values - .into_iter() - .map(|e| serde_json::Value::Number(e.into())) - .collect(), - ), - Value::Array(values) => { - serde_json::Value::Array(values.into_iter().map(Value::to_json).collect()) - } - Value::Object { class, fields } => serde_json::Value::Object( - fields - .into_iter() - .map(|(k, v)| (k, v.to_json())) - .chain(Some(( - "@class".to_string(), - serde_json::Value::String(class), - ))) - .collect(), - ), - } - } -} |