1use std::io;
2
3use crate::render::{format_hex_dump, write_indent};
4use crate::types::{BitPatternField, FieldTable, FixedWidthField, TermAnnotation, Value, VariableLengthField};
5use crate::write::SyntaxWrite;
6
7use super::text::TextRenderError;
8
9pub struct CompactTextRenderer<W> {
17 writer: W,
18 depth: usize,
19 block_stack: Vec<BlockKind>,
20 suppress_depth: Option<usize>,
23}
24
25#[derive(Debug, Clone, Copy, PartialEq)]
26enum BlockKind {
27 Element,
28 If { indented: bool },
31 For,
32 While,
33 DoWhile,
34 Switch,
35 Case { indented: bool },
37}
38
39impl<W: io::Write> CompactTextRenderer<W> {
40 pub fn new(writer: W) -> Self {
41 CompactTextRenderer {
42 writer,
43 depth: 0,
44 block_stack: Vec::new(),
45 suppress_depth: None,
46 }
47 }
48
49 pub fn into_inner(self) -> W {
50 self.writer
51 }
52
53 fn suppressed(&self) -> bool {
54 self.suppress_depth.is_some()
55 }
56
57 fn indent(&mut self) -> io::Result<()> {
58 write_indent(&mut self.writer, self.depth)
59 }
60
61 fn write_field(&mut self, name: &str, value: Option<&Value>, comment: Option<&str>) -> io::Result<()> {
62 if self.suppressed() {
63 return Ok(());
64 }
65 self.indent()?;
66 match (value, comment) {
67 (Some(val), Some(c)) => writeln!(self.writer, "{name}: {val} // {c}"),
68 (Some(val), None) => writeln!(self.writer, "{name}: {val}"),
69 (None, Some(c)) => writeln!(self.writer, "{name} // {c}"),
70 (None, None) => writeln!(self.writer, "{name}"),
71 }
72 }
73}
74
75impl<W: io::Write> SyntaxWrite for CompactTextRenderer<W> {
76 type Error = TextRenderError;
77
78 fn begin_element(&mut self, name: &str, params: Option<&str>) -> Result<(), Self::Error> {
79 if !self.suppressed() {
80 self.indent()?;
81 match params {
82 Some(p) => writeln!(self.writer, "{name}({p}):")?,
83 None => writeln!(self.writer, "{name}:")?,
84 }
85 }
86 self.depth += 1;
87 self.block_stack.push(BlockKind::Element);
88 Ok(())
89 }
90
91 fn end_element(&mut self) -> Result<(), Self::Error> {
92 debug_assert_eq!(self.block_stack.pop(), Some(BlockKind::Element));
93 self.depth -= 1;
94 Ok(())
95 }
96
97 fn fixed_width_field(&mut self, field: &FixedWidthField<'_>) -> Result<(), Self::Error> {
98 self.write_field(field.name, field.value.as_ref(), field.comment)?;
99 Ok(())
100 }
101
102 fn variable_length_field(&mut self, field: &VariableLengthField<'_>) -> Result<(), Self::Error> {
103 self.write_field(field.name, field.value.as_ref(), field.comment)?;
104 Ok(())
105 }
106
107 fn bit_pattern(&mut self, field: &BitPatternField<'_>) -> Result<(), Self::Error> {
108 self.write_field(field.name, Some(&field.value), None)?;
109 Ok(())
110 }
111
112 fn raw_bytes(&mut self, data: &[u8]) -> Result<(), Self::Error> {
113 if self.suppressed() {
114 return Ok(());
115 }
116 if data.len() <= 16 {
117 self.indent()?;
119 let hex: Vec<String> = data.iter().map(|b| format!("{b:02x}")).collect();
120 writeln!(self.writer, "{}", hex.join(" "))?;
121 } else {
122 let lines = format_hex_dump(data);
123 for line in &lines {
124 self.indent()?;
125 writeln!(self.writer, "{line}")?;
126 }
127 }
128 Ok(())
129 }
130
131 fn begin_if(
134 &mut self,
135 _condition: &str,
136 _terms: &[TermAnnotation<'_>],
137 taken: bool,
138 ) -> Result<(), Self::Error> {
139 if !taken && !self.suppressed() {
140 self.suppress_depth = Some(self.depth);
141 }
142 self.block_stack.push(BlockKind::If { indented: false });
144 Ok(())
145 }
146
147 fn begin_else_if(
148 &mut self,
149 _condition: &str,
150 _terms: &[TermAnnotation<'_>],
151 taken: bool,
152 ) -> Result<(), Self::Error> {
153 debug_assert!(matches!(self.block_stack.last(), Some(BlockKind::If { .. })));
154 if taken {
155 if self.suppress_depth == Some(self.depth) {
156 self.suppress_depth = None;
157 }
158 } else if !self.suppressed() {
159 self.suppress_depth = Some(self.depth);
160 }
161 Ok(())
162 }
163
164 fn begin_else(&mut self, taken: bool) -> Result<(), Self::Error> {
165 debug_assert!(matches!(self.block_stack.last(), Some(BlockKind::If { .. })));
166 if taken {
167 if self.suppress_depth == Some(self.depth) {
168 self.suppress_depth = None;
169 }
170 } else if !self.suppressed() {
171 self.suppress_depth = Some(self.depth);
172 }
173 Ok(())
174 }
175
176 fn end_if(&mut self) -> Result<(), Self::Error> {
177 debug_assert!(matches!(self.block_stack.pop(), Some(BlockKind::If { .. })));
178 if self.suppress_depth == Some(self.depth) {
179 self.suppress_depth = None;
180 }
181 Ok(())
182 }
183
184 fn begin_for(
187 &mut self,
188 _header: &str,
189 _terms: &[TermAnnotation<'_>],
190 ) -> Result<(), Self::Error> {
191 self.depth += 1;
192 self.block_stack.push(BlockKind::For);
193 Ok(())
194 }
195
196 fn for_iteration(&mut self, _variable: &str, index: u64) -> Result<(), Self::Error> {
197 if self.suppressed() {
198 return Ok(());
199 }
200 self.indent()?;
201 writeln!(self.writer, "[{index}]:")?;
202 Ok(())
203 }
204
205 fn end_for(&mut self) -> Result<(), Self::Error> {
206 debug_assert_eq!(self.block_stack.pop(), Some(BlockKind::For));
207 self.depth -= 1;
208 Ok(())
209 }
210
211 fn begin_while(&mut self, _condition: &str) -> Result<(), Self::Error> {
212 self.depth += 1;
213 self.block_stack.push(BlockKind::While);
214 Ok(())
215 }
216
217 fn while_iteration(&mut self, index: u64) -> Result<(), Self::Error> {
218 if self.suppressed() {
219 return Ok(());
220 }
221 self.indent()?;
222 writeln!(self.writer, "[{index}]:")?;
223 Ok(())
224 }
225
226 fn end_while(&mut self) -> Result<(), Self::Error> {
227 debug_assert_eq!(self.block_stack.pop(), Some(BlockKind::While));
228 self.depth -= 1;
229 Ok(())
230 }
231
232 fn begin_do_while(&mut self) -> Result<(), Self::Error> {
233 self.depth += 1;
234 self.block_stack.push(BlockKind::DoWhile);
235 Ok(())
236 }
237
238 fn do_while_iteration(&mut self, index: u64) -> Result<(), Self::Error> {
239 if self.suppressed() {
240 return Ok(());
241 }
242 self.indent()?;
243 writeln!(self.writer, "[{index}]:")?;
244 Ok(())
245 }
246
247 fn end_do_while(&mut self, _condition: &str) -> Result<(), Self::Error> {
248 debug_assert_eq!(self.block_stack.pop(), Some(BlockKind::DoWhile));
249 self.depth -= 1;
250 Ok(())
251 }
252
253 fn begin_switch(
256 &mut self,
257 _expression: &str,
258 _terms: &[TermAnnotation<'_>],
259 ) -> Result<(), Self::Error> {
260 self.block_stack.push(BlockKind::Switch);
261 Ok(())
262 }
263
264 fn begin_case(&mut self, _label: &str, taken: bool) -> Result<(), Self::Error> {
265 if !taken && !self.suppressed() {
266 self.suppress_depth = Some(self.depth);
267 }
268 self.block_stack.push(BlockKind::Case { indented: false });
270 Ok(())
271 }
272
273 fn end_case(&mut self) -> Result<(), Self::Error> {
274 debug_assert!(matches!(self.block_stack.pop(), Some(BlockKind::Case { .. })));
275 if self.suppress_depth == Some(self.depth) {
276 self.suppress_depth = None;
277 }
278 Ok(())
279 }
280
281 fn end_switch(&mut self) -> Result<(), Self::Error> {
282 debug_assert_eq!(self.block_stack.pop(), Some(BlockKind::Switch));
283 Ok(())
284 }
285
286 fn field_table(&mut self, table: &FieldTable<'_>) -> Result<(), Self::Error> {
289 if self.suppressed() {
290 return Ok(());
291 }
292 if table.rows.is_empty() {
293 return Ok(());
294 }
295
296 if table.columns.len() == 1 {
297 let col = &table.columns[0];
299 self.indent()?;
300 write!(self.writer, "{}: [", col.name)?;
301 for (i, row) in table.rows.iter().enumerate() {
302 if i > 0 {
303 write!(self.writer, ", ")?;
304 }
305 if let Some(val) = row.first() {
306 write!(self.writer, "{val}")?;
307 }
308 }
309 writeln!(self.writer, "]")?;
310 } else {
311 let mut widths: Vec<usize> = table.columns.iter().map(|c| c.name.len()).collect();
314 for row in table.rows {
315 for (i, val) in row.iter().enumerate() {
316 if i < widths.len() {
317 let val_len = format!("{val}").len();
318 if val_len > widths[i] {
319 widths[i] = val_len;
320 }
321 }
322 }
323 }
324
325 self.indent()?;
327 for (i, col) in table.columns.iter().enumerate() {
328 if i > 0 {
329 write!(self.writer, " ")?;
330 }
331 write!(self.writer, "{:>width$}", col.name, width = widths[i])?;
332 }
333 writeln!(self.writer)?;
334
335 for row in table.rows {
337 self.indent()?;
338 for (i, val) in row.iter().enumerate() {
339 if i > 0 {
340 write!(self.writer, " ")?;
341 }
342 let formatted = format!("{val}");
343 if i < widths.len() {
344 write!(self.writer, "{:>width$}", formatted, width = widths[i])?;
345 } else {
346 write!(self.writer, "{formatted}")?;
347 }
348 }
349 writeln!(self.writer)?;
350 }
351 }
352
353 Ok(())
354 }
355
356 fn assignment(
359 &mut self,
360 expression: &str,
361 computed_value: Option<&Value>,
362 ) -> Result<(), Self::Error> {
363 if self.suppressed() {
364 return Ok(());
365 }
366 self.indent()?;
367 match computed_value {
368 Some(val) => writeln!(self.writer, "{expression} = {val}")?,
369 None => writeln!(self.writer, "{expression}")?,
370 }
371 Ok(())
372 }
373
374 fn comment(&mut self, text: &str) -> Result<(), Self::Error> {
375 if self.suppressed() {
376 return Ok(());
377 }
378 self.indent()?;
379 writeln!(self.writer, "// {text}")?;
380 Ok(())
381 }
382
383 fn ellipsis(&mut self) -> Result<(), Self::Error> {
384 if self.suppressed() {
385 return Ok(());
386 }
387 self.indent()?;
388 writeln!(self.writer, "...")?;
389 Ok(())
390 }
391}