dill/
typecast_builder.rs

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