hyper_util/client/pool/
map.rs1use std::collections::HashMap;
32
33#[cfg(docsrs)]
35pub use self::builder::Builder;
36
37pub struct Map<T, Req>
41where
42 T: target::Target<Req>,
43{
44 map: HashMap<T::Key, T::Service>,
45 targeter: T,
46}
47
48impl Map<builder::StartHere, builder::StartHere> {
51 pub fn builder<Dst>() -> builder::Builder<Dst, builder::WantsKeyer, builder::WantsServiceMaker>
53 {
54 builder::Builder::new()
55 }
56}
57
58impl<T, Req> Map<T, Req>
59where
60 T: target::Target<Req>,
61{
62 fn new(targeter: T) -> Self {
63 Map {
64 map: HashMap::new(),
65 targeter,
66 }
67 }
68}
69
70impl<T, Req> Map<T, Req>
71where
72 T: target::Target<Req>,
73 T::Key: Eq + std::hash::Hash,
74{
75 pub fn service(&mut self, req: &Req) -> &mut T::Service {
77 let key = self.targeter.key(req);
78 self.map
79 .entry(key)
80 .or_insert_with(|| self.targeter.service(req))
81 }
82
83 pub fn retain<F>(&mut self, predicate: F)
85 where
86 F: FnMut(&T::Key, &mut T::Service) -> bool,
87 {
88 self.map.retain(predicate);
89 }
90
91 pub fn clear(&mut self) {
93 self.map.clear();
94 }
95}
96
97mod target {
99 pub trait Target<Dst> {
100 type Key;
101 type Service;
102
103 fn key(&self, dst: &Dst) -> Self::Key;
104 fn service(&self, dst: &Dst) -> Self::Service;
105 }
106}
107
108mod builder {
110 use std::marker::PhantomData;
111
112 pub struct Builder<Dst, K, S> {
120 _dst: PhantomData<fn(Dst)>,
121 keys: K,
122 svcs: S,
123 }
124
125 pub struct WantsKeyer;
126 pub struct WantsServiceMaker;
127
128 pub enum StartHere {}
129
130 pub struct Built<K, S> {
131 keys: K,
132 svcs: S,
133 }
134
135 impl<Dst> Builder<Dst, WantsKeyer, WantsServiceMaker> {
136 pub(super) fn new() -> Self {
137 Builder {
138 _dst: PhantomData,
139 keys: WantsKeyer,
140 svcs: WantsServiceMaker,
141 }
142 }
143 }
144
145 impl<Dst, S> Builder<Dst, WantsKeyer, S> {
146 pub fn keys<K, KK>(self, keyer: K) -> Builder<Dst, K, S>
148 where
149 K: Fn(&Dst) -> KK,
150 {
151 Builder {
152 _dst: PhantomData,
153 keys: keyer,
154 svcs: self.svcs,
155 }
156 }
157 }
158
159 impl<Dst, K> Builder<Dst, K, WantsServiceMaker> {
160 pub fn values<S, SS>(self, svcs: S) -> Builder<Dst, K, S>
162 where
163 S: Fn(&Dst) -> SS,
164 {
165 Builder {
166 _dst: PhantomData,
167 keys: self.keys,
168 svcs,
169 }
170 }
171 }
172
173 impl<Dst, K, S> Builder<Dst, K, S>
174 where
175 Built<K, S>: super::target::Target<Dst>,
176 <Built<K, S> as super::target::Target<Dst>>::Key: Eq + std::hash::Hash,
177 {
178 pub fn build(self) -> super::Map<Built<K, S>, Dst> {
180 super::Map::new(Built {
181 keys: self.keys,
182 svcs: self.svcs,
183 })
184 }
185 }
186
187 impl super::target::Target<StartHere> for StartHere {
188 type Key = StartHere;
189 type Service = StartHere;
190
191 fn key(&self, _: &StartHere) -> Self::Key {
192 match *self {}
193 }
194
195 fn service(&self, _: &StartHere) -> Self::Service {
196 match *self {}
197 }
198 }
199
200 impl<K, KK, S, SS, Dst> super::target::Target<Dst> for Built<K, S>
201 where
202 K: Fn(&Dst) -> KK,
203 S: Fn(&Dst) -> SS,
204 KK: Eq + std::hash::Hash,
205 {
206 type Key = KK;
207 type Service = SS;
208
209 fn key(&self, dst: &Dst) -> Self::Key {
210 (self.keys)(dst)
211 }
212
213 fn service(&self, dst: &Dst) -> Self::Service {
214 (self.svcs)(dst)
215 }
216 }
217}
218
219#[cfg(test)]
220mod tests {
221 #[test]
222 fn smoke() {
223 let mut pool = super::Map::builder().keys(|_| "a").values(|_| "b").build();
224 pool.service(&"hello");
225 }
226}