dill/
typecast_builder.rs

1use std::any::Any;
2use std::marker::PhantomData;
3use std::sync::Arc;
4
5use crate::injection_context::InjectionContext;
6use crate::*;
7
8////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
9
10#[derive(Clone)]
11pub(crate) struct Binding {
12    pub caster: Arc<AnyTypeCaster>,
13    pub builder: Arc<dyn Builder>,
14}
15
16impl Binding {
17    pub(crate) fn new(caster: Arc<AnyTypeCaster>, builder: Arc<dyn Builder>) -> Self {
18        Self { caster, builder }
19    }
20}
21
22////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
23
24/// Takes a dynamic `Builder` and casts the instance to desired interface
25pub struct TypecastBuilder<'a, Iface>
26where
27    Iface: 'static + ?Sized,
28{
29    builder: &'a dyn Builder,
30    caster: &'a TypeCaster<Iface>,
31}
32
33impl<Iface> Builder for TypecastBuilder<'_, Iface>
34where
35    Iface: 'static + ?Sized,
36{
37    fn instance_type(&self) -> TypeInfo {
38        self.builder.instance_type()
39    }
40
41    fn scope_type(&self) -> TypeInfo {
42        self.builder.scope_type()
43    }
44
45    fn interfaces(&self, clb: &mut dyn FnMut(&TypeInfo) -> bool) {
46        self.builder.interfaces(clb);
47    }
48
49    fn dependencies(&self, clb: &mut dyn FnMut(&DependencyInfo) -> bool) {
50        self.builder.dependencies(clb);
51    }
52
53    fn metadata<'b, 'c>(&'b self, clb: &'c mut dyn FnMut(&'b dyn Any) -> bool) {
54        self.builder.metadata(clb)
55    }
56
57    fn get_any(
58        &self,
59        cat: &Catalog,
60        ctx: &InjectionContext,
61    ) -> Result<Arc<dyn Any + Send + Sync>, InjectionError> {
62        self.builder.get_any(cat, ctx)
63    }
64}
65
66impl<'a, Iface> TypecastBuilder<'a, Iface>
67where
68    Iface: 'static + ?Sized,
69{
70    fn new(builder: &'a dyn Builder, caster: &'a TypeCaster<Iface>) -> Self {
71        Self { builder, caster }
72    }
73
74    pub fn get(&self, cat: &Catalog) -> Result<Arc<Iface>, InjectionError> {
75        self.get_with_context(cat, &InjectionContext::new_root())
76    }
77
78    pub fn get_with_context(
79        &self,
80        cat: &Catalog,
81        ctx: &InjectionContext,
82    ) -> Result<Arc<Iface>, InjectionError> {
83        let inst = self.builder.get_any(cat, ctx)?;
84        Ok((self.caster.cast_arc)(inst))
85    }
86}
87
88////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
89
90pub(crate) struct TypeCaster<Into: ?Sized> {
91    pub cast_arc: fn(Arc<dyn Any + Send + Sync>) -> Arc<Into>,
92}
93
94pub(crate) type AnyTypeCaster = dyn Any + Send + Sync;
95
96////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
97
98pub(crate) struct TypecastBuilderIterator<'a, Iface: 'static + ?Sized> {
99    bindings: Option<&'a Vec<Binding>>,
100    pos: usize,
101    _dummy: PhantomData<Iface>,
102}
103
104impl<'a, Iface: 'static + ?Sized> TypecastBuilderIterator<'a, Iface> {
105    pub(crate) fn new(bindings: Option<&'a Vec<Binding>>) -> Self {
106        Self {
107            bindings,
108            pos: 0,
109            _dummy: PhantomData,
110        }
111    }
112}
113
114impl<'a, Iface: 'static + ?Sized> Iterator for TypecastBuilderIterator<'a, Iface> {
115    type Item = TypecastBuilder<'a, Iface>;
116    fn next(&mut self) -> Option<Self::Item> {
117        if let Some(bindings) = self.bindings
118            && self.pos < bindings.len()
119        {
120            let b = &bindings[self.pos];
121            self.pos += 1;
122
123            // SAFETY: the TypeID key of the `bindings` map is guaranteed to match the
124            // `Iface` type
125            let caster: &TypeCaster<Iface> = b.caster.downcast_ref().unwrap();
126            return Some(TypecastBuilder::new(b.builder.as_ref(), caster));
127        }
128        None
129    }
130}
131
132////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
133
134pub(crate) struct TypecastPredicateBuilderIterator<'a, Iface: 'static + ?Sized, Pred>
135where
136    Pred: Fn(&dyn Builder) -> bool,
137{
138    bindings: Option<&'a Vec<Binding>>,
139    pred: Pred,
140    pos: usize,
141    _dummy: PhantomData<Iface>,
142}
143
144impl<'a, Iface: 'static + ?Sized, Pred> TypecastPredicateBuilderIterator<'a, Iface, Pred>
145where
146    Pred: Fn(&dyn Builder) -> bool,
147{
148    pub(crate) fn new(bindings: Option<&'a Vec<Binding>>, pred: Pred) -> Self {
149        Self {
150            bindings,
151            pred,
152            pos: 0,
153            _dummy: PhantomData,
154        }
155    }
156}
157
158impl<'a, Iface: 'static + ?Sized, Pred> Iterator
159    for TypecastPredicateBuilderIterator<'a, Iface, Pred>
160where
161    Pred: Fn(&dyn Builder) -> bool,
162{
163    type Item = TypecastBuilder<'a, Iface>;
164    fn next(&mut self) -> Option<Self::Item> {
165        if let Some(bindings) = self.bindings {
166            while self.pos < bindings.len() {
167                let b = &bindings[self.pos];
168                self.pos += 1;
169
170                if (self.pred)(b.builder.as_ref()) {
171                    // SAFETY: the TypeID key of the `bindings` map is guaranteed to match the
172                    // `Iface` type
173                    let caster: &TypeCaster<Iface> = b.caster.downcast_ref().unwrap();
174                    return Some(TypecastBuilder::new(b.builder.as_ref(), caster));
175                }
176            }
177        }
178        None
179    }
180}