tighterror_build/coder/
generator.rs

1use 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    /// The module name
19    pub(crate) name: String,
20    /// The module code
21    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}