use std::collections::HashMap;
pub type Result<T> = std::result::Result<T, proc_macro2::TokenStream>;
pub trait Generator: Sync {
fn generate(
&self,
input: crate::component::ComponentInput,
manager: &Manager,
) -> Result<proc_macro2::TokenStream>;
fn boxed_clone(&self) -> Box<dyn Generator>;
}
pub struct Manager {
generators: HashMap<String, Box<dyn Generator>>,
}
impl Manager {
pub fn generate(
&self,
input: crate::component::ComponentInput,
) -> Result<proc_macro2::TokenStream> {
if let Some(generator) = self.generators.get(&input.name.to_string()) {
generator.generate(input, self)
} else {
Err(syn::Error::new(
input.name.span(),
format!("No generator for component: {}", input.name.to_string()),
)
.to_compile_error()
.into())
}
}
}
pub struct ManagerBuilder {
manager: Manager,
}
impl ManagerBuilder {
pub fn new() -> Self {
Self {
manager: Manager {
generators: Default::default(),
},
}
}
pub fn create<T>(mut self, name: impl Into<String>) -> Self
where
T: Generator + 'static + Default,
{
self.manager
.generators
.insert(name.into(), Box::new(T::default()));
self
}
pub fn add<T>(mut self, name: impl Into<String>, generator: T) -> Self
where
T: Generator + 'static,
{
self.manager
.generators
.insert(name.into(), Box::new(generator));
self
}
pub fn insert(mut self, manager: &Manager) -> Self {
for (k, v) in manager.generators.iter() {
self.manager
.generators
.insert(k.to_owned(), v.boxed_clone());
}
self
}
}
impl Into<Manager> for ManagerBuilder {
fn into(self) -> Manager {
self.manager
}
}