asn1_compiler/
compiler.rs1#![allow(dead_code)]
2use std::collections::HashMap;
5use std::fs::File;
6use std::io;
7use std::io::Write;
8use std::path::Path;
9use std::process::{Command, Stdio};
10
11use topological_sort::TopologicalSort;
12
13use crate::error::Error;
14use anyhow::Result;
15
16use crate::parser::asn::structs::module::Asn1Module;
17
18use crate::generator::{Codec, Derive, Generator, Visibility};
19use crate::resolver::Resolver;
20use crate::tokenizer::Token;
21
22#[derive(Debug)]
27pub struct Asn1Compiler {
28 modules: HashMap<String, Asn1Module>,
32
33 resolver: Resolver,
35
36 generator: Generator,
38
39 output_filename: String,
41
42 rustfmt_generated_code: bool,
44}
45
46impl Default for Asn1Compiler {
47 fn default() -> Self {
48 Asn1Compiler::new("default.rs", &Visibility::Public, vec![Codec::Aper], vec![])
49 }
50}
51
52impl Asn1Compiler {
53 pub fn new(
55 output: &str,
56 visibility: &Visibility,
57 codecs: Vec<Codec>,
58 derives: Vec<Derive>,
59 ) -> Self {
60 Asn1Compiler {
61 modules: HashMap::new(),
62 resolver: Resolver::new(),
63 generator: Generator::new(visibility, codecs, derives), output_filename: output.to_string(),
65 rustfmt_generated_code: true,
66 }
67 }
68
69 pub fn add_module(&mut self, module: Asn1Module) -> bool {
73 log::debug!("Adding module: {}", module.get_module_name());
74 self.modules
75 .insert(module.get_module_name(), module)
76 .is_some()
77 }
78
79 pub fn set_rustfmt_generated_code(&mut self, rustfmt_generated_code: bool) {
86 self.rustfmt_generated_code = rustfmt_generated_code;
87 }
88
89 pub fn resolve_modules(&mut self) -> Result<()> {
98 log::info!("Resolving imports from all modules.");
99 self.resolve_imports()?;
100
101 log::info!("Resolving definitions from all modules.");
102 self.resolve_definitions()
103 }
104
105 pub fn generate(&mut self) -> Result<()> {
107 log::info!("Generating code, writing to file: {}", self.output_filename);
108
109 let input_text = self.generator.generate(&self.resolver)?;
110
111 let output_text = if self.rustfmt_generated_code {
112 self.rustfmt_generated_code(&input_text)?
113 } else {
114 input_text
115 };
116
117 let mut output_file = File::create(&self.output_filename).map_err(|e| {
118 let errorstr = format!("Error {} Creating File: {}", e, self.output_filename);
119 Error::CodeGenerationError(errorstr)
120 })?;
121
122 output_file
123 .write_all(output_text.as_bytes())
124 .map_err(|e| Error::CodeGenerationError(e.to_string()))?;
125
126 eprintln!("\n\nWrote generated code to '{}'.", self.output_filename);
127
128 Ok(())
129 }
130
131 pub fn compile_string(&mut self, modules_string: &str, parse_only: bool) -> Result<()> {
133 let mut tokens = crate::tokenizer::tokenize_string(modules_string)?;
134 self.parse_tokens_into_modules(&mut tokens)?;
135 if !parse_only {
136 self.resolve_modules()?;
137 self.generate()
138 } else {
139 Ok(())
140 }
141 }
142
143 pub fn compile_files<T: AsRef<Path> + std::fmt::Debug>(&mut self, files: &[T]) -> Result<()> {
145 for file in files {
146 log::info!("Processing file: {:?}", file);
147 let file = File::open(file).map_err(|e| io_error!("{:#?}", e))?;
148 let mut tokens = crate::tokenizer::tokenize(file)?;
149 self.parse_tokens_into_modules(&mut tokens)?;
150 }
151 self.resolve_modules()?;
152
153 self.generate()
154 }
155
156 fn parse_tokens_into_modules(&mut self, tokens: &mut Vec<Token>) -> Result<()> {
157 log::debug!("Parsing {} tokens.", tokens.len());
158 let mut modules = crate::parser::parse(tokens)?;
159 loop {
160 let module = modules.pop();
161 if module.is_none() {
162 break;
163 }
164 let module = module.unwrap();
165 log::debug!("Adding module : {}", module.get_module_name());
166 self.add_module(module);
167 }
168 Ok(())
169 }
170
171 fn rustfmt_generated_code(&self, code: &str) -> Result<String> {
172 log::debug!("Runing `rustfmt` on the generated code.");
173 let rustfmt_binary = "rustfmt"; let mut cmd = Command::new(rustfmt_binary);
175
176 cmd.stdin(Stdio::piped()).stdout(Stdio::piped());
177
178 let mut child = cmd.spawn().map_err(|e| resolve_error!("{:#?}", e))?;
179 let mut child_stdin = child.stdin.take().unwrap();
180 let mut child_stdout = child.stdout.take().unwrap();
181
182 let code = code.to_owned();
183 let stdin_handle =
184 ::std::thread::spawn(move || match child_stdin.write_all(code.as_bytes()) {
185 Ok(_) => code,
186 Err(_) => "write error in rustfmt".to_owned(),
187 });
188
189 let mut output = vec![];
190 io::copy(&mut child_stdout, &mut output).map_err(|e| resolve_error!("{:#?}", e))?;
191
192 let status = child.wait().map_err(|e| resolve_error!("{:#?}", e))?;
193
194 match String::from_utf8(output) {
195 Ok(formatted_output) => match status.code() {
196 Some(0) => Ok(formatted_output),
197 _ => Err(resolve_error!("`rustfmt` failed to write some bindings.").into()),
198 },
199 _ => Ok(stdin_handle.join().unwrap()),
200 }
201 }
202
203 fn resolve_imports(&self) -> Result<()> {
204 log::debug!("Resolving imports.");
205 for (_, module) in self.modules.iter() {
206 for (import, module_name) in module.get_imported_defs() {
207 let target = self.modules.get(module_name.name_as_str());
208 if target.is_none() {
209 return Err(resolve_error!(
210 "Module '{}', corresponding to definition '{}' not found!",
211 module_name.name_as_str(),
212 import
213 )
214 .into());
215 }
216 }
217 }
218
219 log::debug!("All IMPORTS in All Modules Resolved!");
220 Ok(())
221 }
222
223 fn sorted_modules(&self) -> Vec<String> {
224 log::trace!("Topologically sorting modules.");
225 let mut ts = TopologicalSort::<String>::new();
226
227 for module in self.modules.values() {
228 let imports = module.get_imported_defs();
229 for (_, m) in imports {
230 ts.add_dependency(m.name(), module.get_module_name())
231 }
232 ts.insert(module.get_module_name());
233 }
234
235 let mut out_vec = vec![];
236 loop {
237 let popped = ts.pop_all();
238 if popped.is_empty() {
239 break;
240 } else {
241 out_vec.extend(popped);
242 }
243 }
244 out_vec
245 }
246
247 fn resolve_definitions(&mut self) -> Result<()> {
248 let module_names = self.sorted_modules();
249 for name in module_names {
250 let module = self.modules.get_mut(&name).unwrap();
251
252 self.resolver.resolve_definitions(module)?;
254 }
255 log::trace!(
256 "Resolved Definitions: {:#?}",
257 self.resolver.resolved_defs.keys()
258 );
259 log::trace!(
260 "Parameterized Types: {:#?}",
261 self.resolver.parameterized_defs.keys()
262 );
263 log::trace!("Object Classes: {:#?}", self.resolver.classes.keys());
264
265 Ok(())
266 }
267}