aboutsummaryrefslogtreecommitdiff
path: root/src/classes.rs
blob: 87bce8c3688783507df6f9846bc1af2208ef250e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
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,
}