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#[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 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 ($t:ty) => {{
112 let v = field.downcast::<$t>().unwrap();
113 serialize!(self, "{} ", basic_bintype_name(field.vtype))?;
114 v.serialize_bin(self)?;
115 }};
116 ($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 ($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() .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