pub use super::Component;
use crate::{
application::{self, Application},
error::{FrameworkError, FrameworkErrorKind::ComponentError},
shutdown::Shutdown,
};
use std::{any::Any, borrow::Borrow, collections::HashSet, slice};
#[derive(Debug)]
pub struct Registry<A: Application> {
components: Vec<Box<dyn Component<A>>>,
}
impl<A> Default for Registry<A>
where
A: Application,
{
fn default() -> Self {
Registry { components: vec![] }
}
}
impl<A> Registry<A>
where
A: Application,
{
pub fn register<I>(&mut self, components: I) -> Result<(), FrameworkError>
where
I: IntoIterator<Item = Box<dyn Component<A>>>,
{
ensure!(
self.components.is_empty(),
ComponentError,
"no support for registering additional components (yet)"
);
let mut result = Registry {
components: components.into_iter().collect::<Vec<_>>(),
};
let mut names = HashSet::new();
for component in &result.components {
ensure!(
names.insert(component.name()),
ComponentError,
"duplicate component name: {}",
component.name()
);
}
result.sort();
Ok(())
}
pub fn after_config(&mut self, config: &A::Cfg) -> Result<(), FrameworkError> {
for component in self.iter_mut() {
component.after_config(config)?;
}
Ok(())
}
pub fn iter(&mut self) -> slice::Iter<Box<dyn Component<A>>> {
self.components.iter()
}
pub fn iter_mut(&mut self) -> slice::IterMut<Box<dyn Component<A>>> {
self.components.iter_mut()
}
pub fn shutdown(&self, app: &A, shutdown: Shutdown) -> Result<(), FrameworkError> {
for component in self.components.iter().rev() {
component.before_shutdown(shutdown)?;
}
Ok(())
}
fn sort(&mut self) {
self.components.sort_by(|a, b| {
a.partial_cmp(b)
.unwrap_or_else(|| application::exit::bad_component_order(a.borrow(), b.borrow()))
})
}
}
impl<A> Registry<A>
where
A: Application + 'static,
{
pub fn get_ref<C>(&self) -> Option<&C>
where
C: Component<A> + 'static,
{
for component in self.components.iter() {
if let Some(result) = (component as &dyn Any).downcast_ref::<C>() {
return Some(result);
}
}
None
}
pub fn get_mut<C>(&mut self) -> Option<&mut C>
where
C: Component<A> + 'static,
{
for component in self.components.iter_mut() {
if let Some(result) = (component as &mut dyn Any).downcast_mut::<C>() {
return Some(result);
}
}
None
}
}