tighterror_build/coder/
generator.rs1use crate::{
2 coder::{formatter::pretty, FrozenOptions, ALL_MODULES},
3 errors::TbError,
4 spec::Spec,
5};
6use proc_macro2::TokenStream;
7use quote::{format_ident, quote};
8
9mod bits;
10mod helpers;
11mod module;
12mod repr_type;
13
14use module::ModuleGenerator;
15
16#[derive(Debug)]
17pub struct ModuleCode {
18 pub(crate) name: String,
20 pub(crate) code: String,
22}
23
24struct RustGenerator<'a> {
25 opts: &'a FrozenOptions,
26 spec: &'a Spec,
27}
28
29impl<'a> RustGenerator<'a> {
30 fn new(opts: &'a FrozenOptions, spec: &'a Spec) -> RustGenerator<'a> {
31 Self { opts, spec }
32 }
33
34 fn rust(&self) -> Result<Vec<ModuleCode>, TbError> {
35 let mut ret = Vec::new();
36 let mut ts = TokenStream::default();
37 for m in &self.spec.modules {
38 let mod_doc = self.opts.separate_files || self.spec.modules.len() == 1;
39 let tokens = ModuleGenerator::new(self.opts, self.spec, m, mod_doc)?.rust()?;
40 if self.spec.modules.len() > 1 && !self.opts.separate_files {
41 let module_name = format_ident!("{}", m.name());
42 let module_doc = helpers::doc_tokens(m.doc());
43 ts = quote! {
44 #ts
45 #module_doc
46 pub mod #module_name {
47 #tokens
48 }
49 };
50 } else {
51 ret.push(ModuleCode {
52 name: m.name().into(),
53 code: pretty(tokens)?,
54 });
55 }
56 }
57 if ret.is_empty() {
58 let name = if self.spec.modules.len() > 1 {
59 ALL_MODULES.to_owned()
60 } else {
61 self.spec
62 .modules
63 .first()
64 .expect("at least one module is expected to exist at this point")
65 .name()
66 .to_owned()
67 };
68 ret.push(ModuleCode {
69 name,
70 code: pretty(ts)?,
71 });
72 }
73 Ok(ret)
74 }
75}
76
77pub fn spec_to_rust(opts: &FrozenOptions, spec: &Spec) -> Result<Vec<ModuleCode>, TbError> {
78 RustGenerator::new(opts, spec).rust()
79}