1use std::borrow::Borrow;
4use std::collections::BTreeMap;
5use std::fmt;
6use std::iter::FromIterator;
7use std::ops::{Deref, DerefMut};
8
9use async_hash::{Digest, Hash, Output};
10use async_trait::async_trait;
11use destream::de::{Decoder, FromStream};
12use destream::en::{Encoder, IntoStream, ToStream};
13use get_size::GetSize;
14use get_size_derive::*;
15use safecast::*;
16use serde::{Deserialize, Deserializer, Serialize, Serializer};
17
18use tc_error::*;
19
20use super::{Id, Tuple};
21
22#[derive(Clone, GetSize)]
24pub struct Map<T> {
25 inner: BTreeMap<Id, T>,
26}
27
28impl<T> Map<T> {
29 pub fn new() -> Self {
31 Self {
32 inner: BTreeMap::new(),
33 }
34 }
35
36 pub fn one<K: Into<Id>>(key: K, value: T) -> Self {
38 let mut map = Self::new();
39 map.insert(key.into(), value);
40 map
41 }
42
43 #[inline]
44 pub fn expect_empty(self) -> TCResult<()>
46 where
47 T: fmt::Debug,
48 {
49 if self.is_empty() {
50 Ok(())
51 } else {
52 Err(TCError::unexpected(self, "no parameters"))
53 }
54 }
55
56 pub fn into_inner(self) -> BTreeMap<Id, T> {
58 self.inner
59 }
60
61 pub fn option<N, P, D>(&mut self, name: &N, default: D) -> TCResult<P>
63 where
64 Id: Borrow<N> + Ord,
65 N: Ord + fmt::Display + ?Sized,
66 P: TryCastFrom<T>,
67 D: FnOnce() -> P,
68 T: fmt::Debug,
69 {
70 if let Some(param) = self.remove(name) {
71 P::try_cast_from(param, |p| {
72 bad_request!("expected {} but found {p:?}", std::any::type_name::<P>())
73 })
74 } else {
75 Ok((default)())
76 }
77 }
78
79 pub fn or_default<N, P>(&mut self, name: &N) -> TCResult<P>
81 where
82 Id: Borrow<N> + Ord,
83 N: Ord + fmt::Display + ?Sized,
84 P: Default + TryCastFrom<T>,
85 T: fmt::Debug,
86 {
87 if let Some(param) = self.remove(name) {
88 P::try_cast_from(param, |p| {
89 TCError::unexpected(p, std::any::type_name::<P>())
90 })
91 } else {
92 Ok(P::default())
93 }
94 }
95
96 pub fn require<N, P>(&mut self, name: &N) -> TCResult<P>
98 where
99 Id: Borrow<N> + Ord,
100 N: Ord + fmt::Display + ?Sized,
101 P: TryCastFrom<T>,
102 T: fmt::Debug,
103 {
104 let param = self.remove(name).ok_or_else(|| TCError::not_found(name))?;
105
106 P::try_cast_from(param, |p| {
107 TCError::unexpected(p, std::any::type_name::<P>())
108 })
109 }
110}
111
112impl<T> Default for Map<T> {
113 fn default() -> Map<T> {
114 BTreeMap::new().into()
115 }
116}
117
118impl<T: PartialEq> PartialEq for Map<T> {
119 fn eq(&self, other: &Self) -> bool {
120 self.inner == other.inner
121 }
122}
123
124impl<T: PartialEq + Eq> Eq for Map<T> {}
125
126impl<T> AsRef<BTreeMap<Id, T>> for Map<T> {
127 fn as_ref(&self) -> &BTreeMap<Id, T> {
128 &self.inner
129 }
130}
131
132impl<T> Deref for Map<T> {
133 type Target = BTreeMap<Id, T>;
134
135 fn deref(&'_ self) -> &'_ Self::Target {
136 &self.inner
137 }
138}
139
140impl<T> DerefMut for Map<T> {
141 fn deref_mut(&'_ mut self) -> &'_ mut <Self as Deref>::Target {
142 &mut self.inner
143 }
144}
145
146impl<D, T> Hash<D> for Map<T>
147where
148 D: Digest,
149 T: Hash<D>,
150{
151 fn hash(self) -> Output<D> {
152 self.inner.hash()
153 }
154}
155
156impl<'a, D, T> Hash<D> for &'a Map<T>
157where
158 D: Digest,
159 &'a T: Hash<D>,
160{
161 fn hash(self) -> Output<D> {
162 self.inner.hash()
163 }
164}
165
166impl<T> Extend<(Id, T)> for Map<T> {
167 fn extend<I: IntoIterator<Item = (Id, T)>>(&mut self, iter: I) {
168 for (key, value) in iter.into_iter() {
169 self.insert(key, value);
170 }
171 }
172}
173
174impl<T> IntoIterator for Map<T> {
175 type Item = (Id, T);
176 type IntoIter = <BTreeMap<Id, T> as IntoIterator>::IntoIter;
177
178 fn into_iter(self) -> Self::IntoIter {
179 self.inner.into_iter()
180 }
181}
182
183impl<'a, T> IntoIterator for &'a Map<T> {
184 type Item = (&'a Id, &'a T);
185 type IntoIter = <&'a BTreeMap<Id, T> as IntoIterator>::IntoIter;
186
187 fn into_iter(self) -> Self::IntoIter {
188 self.inner.iter()
189 }
190}
191
192impl<F, T> FromIterator<(Id, F)> for Map<T>
193where
194 T: CastFrom<F>,
195{
196 fn from_iter<I: IntoIterator<Item = (Id, F)>>(iter: I) -> Self {
197 let mut inner = BTreeMap::new();
198
199 for (id, f) in iter {
200 inner.insert(id, f.cast_into());
201 }
202
203 Map { inner }
204 }
205}
206
207impl<T> From<BTreeMap<Id, T>> for Map<T> {
208 fn from(inner: BTreeMap<Id, T>) -> Self {
209 Map { inner }
210 }
211}
212
213impl<F, T> TryCastFrom<Tuple<F>> for Map<T>
214where
215 (Id, T): TryCastFrom<F>,
216{
217 fn can_cast_from(tuple: &Tuple<F>) -> bool {
218 tuple.iter().all(|e| e.matches::<(Id, T)>())
219 }
220
221 fn opt_cast_from(tuple: Tuple<F>) -> Option<Self> {
222 let mut inner = BTreeMap::<Id, T>::new();
223
224 for f in tuple.into_iter() {
225 if let Some((id, t)) = f.opt_cast_into() {
226 inner.insert(id, t);
227 } else {
228 return None;
229 }
230 }
231
232 Some(Self { inner })
233 }
234}
235
236#[async_trait]
237impl<T: FromStream<Context = ()>> FromStream for Map<T>
238where
239 T::Context: Copy,
240{
241 type Context = T::Context;
242
243 async fn from_stream<D: Decoder>(context: T::Context, d: &mut D) -> Result<Self, D::Error> {
244 let inner = BTreeMap::<Id, T>::from_stream(context, d).await?;
245 Ok(Self { inner })
246 }
247}
248
249impl<'en, T: IntoStream<'en> + 'en> IntoStream<'en> for Map<T> {
250 fn into_stream<E: Encoder<'en>>(self, encoder: E) -> Result<E::Ok, E::Error> {
251 self.inner.into_stream(encoder)
252 }
253}
254
255impl<'en, T: ToStream<'en> + 'en> ToStream<'en> for Map<T> {
256 fn to_stream<E: Encoder<'en>>(&'en self, encoder: E) -> Result<E::Ok, E::Error> {
257 self.inner.to_stream(encoder)
258 }
259}
260
261impl<'de, T: Deserialize<'de>> Deserialize<'de> for Map<T> {
262 fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
263 BTreeMap::deserialize(deserializer).map(|inner| Self { inner })
264 }
265}
266
267impl<T: Serialize> Serialize for Map<T> {
268 fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
269 self.inner.serialize(serializer)
270 }
271}
272
273impl<F, T: TryCastFrom<F>> TryCastFrom<Map<F>> for BTreeMap<Id, T> {
274 fn can_cast_from(map: &Map<F>) -> bool {
275 map.values().all(|f| T::can_cast_from(f))
276 }
277
278 fn opt_cast_from(source: Map<F>) -> Option<Self> {
279 let mut map = BTreeMap::new();
280
281 for (id, f) in source.into_iter() {
282 if let Some(t) = T::opt_cast_from(f) {
283 map.insert(id, t);
284 } else {
285 return None;
286 }
287 }
288
289 Some(map)
290 }
291}
292
293impl<T: fmt::Debug> fmt::Debug for Map<T> {
294 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
295 f.write_str("{")?;
296
297 for (i, (k, v)) in self.iter().enumerate() {
298 write!(f, "\t{}: {:?}", k, v)?;
299
300 if i < self.len() - 1 {
301 f.write_str(",\n")?;
302 }
303 }
304
305 f.write_str("}")
306 }
307}