aboutsummaryrefslogtreecommitdiff
path: root/src/classes.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/classes.rs')
-rw-r--r--src/classes.rs101
1 files changed, 101 insertions, 0 deletions
diff --git a/src/classes.rs b/src/classes.rs
new file mode 100644
index 0000000..87bce8c
--- /dev/null
+++ b/src/classes.rs
@@ -0,0 +1,101 @@
+use crate::object::Value;
+use anyhow::Result;
+use serde::Serialize;
+use std::collections::BTreeMap;
+
+#[derive(Serialize)]
+pub enum HValue {
+ PPtr(PPtr),
+ Pair(Box<HValue>, Box<HValue>),
+ Value([Value; 1]),
+ Map(BTreeMap<String, HValue>),
+ AssetInfo(AssetInfo),
+
+ Array(Vec<HValue>),
+ Object {
+ class: String,
+ fields: BTreeMap<String, HValue>,
+ },
+}
+
+impl HValue {
+ pub fn from_value(v: Value) -> Result<HValue> {
+ Ok(match v {
+ Value::Array(a) => Self::Array(
+ a.into_iter()
+ .map(|e| HValue::from_value(e))
+ .collect::<Result<Vec<_>>>()?,
+ ),
+ Value::Object { class, fields } => {
+ let mut fields = fields
+ .into_iter()
+ .map(|(k, v)| Ok((k, HValue::from_value(v)?)))
+ .collect::<Result<BTreeMap<_, _>>>()?;
+
+ match class.as_str() {
+ x if x.starts_with("PPtr<") => {
+ let inner = x.strip_prefix("PPtr<").unwrap().strip_suffix(">").unwrap();
+ Self::PPtr(PPtr {
+ class: inner.to_owned(),
+ file_id: fields["m_FileID"].as_value().unwrap().as_i32().unwrap(),
+ path_id: fields["m_PathID"].as_value().unwrap().as_i64().unwrap(),
+ })
+ }
+ "AssetInfo" => Self::AssetInfo(AssetInfo {
+ preload_index: fields["preloadIndex"].as_value().unwrap().as_i32().unwrap(),
+ preload_size: fields["preloadSize"].as_value().unwrap().as_i32().unwrap(),
+ asset: fields.remove("asset").unwrap().as_pptr().unwrap(),
+ }),
+ "map" => {
+ let Self::Array(a) = fields.remove("Array").unwrap() else {
+ unreachable!()
+ };
+ Self::Map(
+ a.into_iter()
+ .map(|e| {
+ let Self::Pair(k, v) = e else { unreachable!() };
+ (k.as_value().unwrap().clone().as_string().unwrap(), *v)
+ })
+ .collect(),
+ )
+ }
+ "pair" => Self::Pair(
+ Box::new(fields.remove("first").unwrap()),
+ Box::new(fields.remove("second").unwrap()),
+ ),
+ "vector" => fields.remove("Array").unwrap(),
+ _ => Self::Object { class, fields },
+ }
+ }
+ x => Self::Value([x]),
+ })
+ }
+ pub fn as_value(&self) -> Option<&Value> {
+ if let HValue::Value(v) = self {
+ Some(&v[0])
+ } else {
+ None
+ }
+ }
+ pub fn as_pptr(self) -> Option<PPtr> {
+ if let HValue::PPtr(v) = self {
+ Some(v)
+ } else {
+ None
+ }
+ }
+}
+
+#[derive(Debug, Serialize)]
+pub struct PPtr {
+ class: String,
+ file_id: i32,
+ path_id: i64,
+}
+
+#[derive(Debug, Serialize)]
+pub struct AssetInfo {
+ preload_index: i32,
+ preload_size: i32,
+ asset: PPtr,
+}