gbf_core/decompiler/ast/visitors/
emit_context.rs1#![deny(missing_docs)]
2
3use thiserror::Error;
4
5#[derive(Debug, Error)]
7pub enum EmitError {}
8
9#[derive(Debug, Clone, Copy, PartialEq, Eq)]
11pub enum EmitVerbosity {
12 Pretty,
14 Minified,
16 Debug,
18}
19
20#[derive(Debug, Clone, Copy, PartialEq, Eq)]
22pub enum IndentStyle {
23 Allman,
25 KAndR,
27}
28
29#[derive(Debug, Clone, Copy)]
31pub struct EmitContext {
32 pub indent: usize,
34 pub indent_step: usize,
36 pub format_number_hex: bool,
38 pub verbosity: EmitVerbosity,
40 pub indent_style: IndentStyle,
42 pub expr_root: bool,
44 pub include_ssa_versions: bool,
46}
47
48impl EmitContext {
49 pub fn scoped<F>(&mut self, action: F) -> Self
65 where
66 F: FnOnce(&mut Self) -> EmitContext,
67 {
68 action(self)
69 }
70
71 pub fn with_indent(&self) -> EmitContext {
84 let mut new_context = *self;
85 new_context.indent += self.indent_step;
86 new_context
87 }
88
89 pub fn with_expr_root(&self, expr_root: bool) -> EmitContext {
105 let mut new_context = *self;
106 new_context.expr_root = expr_root;
107 new_context
108 }
109
110 pub fn builder() -> EmitContextBuilder {
115 EmitContextBuilder::default()
116 }
117}
118
119#[derive(Debug, Clone)]
121pub struct EmitContextBuilder {
122 indent: usize,
123 indent_step: usize,
124 format_number_hex: bool,
125 verbosity: EmitVerbosity,
126 indent_style: IndentStyle,
127 expr_root: bool,
128 include_ssa_versions: bool,
129}
130
131impl EmitContextBuilder {
132 pub fn indent(mut self, indent: usize) -> Self {
134 self.indent = indent;
135 self
136 }
137
138 pub fn indent_step(mut self, indent_step: usize) -> Self {
140 self.indent_step = indent_step;
141 self
142 }
143
144 pub fn format_number_hex(mut self, format_number_hex: bool) -> Self {
146 self.format_number_hex = format_number_hex;
147 self
148 }
149
150 pub fn verbosity(mut self, verbosity: EmitVerbosity) -> Self {
152 self.verbosity = verbosity;
153 self
154 }
155
156 pub fn indent_style(mut self, indent_style: IndentStyle) -> Self {
158 self.indent_style = indent_style;
159 self
160 }
161
162 pub fn expr_root(mut self, expr_root: bool) -> Self {
164 self.expr_root = expr_root;
165 self
166 }
167
168 pub fn include_ssa_versions(mut self, include_ssa_versions: bool) -> Self {
170 self.include_ssa_versions = include_ssa_versions;
171 self
172 }
173
174 pub fn build(self) -> EmitContext {
176 EmitContext {
177 indent: self.indent,
178 indent_step: self.indent_step,
179 format_number_hex: self.format_number_hex,
180 verbosity: self.verbosity,
181 indent_style: self.indent_style,
182 expr_root: self.expr_root,
183 include_ssa_versions: self.include_ssa_versions,
184 }
185 }
186}
187
188impl Default for EmitContextBuilder {
191 fn default() -> Self {
192 Self {
193 indent: 0,
194 indent_step: 4,
195 format_number_hex: false,
196 verbosity: EmitVerbosity::Pretty,
197 indent_style: IndentStyle::Allman,
198 expr_root: true,
199 include_ssa_versions: false,
200 }
201 }
202}
203
204impl Default for EmitContext {
205 fn default() -> Self {
206 EmitContextBuilder::default().build()
207 }
208}
209
210#[cfg(test)]
211mod tests {
212 use super::*;
213
214 #[test]
215 fn test_emit_context_with_indent() {
216 let context = EmitContext::default();
217 let new_context = context.with_indent();
218 assert_eq!(new_context.indent, 4);
219 }
220
221 #[test]
222 fn test_emit_context_scoped() {
223 let mut context = EmitContext::default();
224 let body_context = context.scoped(|ctx| ctx.with_indent());
225 assert_eq!(body_context.indent, 4);
226 }
227
228 #[test]
229 fn test_builder_default_values() {
230 let builder = EmitContext::builder();
231 let context = builder.build();
232 assert_eq!(context.indent, 0);
233 assert_eq!(context.indent_step, 4);
234 assert!(!context.format_number_hex);
235 assert_eq!(context.verbosity, EmitVerbosity::Pretty);
236 assert_eq!(context.indent_style, IndentStyle::Allman);
237 }
238
239 #[test]
240 fn test_builder_custom_values() {
241 let context = EmitContext::builder()
242 .indent(2)
243 .indent_step(8)
244 .format_number_hex(true)
245 .verbosity(EmitVerbosity::Debug)
246 .indent_style(IndentStyle::KAndR)
247 .expr_root(true)
248 .include_ssa_versions(true)
249 .build();
250 assert_eq!(context.indent, 2);
251 assert_eq!(context.indent_step, 8);
252 assert!(context.format_number_hex);
253 assert_eq!(context.verbosity, EmitVerbosity::Debug);
254 assert_eq!(context.indent_style, IndentStyle::KAndR);
255 assert!(context.expr_root);
256 assert!(context.include_ssa_versions);
257 }
258}