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
43impl Default for Asn1Compiler {
44 fn default() -> Self {
45 Asn1Compiler::new("default.rs", &Visibility::Public, vec![Codec::Aper], vec![])
46 }
47}
48
49impl Asn1Compiler {
50 pub fn new(
52 output: &str,
53 visibility: &Visibility,
54 codecs: Vec<Codec>,
55 derives: Vec<Derive>,
56 ) -> Self {
57 Asn1Compiler {
58 modules: HashMap::new(),
59 resolver: Resolver::new(),
60 generator: Generator::new(visibility, codecs, derives), output_filename: output.to_string(),
62 }
63 }
64
65 pub fn add_module(&mut self, module: Asn1Module) -> bool {
69 log::debug!("Adding module: {}", module.get_module_name());
70 self.modules
71 .insert(module.get_module_name(), module)
72 .is_some()
73 }
74
75 pub fn resolve_modules(&mut self) -> Result<()> {
84 log::info!("Resolving imports from all modules.");
85 self.resolve_imports()?;
86
87 log::info!("Resolving definitions from all modules.");
88 self.resolve_definitions()
89 }
90
91 pub fn generate(&mut self) -> Result<()> {
93 log::info!("Generating code, writing to file: {}", self.output_filename);
94
95 let input_text = self.generator.generate(&self.resolver)?;
96 let output_text = self.rustfmt_generated_code(&input_text)?;
97
98 let mut output_file = File::create(&self.output_filename).map_err(|e| {
99 let errorstr = format!("Error {} Creating File: {}", e, self.output_filename);
100 Error::CodeGenerationError(errorstr)
101 })?;
102
103 output_file
104 .write_all(output_text.as_bytes())
105 .map_err(|e| Error::CodeGenerationError(e.to_string()))?;
106
107 eprintln!("\n\nWrote generated code to '{}'.", self.output_filename);
108
109 Ok(())
110 }
111
112 pub fn compile_string(&mut self, modules_string: &str, parse_only: bool) -> Result<()> {
114 let mut tokens = crate::tokenizer::tokenize_string(modules_string)?;
115 self.parse_tokens_into_modules(&mut tokens)?;
116 if !parse_only {
117 self.resolve_modules()?;
118 self.generate()
119 } else {
120 Ok(())
121 }
122 }
123
124 pub fn compile_files<T: AsRef<Path> + std::fmt::Debug>(&mut self, files: &[T]) -> Result<()> {
126 for file in files {
127 log::info!("Processing file: {:?}", file);
128 let file = File::open(file).map_err(|e| io_error!("{:#?}", e))?;
129 let mut tokens = crate::tokenizer::tokenize(file)?;
130 self.parse_tokens_into_modules(&mut tokens)?;
131 }
132 self.resolve_modules()?;
133
134 self.generate()
135 }
136
137 fn parse_tokens_into_modules(&mut self, tokens: &mut Vec<Token>) -> Result<()> {
138 log::debug!("Parsing {} tokens.", tokens.len());
139 let mut modules = crate::parser::parse(tokens)?;
140 loop {
141 let module = modules.pop();
142 if module.is_none() {
143 break;
144 }
145 let module = module.unwrap();
146 log::debug!("Adding module : {}", module.get_module_name());
147 self.add_module(module);
148 }
149 Ok(())
150 }
151
152 fn rustfmt_generated_code(&self, code: &str) -> Result<String> {
153 log::debug!("Runing `rustfmt` on the generated code.");
154 let rustfmt_binary = "rustfmt"; let mut cmd = Command::new(rustfmt_binary);
156
157 cmd.stdin(Stdio::piped()).stdout(Stdio::piped());
158
159 let mut child = cmd.spawn().map_err(|e| resolve_error!("{:#?}", e))?;
160 let mut child_stdin = child.stdin.take().unwrap();
161 let mut child_stdout = child.stdout.take().unwrap();
162
163 let code = code.to_owned();
164 let stdin_handle =
165 ::std::thread::spawn(move || match child_stdin.write_all(code.as_bytes()) {
166 Ok(_) => code,
167 Err(_) => "write error in rustfmt".to_owned(),
168 });
169
170 let mut output = vec![];
171 io::copy(&mut child_stdout, &mut output).map_err(|e| resolve_error!("{:#?}", e))?;
172
173 let status = child.wait().map_err(|e| resolve_error!("{:#?}", e))?;
174
175 match String::from_utf8(output) {
176 Ok(formatted_output) => match status.code() {
177 Some(0) => Ok(formatted_output),
178 _ => Err(resolve_error!("`rustfmt` failed to write some bindings.").into()),
179 },
180 _ => Ok(stdin_handle.join().unwrap()),
181 }
182 }
183
184 fn resolve_imports(&self) -> Result<()> {
185 log::debug!("Resolving imports.");
186 for (_, module) in self.modules.iter() {
187 for (import, module_name) in module.get_imported_defs() {
188 let target = self.modules.get(module_name.name_as_str());
189 if target.is_none() {
190 return Err(resolve_error!(
191 "Module '{}', corresponding to definition '{}' not found!",
192 module_name.name_as_str(),
193 import
194 )
195 .into());
196 }
197 }
198 }
199
200 log::debug!("All IMPORTS in All Modules Resolved!");
201 Ok(())
202 }
203
204 fn sorted_modules(&self) -> Vec<String> {
205 log::trace!("Topologically sorting modules.");
206 let mut ts = TopologicalSort::<String>::new();
207
208 for module in self.modules.values() {
209 let imports = module.get_imported_defs();
210 for (_, m) in imports {
211 ts.add_dependency(m.name(), module.get_module_name())
212 }
213 ts.insert(module.get_module_name());
214 }
215
216 let mut out_vec = vec![];
217 loop {
218 let popped = ts.pop_all();
219 if popped.is_empty() {
220 break;
221 } else {
222 out_vec.extend(popped);
223 }
224 }
225 out_vec
226 }
227
228 fn resolve_definitions(&mut self) -> Result<()> {
229 let module_names = self.sorted_modules();
230 for name in module_names {
231 let module = self.modules.get_mut(&name).unwrap();
232
233 self.resolver.resolve_definitions(module)?;
235 }
236 log::trace!(
237 "Resolved Definitions: {:#?}",
238 self.resolver.resolved_defs.keys()
239 );
240 log::trace!(
241 "Parameterized Types: {:#?}",
242 self.resolver.parameterized_defs.keys()
243 );
244 log::trace!("Object Classes: {:#?}", self.resolver.classes.keys());
245
246 Ok(())
247 }
248}