use super::{handle::Handle, id::Id, Component};
use crate::{
application::{self, Application},
shutdown::Shutdown,
FrameworkError,
FrameworkErrorKind::ComponentError,
Map,
};
use std::{any::TypeId, borrow::Borrow, slice, sync};
pub type Iter<'a, A> = slice::Iter<'a, Box<dyn Component<A>>>;
pub type IterMut<'a, A> = slice::IterMut<'a, Box<dyn Component<A>>>;
pub type Reader<'a, A> = sync::RwLockReadGuard<'a, Registry<A>>;
pub type Writer<'a, A> = sync::RwLockWriteGuard<'a, Registry<A>>;
type IdMap = Map<Id, Index>;
type TypeMap = Map<TypeId, Index>;
#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
pub struct Index(usize);
#[derive(Debug, Default)]
pub struct Registry<A: Application + 'static> {
components: Vec<Box<dyn Component<A>>>,
id_map: IdMap,
type_map: TypeMap,
}
impl<A> Registry<A>
where
A: Application + 'static,
{
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 components = components.into_iter().collect::<Vec<_>>();
components.sort_by(|a, b| {
a.partial_cmp(b)
.unwrap_or_else(|| application::exit::bad_component_order(a.borrow(), b.borrow()))
});
for component in components {
self.register_component(component)?;
}
Ok(())
}
pub fn after_config(&mut self, config: &A::Cfg) -> Result<(), FrameworkError> {
let mut component_indexes: Vec<(Index, Vec<Index>)> = vec![];
for (index, component) in self.components.iter_mut().enumerate() {
component.after_config(config)?;
let mut dep_indexes = vec![];
for id in component.dependencies() {
if let Some(index) = self.id_map.get(id) {
dep_indexes.push(*index);
} else {
fail!(ComponentError, "unregistered dependency ID: {}", id);
}
}
component_indexes.push((Index(index), dep_indexes));
}
for (component_index, dep_indexes) in component_indexes {
for dep_index in dep_indexes {
if let (Some(component), Some(dep)) = self.get2_mut(component_index, dep_index) {
let dep_handle = Handle::new(dep.id(), dep_index);
component.register_dependency(dep_handle, dep.as_mut())?;
} else {
unreachable!();
}
}
}
Ok(())
}
pub fn len(&self) -> usize {
self.components.len()
}
pub fn is_empty(&self) -> bool {
self.components.is_empty()
}
pub fn get(&self, handle: Handle) -> Option<&dyn Component<A>> {
self.components.get(handle.index.0).map(AsRef::as_ref)
}
pub fn get_mut(&mut self, handle: Handle) -> Option<&mut (dyn Component<A> + 'static)> {
self.components.get_mut(handle.index.0).map(AsMut::as_mut)
}
pub fn get_handle_by_id(&self, id: Id) -> Option<Handle> {
Some(Handle::new(id, *self.id_map.get(&id)?))
}
pub fn get_handle(&self, component: &dyn Component<A>) -> Option<Handle> {
self.get_handle_by_id(component.id())
}
pub fn get_by_id(&self, id: Id) -> Option<&dyn Component<A>> {
self.get(self.get_handle_by_id(id)?)
}
pub fn get_mut_by_id(&mut self, id: Id) -> Option<&mut (dyn Component<A> + 'static)> {
self.get_mut(self.get_handle_by_id(id)?)
}
pub fn iter(&self) -> Iter<'_, A> {
self.components.iter()
}
pub fn iter_mut(&mut self) -> IterMut<'_, 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(())
}
pub fn get_downcast_ref<C>(&self) -> Option<&C>
where
C: Component<A>,
{
let index = *self.type_map.get(&TypeId::of::<C>())?;
self.components
.get(index.0)
.and_then(|box_component| (*(*box_component)).as_any().downcast_ref())
}
pub fn get_downcast_mut<C>(&mut self) -> Option<&mut C>
where
C: Component<A>,
{
let index = *self.type_map.get(&TypeId::of::<C>())?;
self.components
.get_mut(index.0)
.and_then(|box_component| (*(*box_component)).as_mut_any().downcast_mut())
}
fn register_component(
&mut self,
component: Box<dyn Component<A>>,
) -> Result<(), FrameworkError> {
let id = component.id();
let version = component.version();
let type_id = (*component).type_id();
ensure!(
!self.id_map.contains_key(&id) && !self.type_map.contains_key(&type_id),
ComponentError,
"duplicate component registration: {}",
id
);
let index = Index(self.components.len());
self.components.push(component);
assert!(self.id_map.insert(id, index).is_none());
assert!(self.type_map.insert(type_id, index).is_none());
debug!("registered component: {} (v{})", id, version);
Ok(())
}
#[allow(clippy::type_complexity)]
fn get2_mut(
&mut self,
a: Index,
b: Index,
) -> (
Option<&mut Box<dyn Component<A>>>,
Option<&mut Box<dyn Component<A>>>,
) {
let (a_slice, b_slice) = if b.0 <= self.components.len() {
self.components.split_at_mut(b.0)
} else {
(self.components.as_mut(), Default::default())
};
(a_slice.get_mut(a.0), b_slice.first_mut())
}
}