use std::any::TypeId;
use std::sync::Arc;
use nest_rs_core::Container;
use nest_rs_pipes::GlobalPipe;
use crate::Guard;
pub struct GuardSpec {
pub type_id: TypeId,
pub name: &'static str,
pub(crate) resolve: fn(&Container) -> Option<Arc<dyn Guard>>,
}
pub fn guard<G: Guard + 'static>() -> GuardSpec {
GuardSpec {
type_id: TypeId::of::<G>(),
name: std::any::type_name::<G>(),
resolve: |c| c.get::<G>().map(|arc| arc as Arc<dyn Guard>),
}
}
impl GuardSpec {
pub fn resolve(&self, container: &Container) -> Option<Arc<dyn Guard>> {
(self.resolve)(container)
}
}
pub struct PipeSpec {
pub type_id: TypeId,
pub name: &'static str,
pub(crate) resolve: fn(&Container) -> Option<Arc<dyn GlobalPipe>>,
}
pub fn pipe<P: GlobalPipe + 'static>() -> PipeSpec {
PipeSpec {
type_id: TypeId::of::<P>(),
name: std::any::type_name::<P>(),
resolve: |c| c.get::<P>().map(|arc| arc as Arc<dyn GlobalPipe>),
}
}
impl PipeSpec {
pub fn resolve(&self, container: &Container) -> Option<Arc<dyn GlobalPipe>> {
(self.resolve)(container)
}
}
pub struct GuardSpecs(pub Vec<GuardSpec>);
impl GuardSpecs {
pub fn resolve_chain(
&self,
container: &Container,
label: &str,
) -> Vec<nest_rs_core::ResolvedLayer<dyn Guard>> {
let global: Vec<nest_rs_core::ResolvedLayer<dyn Guard>> = self
.0
.iter()
.filter_map(|spec| {
spec.resolve(container)
.map(|layer| nest_rs_core::ResolvedLayer {
type_id: spec.type_id,
name: spec.name,
source: nest_rs_core::LayerSite::Global,
layer,
})
})
.collect();
nest_rs_core::compose_chain(global, Vec::new(), Vec::new(), &[], label)
}
}
pub struct PipeSpecs(pub Vec<PipeSpec>);