Skip to main content

cdragon_prop/
text_tree.rs

1use std::io;
2use std::io::Write;
3use super::{
4    BinEntry,
5    BinHashMappers,
6    data::*,
7    serializer::{BinSerializer, BinEntriesSerializer, BinSerializable},
8    binvalue_map_keytype,
9    binvalue_map_type,
10};
11
12
13macro_rules! indented {
14    ($s:expr, $b:block) => {{
15        $s.indent += 2;
16        let result = $b;
17        $s.indent -= 2;
18        result
19    }}
20}
21
22macro_rules! serialize {
23    ($s:expr, $($arg:tt)*) => (
24        write!($s.writer, $($arg)*)
25    );
26}
27
28macro_rules! serializeln {
29    ($s:expr) => (
30        write!($s.writer, "\n{i_:iw_$}", i_="", iw_=$s.indent)
31    );
32    ($s:expr, $fmt:expr) => (
33        serialize!($s, concat!("\n{i_:iw_$}", $fmt), i_="", iw_=$s.indent)
34    );
35    ($s:expr, $fmt:expr, $($arg:tt)*) => (
36        serialize!($s, concat!("\n{i_:iw_$}", $fmt), $($arg)*, i_="", iw_=$s.indent)
37    );
38}
39
40
41/// Serialize bin values to a human readable text tree
42#[derive(Debug)]
43pub struct TextTreeSerializer<'a, W: Write> {
44    writer: W,
45    hmappers: &'a BinHashMappers,
46    indent: usize,
47}
48
49impl<'a, W: Write> TextTreeSerializer<'a, W> {
50    /// Create a new serializer
51    pub fn new(writer: W, hmappers: &'a BinHashMappers) -> Self {
52        Self { writer, hmappers, indent: 0 }
53    }
54
55    fn format_entry_path(&self, h: BinEntryPath) -> String {
56        match h.get_str(self.hmappers) {
57            Some(s) => format!("'{}'", s),
58            _ => format!("{{{:x}}}", h),
59        }
60    }
61
62    fn format_type_name(&self, h: BinClassName) -> String {
63        match h.get_str(self.hmappers) {
64            Some(s) => s.to_string(),
65            _ => format!("{{{:x}}}", h),
66        }
67    }
68
69    fn format_field_name(&self, h: BinFieldName) -> String {
70        match h.get_str(self.hmappers) {
71            Some(s) => s.to_string(),
72            _ => format!("{{{:x}}}", h),
73        }
74    }
75
76    fn format_hash_value(&self, h: BinHashValue) -> String {
77        match h.get_str(self.hmappers) {
78            Some(s) => format!("'{}'", s),
79            _ => format!("{{{:x}}}", h),
80        }
81    }
82
83    fn format_path_value(&self, h: BinPathValue) -> String {
84        match h.get_str(self.hmappers) {
85            Some(s) => format!("'{}'", s),
86            _ => format!("{{{:x}}}", h),
87        }
88    }
89
90    fn write_fields(&mut self, fields: &[BinField]) -> io::Result<()> {
91        if fields.is_empty() {
92            serialize!(self, "[]")?;
93        } else {
94            serialize!(self, "[")?;
95            indented!(self, {
96                fields.iter().try_for_each(|field| -> io::Result<()> {
97                    serializeln!(self, "<{} ", self.format_field_name(field.name))?;
98                    self.write_field_content(field)?;
99                    serialize!(self, ">")?;
100                    Ok(())
101                })?;
102            });
103            serializeln!(self, "]")?;
104        }
105        Ok(())
106    }
107
108    fn write_field_content(&mut self, field: &BinField) -> io::Result<()> {
109        macro_rules! serialize_field {
110            // Default, for basic bin types
111            ($t:ty) => {{
112                let v = field.downcast::<$t>().unwrap();
113                serialize!(self, "{} ", basic_bintype_name(field.vtype))?;
114                v.serialize_bin(self)?;
115            }};
116            // Nested bin types with fields
117            ($t:ty: {$v:ident} => $($fmt:tt)*) => {{
118                let $v = field.downcast::<$t>().unwrap();
119                serialize!(self, $($fmt)*)?;
120                self.write_fields(&$v.fields)?;
121            }};
122            // Other nested bin types
123            ($t:ty: [$v:ident] => $($fmt:tt)*) => {{
124                let $v = field.downcast::<$t>().unwrap();
125                serialize!(self, $($fmt)*)?;
126                $v.serialize_bin(self)?;
127            }};
128        }
129
130        match field.vtype {
131            BinType::None => serialize_field!(BinNone),
132            BinType::Bool => serialize_field!(BinBool),
133            BinType::S8 => serialize_field!(BinS8),
134            BinType::U8 => serialize_field!(BinU8),
135            BinType::S16 => serialize_field!(BinS16),
136            BinType::U16 => serialize_field!(BinU16),
137            BinType::S32 => serialize_field!(BinS32),
138            BinType::U32 => serialize_field!(BinU32),
139            BinType::S64 => serialize_field!(BinS64),
140            BinType::U64 => serialize_field!(BinU64),
141            BinType::Float => serialize_field!(BinFloat),
142            BinType::Vec2 => serialize_field!(BinVec2),
143            BinType::Vec3 => serialize_field!(BinVec3),
144            BinType::Vec4 => serialize_field!(BinVec4),
145            BinType::Matrix => serialize_field!(BinMatrix),
146            BinType::Color => serialize_field!(BinColor),
147            BinType::String => serialize_field!(BinString),
148            BinType::Hash => serialize_field!(BinHash),
149            BinType::Path => serialize_field!(BinPath),
150            BinType::List | BinType::List2 => serialize_field!(BinList: [v] => "LIST({}) ", basic_bintype_name(v.vtype)),
151            BinType::Struct => serialize_field!(BinStruct: {v} => "STRUCT {} ", self.format_type_name(v.ctype)),
152            BinType::Embed => serialize_field!(BinEmbed: {v} => "EMBED {} ", self.format_type_name(v.ctype)),
153            BinType::Link => serialize_field!(BinLink),
154            BinType::Option => serialize_field!(BinOption: [v] => "OPTION({}) ", basic_bintype_name(v.vtype)),
155            BinType::Map => serialize_field!(BinMap: [v] => "MAP({},{}) ", basic_bintype_name(v.ktype), basic_bintype_name(v.vtype)),
156            BinType::Flag => serialize_field!(BinFlag),
157        }
158        Ok(())
159    }
160}
161
162impl<'a, W: Write> BinSerializer for TextTreeSerializer<'a, W> {
163    type EntriesSerializer = TextTreeEntriesSerializer<'a, W>;
164
165    fn write_entry(&mut self, v: &BinEntry) -> io::Result<()> {
166        serialize!(self, "<BinEntry {} {} ", self.format_entry_path(v.path), self.format_type_name(v.ctype))?;
167        self.write_fields(&v.fields)?;
168        serialize!(self, ">")?;
169        serializeln!(self)
170    }
171
172    fn write_entries(self) -> io::Result<Self::EntriesSerializer> {
173        Ok(Self::EntriesSerializer { parent: self })
174    }
175
176    fn write_none(&mut self, _: &BinNone) -> io::Result<()> { serialize!(self, "-") }
177    fn write_bool(&mut self, v: &BinBool) -> io::Result<()> { serialize!(self, "{}", v.0) }
178    fn write_s8(&mut self, v: &BinS8) -> io::Result<()> { serialize!(self, "{}", v.0) }
179    fn write_u8(&mut self, v: &BinU8) -> io::Result<()> { serialize!(self, "{}", v.0) }
180    fn write_s16(&mut self, v: &BinS16) -> io::Result<()> { serialize!(self, "{}", v.0) }
181    fn write_u16(&mut self, v: &BinU16) -> io::Result<()> { serialize!(self, "{}", v.0) }
182    fn write_s32(&mut self, v: &BinS32) -> io::Result<()> { serialize!(self, "{}", v.0) }
183    fn write_u32(&mut self, v: &BinU32) -> io::Result<()> { serialize!(self, "{}", v.0) }
184    fn write_s64(&mut self, v: &BinS64) -> io::Result<()> { serialize!(self, "{}", v.0) }
185    fn write_u64(&mut self, v: &BinU64) -> io::Result<()> { serialize!(self, "{}", v.0) }
186    fn write_float(&mut self, v: &BinFloat) -> io::Result<()> { serialize!(self, "{}", v.0) }
187    fn write_vec2(&mut self, v: &BinVec2) -> io::Result<()> { serialize!(self, "({}, {})", v.0, v.1) }
188    fn write_vec3(&mut self, v: &BinVec3) -> io::Result<()> { serialize!(self, "({}, {}, {})", v.0, v.1, v.2) }
189    fn write_vec4(&mut self, v: &BinVec4) -> io::Result<()> { serialize!(self, "({}, {}, {}, {})", v.0, v.1, v.2, v.3) }
190    fn write_matrix(&mut self, v: &BinMatrix) -> io::Result<()> { serialize!(self,
191        "(({}, {}, {}, {}), ({}, {}, {}, {}), ({}, {}, {}, {}), ({}, {}, {}, {}))",
192        v.0[0][0], v.0[0][1], v.0[0][2], v.0[0][3],
193        v.0[1][0], v.0[1][1], v.0[1][2], v.0[1][3],
194        v.0[2][0], v.0[2][1], v.0[2][2], v.0[2][3],
195        v.0[3][0], v.0[3][1], v.0[3][2], v.0[3][3]) }
196    fn write_color(&mut self, v: &BinColor) -> io::Result<()> { serialize!(self, "({}, {}, {}, {})", v.r, v.g, v.b, v.a) }
197    fn write_string(&mut self, v: &BinString) -> io::Result<()> { serialize!(self, "'{}'", v.0) }
198    fn write_hash(&mut self, v: &BinHash) -> io::Result<()> { serialize!(self, "{}", self.format_hash_value(v.0)) }
199    fn write_path(&mut self, v: &BinPath) -> io::Result<()> { serialize!(self, "{}", self.format_path_value(v.0)) }
200    fn write_link(&mut self, v: &BinLink) -> io::Result<()> { serialize!(self, "{}", self.format_entry_path(v.0)) }
201    fn write_flag(&mut self, v: &BinFlag) -> io::Result<()> { serialize!(self, "{}", v.0) }
202
203    fn write_list(&mut self, v: &BinList) -> io::Result<()> {
204        serialize!(self, "[")?;
205        indented!(self, {
206            binvalue_map_type!(
207                v.vtype, T,
208                v.downcast::<T>().unwrap().iter().try_for_each(|x| {
209                    serializeln!(self)?;
210                    x.serialize_bin(self)
211                }))?;
212        });
213        serializeln!(self, "]")?;
214        Ok(())
215    }
216
217    fn write_struct(&mut self, v: &BinStruct) -> io::Result<()> {
218        serialize!(self, "<STRUCT {} ", self.format_type_name(v.ctype))?;
219        self.write_fields(&v.fields)?;
220        serialize!(self, ">")?;
221        Ok(())
222    }
223
224    fn write_embed(&mut self, v: &BinEmbed) -> io::Result<()> {
225        serialize!(self, "<EMBED {} ", self.format_type_name(v.ctype))?;
226        self.write_fields(&v.fields)?;
227        serialize!(self, ">")?;
228        Ok(())
229    }
230
231    fn write_option(&mut self, option: &BinOption) -> io::Result<()> {
232        if option.value.is_none() {
233            serialize!(self, "-")?;
234        } else {
235            serialize!(self, "[")?;
236            indented!(self, {
237                serializeln!(self)?;
238                binvalue_map_type!(option.vtype, T, {
239                    option
240                        .downcast::<T>()
241                        .unwrap()  // `None` case processed above
242                        .serialize_bin(self)
243                })?
244            });
245            serializeln!(self, "]")?;
246        }
247        Ok(())
248    }
249
250    fn write_map(&mut self, map: &BinMap) -> io::Result<()> {
251        serialize!(self, "{{")?;
252        indented!(self, {
253            binvalue_map_keytype!(
254                map.ktype, K,
255                binvalue_map_type!(
256                    map.vtype, V,
257                    map.downcast::<K, V>().unwrap().iter().try_for_each(|(k, v)| -> io::Result<()> {
258                        serializeln!(self)?;
259                        k.serialize_bin(self)?;
260                        serialize!(self, " => ")?;
261                        v.serialize_bin(self)?;
262                        Ok(())
263                    })))?;
264        });
265        serializeln!(self, "}}")?;
266        Ok(())
267    }
268}
269
270fn basic_bintype_name(vtype: BinType) -> &'static str {
271    match vtype {
272        BinType::None => "NONE",
273        BinType::Bool => "BOOL",
274        BinType::S8 => "S8",
275        BinType::U8 => "U8",
276        BinType::S16 => "S16",
277        BinType::U16 => "U16",
278        BinType::S32 => "S32",
279        BinType::U32 => "U32",
280        BinType::S64 => "S64",
281        BinType::U64 => "U64",
282        BinType::Float => "FLOAT",
283        BinType::Vec2 => "VEC2",
284        BinType::Vec3 => "VEC3",
285        BinType::Vec4 => "VEC4",
286        BinType::Matrix => "MATRIX",
287        BinType::Color => "COLOR",
288        BinType::String => "STRING",
289        BinType::Hash => "HASH",
290        BinType::Path => "PATH",
291        BinType::Struct => "STRUCT",
292        BinType::Embed => "EMBED",
293        BinType::Link => "LINK",
294        BinType::Flag => "FLAG",
295        _ => panic!("basic BinType name should not be needed for non-nestable types"),
296    }
297}
298
299
300pub struct TextTreeEntriesSerializer<'a, W: Write> {
301    parent: TextTreeSerializer<'a, W>,
302}
303
304impl<'a, W: Write> BinEntriesSerializer for TextTreeEntriesSerializer<'a, W> {
305    fn write_entry(&mut self, entry: &BinEntry) -> io::Result<()> {
306        self.parent.write_entry(entry)
307    }
308
309    fn end(&mut self) -> io::Result<()> {
310        Ok(())
311    }
312}
313