brisk_it/
generator.rs

1//! Traits and structure used for generating the imperative representation from the declartive representation.
2
3use std::collections::HashMap;
4
5/// Result type, which return a token stream with the error
6pub type Result<T> = std::result::Result<T, proc_macro2::TokenStream>;
7
8/// Implement this trait to convert a ComponentInput into its imperative form.
9pub trait Generator: Sync {
10    /// Generate the imperative form.
11    fn generate(
12        &self,
13        input: crate::component::ComponentInput,
14        manager: &Manager,
15    ) -> Result<proc_macro2::TokenStream>;
16    /// Clone this generator
17    fn boxed_clone(&self) -> Box<dyn Generator>;
18}
19
20/// A `Manager` contains a list of generator that can be used by `brisk_it` to generate the code.
21pub struct Manager {
22    generators: HashMap<String, Box<dyn Generator>>,
23}
24
25impl Manager {
26    /// Generate the given component
27    pub fn generate(
28        &self,
29        input: crate::component::ComponentInput,
30    ) -> Result<proc_macro2::TokenStream> {
31        if let Some(generator) = self.generators.get(&input.name.to_string()) {
32            generator.generate(input, self)
33        } else {
34            Err(syn::Error::new(
35                input.name.span(),
36                format!("No generator for component: {}", input.name.to_string()),
37            )
38            .to_compile_error()
39            .into())
40        }
41    }
42}
43
44/// Used to initialise a manager
45pub struct ManagerBuilder {
46    manager: Manager,
47}
48
49impl ManagerBuilder {
50    /// Create an empty builder
51    pub fn new() -> Self {
52        Self {
53            manager: Manager {
54                generators: Default::default(),
55            },
56        }
57    }
58    /// Create a generator and add it to the builder
59    pub fn create<T>(mut self, name: impl Into<String>) -> Self
60    where
61        T: Generator + 'static + Default,
62    {
63        self.manager
64            .generators
65            .insert(name.into(), Box::new(T::default()));
66        self
67    }
68    /// Add a generator to the builder
69    pub fn add<T>(mut self, name: impl Into<String>, generator: T) -> Self
70    where
71        T: Generator + 'static,
72    {
73        self.manager
74            .generators
75            .insert(name.into(), Box::new(generator));
76        self
77    }
78    ///
79    pub fn insert(mut self, manager: &Manager) -> Self {
80        for (k, v) in manager.generators.iter() {
81            self.manager
82                .generators
83                .insert(k.to_owned(), v.boxed_clone());
84        }
85        self
86    }
87}
88
89impl Into<Manager> for ManagerBuilder {
90    fn into(self) -> Manager {
91        self.manager
92    }
93}