deorbit_core/resolver/
services.rs1use crate::builder::ServicesBuilder;
2use crate::builder::{BindingKind, BindingLifetime};
3use crate::either_iter::EitherIter;
4use crate::mbmany::OneOrMany;
5use crate::resolver::Error;
6use crate::resolver::graph;
7use crate::resolver::resolved::Resolved;
8use crate::runtime::ServiceFactory;
9use crate::runtime::TypeMeta;
10use crate::runtime::{ErasedArc, ErasedUnsizer};
11use std::collections::HashMap;
12use std::iter;
13
14#[derive(Debug)]
16pub struct Services {
17 services: HashMap<TypeMeta, ImmutableBinding>,
18}
19
20#[derive(Debug)]
21enum ImmutableBinding {
22 Type {
23 binding: ImmutableTypeBinding,
24 },
25 Alias {
26 impls: OneOrMany<(ErasedUnsizer, ImmutableTypeBinding)>,
27 },
28}
29
30impl ImmutableBinding {
31 pub fn unwrap_type(&self) -> &ImmutableTypeBinding {
32 match self {
33 ImmutableBinding::Type { binding } => binding,
34 ImmutableBinding::Alias { .. } => {
35 panic!("Called unwrap_type on an Alias binding")
36 }
37 }
38 }
39}
40
41#[derive(Debug, Clone)]
42enum ImmutableTypeBinding {
43 Singleton(ErasedArc),
44 Transient(ServiceFactory),
45}
46
47impl ImmutableTypeBinding {
48 fn from(value: BindingLifetime, services: &Services) -> Result<Self, Error> {
49 let binding = match value {
50 BindingLifetime::Singleton(x) => Self::Singleton(x.to_instance(services)?),
51 BindingLifetime::Transient(x) => Self::Transient(x),
52 };
53
54 Ok(binding)
55 }
56}
57
58impl Services {
59 pub fn from_builder(builder: ServicesBuilder) -> Result<Self, Error> {
61 let bindings = builder.to_vec();
62
63 let bindings = graph::merge_aliases(bindings);
64 let bindings = graph::resolve_order(bindings)?;
65
66 let unbind: Vec<_> = bindings
69 .iter()
70 .filter_map(|x| match x.kind {
71 BindingKind::Type { bind_self, .. } if !bind_self => Some(x.ty),
72 _ => None,
73 })
74 .collect();
75
76 let mut services = Self {
77 services: HashMap::new(),
78 };
79
80 for binding in bindings {
81 let ty = binding.ty;
82
83 let binding = match binding.kind {
84 BindingKind::Type { lifetime, .. } => ImmutableBinding::Type {
85 binding: ImmutableTypeBinding::from(lifetime, &services)?,
86 },
87 BindingKind::Alias { impls } => {
88 ImmutableBinding::Alias {
89 impls: impls
90 .iter()
91 .map(|(meta, unsizer)| {
92 let binding = services.services.get(meta).unwrap();
95
96 (unsizer.clone(), binding.unwrap_type().clone())
97 })
98 .collect(),
99 }
100 }
101 };
102
103 services.services.insert(ty, binding);
104 }
105
106 for ty in unbind {
109 services.services.remove(&ty);
110 }
111
112 Ok(services)
113 }
114}
115
116impl Services {
117 pub fn resolve_all<T>(&self) -> Option<impl DoubleEndedIterator<Item = Resolved<T>>>
120 where
121 T: ?Sized + Send + Sync + 'static,
122 {
123 let type_meta = TypeMeta::of::<T>();
124
125 self.services.get(&type_meta).map(|x| match x {
126 ImmutableBinding::Type { binding } => {
127 let iter = iter::once(binding).map(|binding| {
128 self.get_instance(binding)
129 .coerce::<T>()
130 .expect("Failed to coerce. This is a bug!")
131 });
132
133 EitherIter::Left(iter)
134 }
135 ImmutableBinding::Alias { impls } => {
136 let iter = impls.into_iter().map(|(unsizer, binding)| {
137 let arc = self.get_instance(binding);
138
139 unsizer
140 .unsize::<T>(arc)
141 .expect("Failed to unsize. This is a bug!")
142 });
143
144 EitherIter::Right(iter)
145 }
146 })
147 }
148
149 pub fn resolve<T>(&self) -> Option<Resolved<T>>
151 where
152 T: ?Sized + Send + Sync + 'static,
153 {
154 self.resolve_all().map(|mut x| x.next_back().unwrap())
155 }
156
157 fn get_instance(&self, binding: &ImmutableTypeBinding) -> ErasedArc {
158 match binding {
159 ImmutableTypeBinding::Singleton(arc) => arc.clone(),
160 ImmutableTypeBinding::Transient(factory) => factory
163 .produce(self)
164 .expect("Failed while trying to instantiate Transient"),
165 }
166 }
167}