mpeg_syntax_dump/write.rs
1use crate::types::{
2 BitPatternField, FieldTable, FixedWidthField, TermAnnotation, Value, VariableLengthField,
3};
4
5/// Trait for rendering MPEG specification syntax structures.
6///
7/// Renderers implement this trait to produce output in a specific format
8/// (plain text, ANSI-colored text, HTML, etc.). Producers call these
9/// methods to describe the syntax structure and field values.
10///
11/// Methods use `begin_`/`end_` pairs rather than closures to avoid
12/// borrow-checker issues when the producer needs `&mut W` inside a
13/// closure while also borrowing `&self` for data access.
14pub trait SyntaxWrite {
15 type Error: std::error::Error;
16
17 // ── Element blocks ──────────────────────────────────────
18
19 /// Begin a named syntax element (a "syntax table" in MPEG specs).
20 ///
21 /// `params` is `None` for unparameterized elements like `transport_packet()`,
22 /// or `Some("payloadType, payloadSize")` for parameterized ones like
23 /// `sei_payload(payloadType, payloadSize)`.
24 fn begin_element(&mut self, name: &str, params: Option<&str>)
25 -> Result<(), Self::Error>;
26
27 /// End the current syntax element.
28 fn end_element(&mut self) -> Result<(), Self::Error>;
29
30 // ── Fields ──────────────────────────────────────────────
31
32 /// Render a fixed-width field.
33 fn fixed_width_field(&mut self, field: &FixedWidthField<'_>)
34 -> Result<(), Self::Error>;
35
36 /// Render a variable-length coded field.
37 fn variable_length_field(&mut self, field: &VariableLengthField<'_>)
38 -> Result<(), Self::Error>;
39
40 /// Render a fixed bit pattern or marker bit.
41 fn bit_pattern(&mut self, field: &BitPatternField<'_>)
42 -> Result<(), Self::Error>;
43
44 // ── Raw byte hex dump ───────────────────────────────────
45
46 /// Render raw bytes as a hex dump. Called after a field template line;
47 /// the renderer formats as hex lines (16 bytes per line).
48 fn raw_bytes(&mut self, data: &[u8]) -> Result<(), Self::Error>;
49
50 // ── Conditionals ────────────────────────────────────────
51
52 /// Begin an `if` block. The renderer adds `if (condition) {` and any
53 /// term annotations. `taken` is a hint for dimming not-taken branches.
54 fn begin_if(&mut self, condition: &str,
55 terms: &[TermAnnotation<'_>], taken: bool)
56 -> Result<(), Self::Error>;
57
58 /// Close the previous branch and open an `else if` branch.
59 fn begin_else_if(&mut self, condition: &str,
60 terms: &[TermAnnotation<'_>], taken: bool)
61 -> Result<(), Self::Error>;
62
63 /// Close the previous branch and open an `else` branch.
64 fn begin_else(&mut self, taken: bool)
65 -> Result<(), Self::Error>;
66
67 /// Close the final branch of an if/else-if/else chain.
68 fn end_if(&mut self) -> Result<(), Self::Error>;
69
70 // ── For loops ───────────────────────────────────────────
71
72 /// Begin a `for` loop. `header` is the loop clause, e.g.
73 /// `"i = 0; i < N; i++"`. The renderer adds `for (header) {`.
74 fn begin_for(&mut self, header: &str,
75 terms: &[TermAnnotation<'_>])
76 -> Result<(), Self::Error>;
77
78 /// Mark a for-loop iteration with the variable name and index.
79 fn for_iteration(&mut self, variable: &str, index: u64)
80 -> Result<(), Self::Error>;
81
82 /// End a `for` loop.
83 fn end_for(&mut self) -> Result<(), Self::Error>;
84
85 // ── While loops ─────────────────────────────────────────
86
87 /// Begin a `while` loop.
88 fn begin_while(&mut self, condition: &str)
89 -> Result<(), Self::Error>;
90
91 /// Mark a while-loop iteration.
92 fn while_iteration(&mut self, index: u64)
93 -> Result<(), Self::Error>;
94
95 /// End a `while` loop.
96 fn end_while(&mut self) -> Result<(), Self::Error>;
97
98 // ── Do-while loops ──────────────────────────────────────
99
100 /// Begin a `do-while` loop.
101 fn begin_do_while(&mut self) -> Result<(), Self::Error>;
102
103 /// Mark a do-while iteration.
104 fn do_while_iteration(&mut self, index: u64)
105 -> Result<(), Self::Error>;
106
107 /// End a `do-while` loop with the given condition.
108 fn end_do_while(&mut self, condition: &str)
109 -> Result<(), Self::Error>;
110
111 // ── Switch/case ────────────────────────────────────────
112
113 /// Begin a `switch` statement. `expression` is the switch discriminator,
114 /// e.g. `"id"`. `terms` provides term annotations for the discriminator.
115 fn begin_switch(&mut self, expression: &str,
116 terms: &[TermAnnotation<'_>]) -> Result<(), Self::Error>;
117
118 /// Begin a `case` within a switch. `label` is the case label,
119 /// e.g. `"ID_CPE"`. `taken` indicates whether this is the active case.
120 fn begin_case(&mut self, label: &str, taken: bool)
121 -> Result<(), Self::Error>;
122
123 /// End the current case.
124 fn end_case(&mut self) -> Result<(), Self::Error>;
125
126 /// End the switch statement.
127 fn end_switch(&mut self) -> Result<(), Self::Error>;
128
129 // ── Field tables ──────────────────────────────────────────
130
131 /// Render a table of homogeneous field values from a loop.
132 ///
133 /// The default implementation expands the table into a `for` loop with
134 /// one iteration per row. Compact renderers override this to produce
135 /// inline lists or aligned tables.
136 fn field_table(&mut self, table: &FieldTable<'_>) -> Result<(), Self::Error> {
137 let n = table.rows.len();
138 let header = if table.columns.len() == 1 {
139 format!("i = 0; i < {n}; i++")
140 } else {
141 format!("i = 0; i < {n}; i++")
142 };
143 self.begin_for(&header, &[])?;
144 for (i, row) in table.rows.iter().enumerate() {
145 self.for_iteration("i", i as u64)?;
146 for (col_idx, col) in table.columns.iter().enumerate() {
147 if let Some(val) = row.get(col_idx) {
148 let name = format!("{}[{i}]", col.name);
149 match col.bits {
150 Some(bits) => self.fixed_width_field(&FixedWidthField {
151 name: &name,
152 bits,
153 descriptor: col.descriptor,
154 value: Some(val.clone()),
155 comment: None,
156 })?,
157 None => self.variable_length_field(&VariableLengthField {
158 name: &name,
159 descriptor: col.descriptor,
160 value: Some(val.clone()),
161 comment: None,
162 })?,
163 }
164 }
165 }
166 }
167 self.end_for()
168 }
169
170 // ── Assignments ─────────────────────────────────────────
171
172 /// Render an inline variable assignment. `computed_value` of `Some(value)`
173 /// renders a trailing `/* = value */` annotation.
174 fn assignment(&mut self, expression: &str,
175 computed_value: Option<&Value>) -> Result<(), Self::Error>;
176
177 // ── Comments and ellipsis ───────────────────────────────
178
179 /// Render a standalone comment line.
180 fn comment(&mut self, text: &str) -> Result<(), Self::Error>;
181
182 /// Render an ellipsis (`...`) indicating omitted content.
183 fn ellipsis(&mut self) -> Result<(), Self::Error>;
184}