tcgeneric/
map.rs

1//! A generic map whose keys are [`Id`]s
2
3use 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/// A generic map whose keys are [`Id`]s, based on [`BTreeMap`]
23#[derive(Clone, GetSize)]
24pub struct Map<T> {
25    inner: BTreeMap<Id, T>,
26}
27
28impl<T> Map<T> {
29    /// Construct a new [`Map`].
30    pub fn new() -> Self {
31        Self {
32            inner: BTreeMap::new(),
33        }
34    }
35
36    /// Construct a new [`Map`] with a single entry.
37    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    /// Return an error if this [`Map`] is not empty.
45    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    /// Retrieve this [`Map`]'s underlying [`BTreeMap`].
57    pub fn into_inner(self) -> BTreeMap<Id, T> {
58        self.inner
59    }
60
61    /// Remove and return the parameter with the given `name`, or the `default` if not present.
62    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    /// Remove and return the parameter with the given `name`, or it's type's [`Default`].
80    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    /// Remove and return the parameter with the given `name`, or a "not found" error.
97    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}