use crate::error::Result;
use crate::app::BuildState;
use crate::option::ModOption;
use crate::wiring::{impl_group_wiring_methods, impl_private_wiring_methods, impl_wiring_methods};
use std::fmt;
pub struct Module {
name: &'static str,
options: Vec<Box<dyn ModOption>>,
}
impl fmt::Debug for Module {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Module")
.field("name", &self.name)
.field("options", &self.options.len())
.finish()
}
}
impl Module {
#[must_use]
pub fn builder(name: &'static str) -> Self {
Self {
name,
options: Vec::new(),
}
}
fn push_option(&mut self, option: Box<dyn ModOption>) {
self.options.push(option);
}
#[must_use]
pub fn module(mut self, child: Module) -> Self {
self.push_option(child.into_option());
self
}
pub(crate) fn into_option(self) -> Box<dyn ModOption> {
Box::new(ModuleOption {
name: self.name,
options: self.options,
})
}
}
impl_wiring_methods!(Module);
impl_private_wiring_methods!(Module);
impl_group_wiring_methods!(Module);
struct ModuleOption {
name: &'static str,
options: Vec<Box<dyn ModOption>>,
}
impl ModOption for ModuleOption {
fn apply(self: Box<Self>, app: &mut BuildState) -> Result<()> {
let parent = app.current_scope;
let child = app.container.scopes_mut().child(parent, self.name);
app.current_scope = child;
let result = (|| {
for opt in self.options {
opt.apply(app)?;
}
Ok(())
})();
app.current_scope = parent;
result
}
}