1use std::io;
2
3use crate::render::{format_hex_dump, format_term_annotations, write_indent, INDENT_WIDTH};
4use crate::types::{BitPatternField, FixedWidthField, TermAnnotation, Value, VariableLengthField};
5use crate::write::SyntaxWrite;
6
7#[derive(Debug)]
9pub struct TextRenderError(io::Error);
10
11impl std::fmt::Display for TextRenderError {
12 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
13 write!(f, "text render error: {}", self.0)
14 }
15}
16
17impl std::error::Error for TextRenderError {
18 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
19 Some(&self.0)
20 }
21}
22
23impl From<io::Error> for TextRenderError {
24 fn from(e: io::Error) -> Self {
25 TextRenderError(e)
26 }
27}
28
29struct FieldColumns {
32 width_col: usize,
34 descriptor_col: usize,
36 value_col: usize,
38}
39
40const COLUMNS: FieldColumns = FieldColumns {
42 width_col: 49,
43 descriptor_col: 58,
44 value_col: 70,
45};
46
47pub struct PlainTextRenderer<W> {
49 writer: W,
50 depth: usize,
51 block_stack: Vec<BlockKind>,
53}
54
55#[derive(Debug, Clone, Copy, PartialEq)]
56enum BlockKind {
57 Element,
58 If,
59 For,
60 While,
61 DoWhile,
62 Switch,
63 Case,
64}
65
66impl<W: io::Write> PlainTextRenderer<W> {
67 pub fn new(writer: W) -> Self {
68 PlainTextRenderer {
69 writer,
70 depth: 0,
71 block_stack: Vec::new(),
72 }
73 }
74
75 pub fn into_inner(self) -> W {
77 self.writer
78 }
79
80 fn indent(&mut self) -> io::Result<()> {
81 write_indent(&mut self.writer, self.depth)
82 }
83
84 fn current_indent_width(&self) -> usize {
85 self.depth * INDENT_WIDTH
86 }
87
88 fn write_fixed_field_line(
90 &mut self,
91 name: &str,
92 comment: Option<&str>,
93 bits: u32,
94 descriptor: &str,
95 value: Option<&Value>,
96 ) -> io::Result<()> {
97 self.indent()?;
98
99 let name_part = match comment {
101 Some(c) => format!("{name} /* {c} */"),
102 None => name.to_string(),
103 };
104
105 let indent_w = self.current_indent_width();
106 let name_end = indent_w + name_part.len();
107
108 let width_str = bits.to_string();
110 let padding1 = if name_end < COLUMNS.width_col {
111 COLUMNS.width_col - name_end
112 } else {
113 1
114 };
115 write!(self.writer, "{name_part}{:padding1$}{width_str}", "")?;
116
117 let width_end = COLUMNS.width_col + width_str.len();
119 let padding2 = if width_end < COLUMNS.descriptor_col {
120 COLUMNS.descriptor_col - width_end
121 } else {
122 1
123 };
124 write!(self.writer, "{:padding2$}{descriptor}", "")?;
125
126 if let Some(val) = value {
128 let desc_end = COLUMNS.descriptor_col + descriptor.len();
129 let padding3 = if desc_end < COLUMNS.value_col {
130 COLUMNS.value_col - desc_end
131 } else {
132 1
133 };
134 write!(self.writer, "{:padding3$}= {val}", "")?;
135 }
136
137 writeln!(self.writer)?;
138 Ok(())
139 }
140
141 fn write_variable_field_line(
143 &mut self,
144 name: &str,
145 comment: Option<&str>,
146 descriptor: &str,
147 value: Option<&Value>,
148 ) -> io::Result<()> {
149 self.indent()?;
150
151 let name_part = match comment {
152 Some(c) => format!("{name} /* {c} */"),
153 None => name.to_string(),
154 };
155
156 let indent_w = self.current_indent_width();
157 let name_end = indent_w + name_part.len();
158
159 let padding1 = if name_end < COLUMNS.descriptor_col {
161 COLUMNS.descriptor_col - name_end
162 } else {
163 1
164 };
165 write!(self.writer, "{name_part}{:padding1$}{descriptor}", "")?;
166
167 if let Some(val) = value {
168 let desc_end = COLUMNS.descriptor_col + descriptor.len();
169 let padding3 = if desc_end < COLUMNS.value_col {
170 COLUMNS.value_col - desc_end
171 } else {
172 1
173 };
174 write!(self.writer, "{:padding3$}= {val}", "")?;
175 }
176
177 writeln!(self.writer)?;
178 Ok(())
179 }
180}
181
182impl<W: io::Write> SyntaxWrite for PlainTextRenderer<W> {
183 type Error = TextRenderError;
184
185 fn begin_element(&mut self, name: &str, params: Option<&str>) -> Result<(), Self::Error> {
186 self.indent()?;
187 match params {
188 Some(p) => writeln!(self.writer, "{name}({p}) {{")?,
189 None => writeln!(self.writer, "{name}() {{")?,
190 }
191 self.depth += 1;
192 self.block_stack.push(BlockKind::Element);
193 Ok(())
194 }
195
196 fn end_element(&mut self) -> Result<(), Self::Error> {
197 debug_assert_eq!(self.block_stack.pop(), Some(BlockKind::Element));
198 self.depth -= 1;
199 self.indent()?;
200 writeln!(self.writer, "}}")?;
201 Ok(())
202 }
203
204 fn fixed_width_field(&mut self, field: &FixedWidthField<'_>) -> Result<(), Self::Error> {
205 self.write_fixed_field_line(
206 field.name,
207 field.comment,
208 field.bits,
209 field.descriptor,
210 field.value.as_ref(),
211 )?;
212 Ok(())
213 }
214
215 fn variable_length_field(
216 &mut self,
217 field: &VariableLengthField<'_>,
218 ) -> Result<(), Self::Error> {
219 self.write_variable_field_line(
220 field.name,
221 field.comment,
222 field.descriptor,
223 field.value.as_ref(),
224 )?;
225 Ok(())
226 }
227
228 fn bit_pattern(&mut self, field: &BitPatternField<'_>) -> Result<(), Self::Error> {
229 self.write_fixed_field_line(
230 field.name,
231 None,
232 field.bits,
233 field.descriptor,
234 Some(&field.value),
235 )?;
236 Ok(())
237 }
238
239 fn raw_bytes(&mut self, data: &[u8]) -> Result<(), Self::Error> {
240 let lines = format_hex_dump(data);
241 for line in &lines {
242 self.indent()?;
243 writeln!(self.writer, "{line}")?;
244 }
245 Ok(())
246 }
247
248 fn begin_if(
249 &mut self,
250 condition: &str,
251 terms: &[TermAnnotation<'_>],
252 _taken: bool,
253 ) -> Result<(), Self::Error> {
254 self.indent()?;
255 let annotations = format_term_annotations(terms);
256 writeln!(self.writer, "if ({condition}) {{{annotations}")?;
257 self.depth += 1;
258 self.block_stack.push(BlockKind::If);
259 Ok(())
260 }
261
262 fn begin_else_if(
263 &mut self,
264 condition: &str,
265 terms: &[TermAnnotation<'_>],
266 _taken: bool,
267 ) -> Result<(), Self::Error> {
268 debug_assert_eq!(self.block_stack.last(), Some(&BlockKind::If));
269 self.depth -= 1;
270 self.indent()?;
271 let annotations = format_term_annotations(terms);
272 writeln!(self.writer, "}} else if ({condition}) {{{annotations}")?;
273 self.depth += 1;
274 Ok(())
275 }
276
277 fn begin_else(&mut self, _taken: bool) -> Result<(), Self::Error> {
278 debug_assert_eq!(self.block_stack.last(), Some(&BlockKind::If));
279 self.depth -= 1;
280 self.indent()?;
281 writeln!(self.writer, "}} else {{")?;
282 self.depth += 1;
283 Ok(())
284 }
285
286 fn end_if(&mut self) -> Result<(), Self::Error> {
287 debug_assert_eq!(self.block_stack.pop(), Some(BlockKind::If));
288 self.depth -= 1;
289 self.indent()?;
290 writeln!(self.writer, "}}")?;
291 Ok(())
292 }
293
294 fn begin_for(
295 &mut self,
296 header: &str,
297 terms: &[TermAnnotation<'_>],
298 ) -> Result<(), Self::Error> {
299 self.indent()?;
300 let annotations = format_term_annotations(terms);
301 writeln!(self.writer, "for ({header}) {{{annotations}")?;
302 self.depth += 1;
303 self.block_stack.push(BlockKind::For);
304 Ok(())
305 }
306
307 fn for_iteration(&mut self, variable: &str, index: u64) -> Result<(), Self::Error> {
308 self.indent()?;
309 writeln!(self.writer, "/* {variable}: {index} */")?;
310 Ok(())
311 }
312
313 fn end_for(&mut self) -> Result<(), Self::Error> {
314 debug_assert_eq!(self.block_stack.pop(), Some(BlockKind::For));
315 self.depth -= 1;
316 self.indent()?;
317 writeln!(self.writer, "}}")?;
318 Ok(())
319 }
320
321 fn begin_while(&mut self, condition: &str) -> Result<(), Self::Error> {
322 self.indent()?;
323 writeln!(self.writer, "while ({condition}) {{")?;
324 self.depth += 1;
325 self.block_stack.push(BlockKind::While);
326 Ok(())
327 }
328
329 fn while_iteration(&mut self, index: u64) -> Result<(), Self::Error> {
330 self.indent()?;
331 writeln!(self.writer, "/* iteration: {index} */")?;
332 Ok(())
333 }
334
335 fn end_while(&mut self) -> Result<(), Self::Error> {
336 debug_assert_eq!(self.block_stack.pop(), Some(BlockKind::While));
337 self.depth -= 1;
338 self.indent()?;
339 writeln!(self.writer, "}}")?;
340 Ok(())
341 }
342
343 fn begin_do_while(&mut self) -> Result<(), Self::Error> {
344 self.indent()?;
345 writeln!(self.writer, "do {{")?;
346 self.depth += 1;
347 self.block_stack.push(BlockKind::DoWhile);
348 Ok(())
349 }
350
351 fn do_while_iteration(&mut self, index: u64) -> Result<(), Self::Error> {
352 self.indent()?;
353 writeln!(self.writer, "/* iteration: {index} */")?;
354 Ok(())
355 }
356
357 fn end_do_while(&mut self, condition: &str) -> Result<(), Self::Error> {
358 debug_assert_eq!(self.block_stack.pop(), Some(BlockKind::DoWhile));
359 self.depth -= 1;
360 self.indent()?;
361 writeln!(self.writer, "}} while ({condition})")?;
362 Ok(())
363 }
364
365 fn begin_switch(
366 &mut self,
367 expression: &str,
368 terms: &[TermAnnotation<'_>],
369 ) -> Result<(), Self::Error> {
370 self.indent()?;
371 let annotations = format_term_annotations(terms);
372 writeln!(self.writer, "switch ({expression}) {{{annotations}")?;
373 self.depth += 1;
374 self.block_stack.push(BlockKind::Switch);
375 Ok(())
376 }
377
378 fn begin_case(&mut self, label: &str, _taken: bool) -> Result<(), Self::Error> {
379 self.indent()?;
380 writeln!(self.writer, "case {label}:")?;
381 self.depth += 1;
382 self.block_stack.push(BlockKind::Case);
383 Ok(())
384 }
385
386 fn end_case(&mut self) -> Result<(), Self::Error> {
387 debug_assert_eq!(self.block_stack.pop(), Some(BlockKind::Case));
388 self.indent()?;
389 writeln!(self.writer, "break")?;
390 self.depth -= 1;
391 Ok(())
392 }
393
394 fn end_switch(&mut self) -> Result<(), Self::Error> {
395 debug_assert_eq!(self.block_stack.pop(), Some(BlockKind::Switch));
396 self.depth -= 1;
397 self.indent()?;
398 writeln!(self.writer, "}}")?;
399 Ok(())
400 }
401
402 fn assignment(
403 &mut self,
404 expression: &str,
405 computed_value: Option<&Value>,
406 ) -> Result<(), Self::Error> {
407 self.indent()?;
408 match computed_value {
409 Some(val) => writeln!(self.writer, "{expression}{:width$}/* = {val} */", "",
410 width = COLUMNS.value_col.saturating_sub(self.current_indent_width() + expression.len()))?,
411 None => writeln!(self.writer, "{expression}")?,
412 }
413 Ok(())
414 }
415
416 fn comment(&mut self, text: &str) -> Result<(), Self::Error> {
417 self.indent()?;
418 writeln!(self.writer, "/* {text} */")?;
419 Ok(())
420 }
421
422 fn ellipsis(&mut self) -> Result<(), Self::Error> {
423 self.indent()?;
424 writeln!(self.writer, "...")?;
425 Ok(())
426 }
427}