Hi everybody,
I have currently a working code that register struct init function inside a singleton, to allow building when required.
Here the current code
pub trait ComponentBuilder: Send + Sync where Self: 'static {
fn new() -> Box<dyn ComponentBuilder> where Self: Default {
Box::new(Self::default())
}
// Some other functions...
fn build(&self) -> Result<Box<dyn Component>, CustomError>;
}
static REGISTERED_COMPONENT_BUILDERS: Mutex<Vec<fn() -> Box<dyn ComponentBuilder>>> = Mutex::new(Vec::new());
pub fn register_new_component_builder(builder: fn() -> Box<dyn ComponentBuilder>) -> Result<(), CustomError> {
match REGISTERED_COMPONENT_BUILDERS.lock() {
Ok(mut builders) => {
if is_builder_registered(builder().get_id(), builders.as_ref()) {
Err(CustomError::from(ErrorType::BuilderAlreadyRegistered))
} else {
builders.push(builder);
Ok(())
}
}
Err(error) => {
Err(CustomError::from(error))
}
}
}
fn is_builder_registered(id: String, builders: &Vec<fn() -> Box<dyn ComponentBuilder>>) -> bool {
builders.iter().any(|b| b().get_id() == id)
}
pub fn get_builder_for_id(id: String) -> Result<Option<Box<dyn ComponentBuilder>>, CustomError> {
match REGISTERED_COMPONENT_BUILDERS.lock() {
Ok(builders) => Ok(builders.iter().map(|b| b()).find(|b| b.get_id() == id)),
Err(error) => Err(CustomError::from(error)),
}
}
// In main.rs :
fn register_components() {
register_component(FirstExampleBuilder::new);
register_component(SecondExampleBuilder::new);
register_component(ThirdExampleBuilder::new);
}
fn register_component(builder: fn() -> Box<dyn ComponentBuilder>) {
let builder_id = builder().get_id();
if let Err(error) = component_builder::register_new_component_builder(builder) {
warn!("Could not register component '{builder_id}' : {error}");
}
}
I want to make a more concise code. A simple way to register each struct implementing the ComponentBuilder
trait.
I was thinkg about macro (attribute-like maybe ?), but I have never write it, and I'm not sure this can resolve my problem.
I've understand that macro will be replaced with code, so the code must be called at a moment.
So do you have any ideo how to simplify this ? Or is too complex and I must let the code as is ?
Thanks by advance !