Skip to main content

formality_core/
cast.rs

1use std::sync::Arc;
2
3use crate::collections::Set;
4
5pub trait To {
6    fn to<T>(&self) -> T
7    where
8        Self: Upcast<T>;
9}
10
11impl<A> To for A {
12    fn to<T>(&self) -> T
13    where
14        Self: Upcast<T>,
15    {
16        <&A as Upcast<T>>::upcast(self)
17    }
18}
19
20/// Our version of `Into`. This is the trait you use in where clauses,
21/// but you typically implement `UpcastFrom`.
22pub trait Upcast<T>: Clone {
23    fn upcast(self) -> T;
24}
25
26impl<T, U> Upcast<U> for T
27where
28    T: Clone,
29    U: UpcastFrom<T>,
30{
31    fn upcast(self) -> U {
32        U::upcast_from(self)
33    }
34}
35
36/// Our version of `From`. One twist: it is implemented for &T for all T.
37/// This is the trait you implement.
38pub trait UpcastFrom<T: Clone> {
39    fn upcast_from(term: T) -> Self;
40}
41
42/// This is the convenience trait whose method you should call to do a downcast.
43pub trait Downcast: Sized {
44    fn downcast<T>(&self) -> Option<T>
45    where
46        T: DowncastFrom<Self>;
47
48    fn is_a<T>(&self) -> bool
49    where
50        T: DowncastFrom<Self>,
51    {
52        self.downcast::<T>().is_some()
53    }
54}
55
56impl<U> Downcast for U {
57    fn downcast<T>(&self) -> Option<T>
58    where
59        T: DowncastFrom<Self>,
60    {
61        T::downcast_from(self)
62    }
63}
64
65/// Our version of "try-into". A "downcast" casts
66/// from a more general type
67/// (e.g., any Parameter) to a more specific type
68/// (e.g., a type).
69///
70/// This is the trait that you prefer to implement,
71/// but use `DowncastFrom` in where-clauses.
72pub trait DowncastTo<T>: Sized {
73    fn downcast_to(&self) -> Option<T>;
74}
75
76impl<T: Clone, U> DowncastTo<T> for &U
77where
78    T: DowncastFrom<U>,
79{
80    fn downcast_to(&self) -> Option<T> {
81        T::downcast_from(self)
82    }
83}
84
85impl<A, B> DowncastTo<Vec<B>> for Vec<A>
86where
87    B: DowncastFrom<A>,
88{
89    fn downcast_to(&self) -> Option<Vec<B>> {
90        self.iter().map(|a| B::downcast_from(a)).collect()
91    }
92}
93
94/// Our version of "try-from". A "downcast" casts
95/// from a more general type
96/// (e.g., any Parameter) to a more specific type
97/// (e.g., a type). This returns an Option because
98/// the value may not be an instance of the more
99/// specific type.
100pub trait DowncastFrom<T>: Sized {
101    fn downcast_from(t: &T) -> Option<Self>;
102}
103
104impl<T, U> DowncastFrom<T> for U
105where
106    T: DowncastTo<U>,
107{
108    fn downcast_from(t: &T) -> Option<U> {
109        t.downcast_to()
110    }
111}
112
113impl<A, B> DowncastFrom<Set<A>> for Set<B>
114where
115    A: Ord,
116    B: DowncastFrom<A> + Ord,
117{
118    fn downcast_from(t: &Set<A>) -> Option<Self> {
119        t.iter().map(|a| B::downcast_from(a)).collect()
120    }
121}
122
123impl<T, U> DowncastFrom<Option<U>> for Option<T>
124where
125    T: DowncastFrom<U>,
126{
127    fn downcast_from(u: &Option<U>) -> Option<Self> {
128        match u {
129            Some(u) => Some(Some(T::downcast_from(u)?)),
130            None => None,
131        }
132    }
133}
134
135impl<T, U> DowncastFrom<Arc<U>> for Arc<T>
136where
137    T: DowncastFrom<U>,
138{
139    fn downcast_from(u: &Arc<U>) -> Option<Self> {
140        let t: T = T::downcast_from(u)?;
141        Some(Arc::new(t))
142    }
143}
144
145impl<A, B, A1, B1> DowncastFrom<(A1, B1)> for (A, B)
146where
147    A: DowncastFrom<A1>,
148    B: DowncastFrom<B1>,
149{
150    fn downcast_from(term: &(A1, B1)) -> Option<Self> {
151        let (a1, b1) = term;
152        let a = DowncastFrom::downcast_from(a1)?;
153        let b = DowncastFrom::downcast_from(b1)?;
154        Some((a, b))
155    }
156}
157
158impl<A, B, C, A1, B1, C1> DowncastFrom<(A1, B1, C1)> for (A, B, C)
159where
160    A: DowncastFrom<A1>,
161    B: DowncastFrom<B1>,
162    C: DowncastFrom<C1>,
163{
164    fn downcast_from(term: &(A1, B1, C1)) -> Option<Self> {
165        let (a1, b1, c1) = term;
166        let a = DowncastFrom::downcast_from(a1)?;
167        let b = DowncastFrom::downcast_from(b1)?;
168        let c = DowncastFrom::downcast_from(c1)?;
169        Some((a, b, c))
170    }
171}
172
173impl<T: Clone, U> UpcastFrom<&T> for U
174where
175    T: Upcast<U>,
176{
177    fn upcast_from(term: &T) -> Self {
178        T::upcast(T::clone(term))
179    }
180}
181
182impl<T: Clone, U> UpcastFrom<Vec<T>> for Vec<U>
183where
184    T: Upcast<U>,
185{
186    fn upcast_from(term: Vec<T>) -> Self {
187        term.into_iter().map(|t| T::upcast(t)).collect()
188    }
189}
190
191impl<T: Clone, U> UpcastFrom<Set<T>> for Set<U>
192where
193    T: Upcast<U> + Ord,
194    U: Ord,
195{
196    fn upcast_from(term: Set<T>) -> Self {
197        term.into_iter().map(|t| T::upcast(t)).collect()
198    }
199}
200
201impl<T: Clone, U> UpcastFrom<&[T]> for Vec<U>
202where
203    T: Upcast<U>,
204{
205    fn upcast_from(term: &[T]) -> Self {
206        term.iter().map(|t| t.upcast()).collect()
207    }
208}
209
210impl<T: Clone, U> UpcastFrom<Option<T>> for Option<U>
211where
212    T: Upcast<U>,
213{
214    fn upcast_from(term: Option<T>) -> Self {
215        term.map(|t| t.upcast())
216    }
217}
218
219impl DowncastTo<()> for () {
220    fn downcast_to(&self) -> Option<()> {
221        Some(())
222    }
223}
224
225impl<T> UpcastFrom<()> for T
226where
227    T: Default,
228{
229    fn upcast_from((): ()) -> Self {
230        Default::default()
231    }
232}
233
234impl<T: Clone, U> UpcastFrom<Arc<T>> for Arc<U>
235where
236    T: Upcast<U>,
237{
238    fn upcast_from(term: Arc<T>) -> Self {
239        let term: &T = &term;
240        Arc::new(term.to())
241    }
242}
243
244impl<A, B, A1, B1> UpcastFrom<(A1, B1)> for (A, B)
245where
246    A1: Upcast<A>,
247    B1: Upcast<B>,
248{
249    fn upcast_from(term: (A1, B1)) -> Self {
250        let (a1, b1) = term;
251        (a1.upcast(), b1.upcast())
252    }
253}
254
255impl<A, B, C, A1, B1, C1> UpcastFrom<(A1, B1, C1)> for (A, B, C)
256where
257    A1: Upcast<A>,
258    B1: Upcast<B>,
259    C1: Upcast<C>,
260{
261    fn upcast_from(term: (A1, B1, C1)) -> Self {
262        let (a1, b1, c1) = term;
263        (a1.upcast(), b1.upcast(), c1.upcast())
264    }
265}
266
267impl<A, As, B, Bs, Z> UpcastFrom<(A, B)> for Vec<Z>
268where
269    A: IntoIterator<Item = As> + Clone,
270    As: Upcast<Z>,
271    B: IntoIterator<Item = Bs> + Clone,
272    Bs: Upcast<Z>,
273{
274    fn upcast_from(term: (A, B)) -> Self {
275        let (a, b) = term;
276        let mut v: Self = vec![];
277        v.extend(a.into_iter().map(|a| a.upcast()));
278        v.extend(b.into_iter().map(|b| b.upcast()));
279        v
280    }
281}
282
283impl<A, B, C, Z> UpcastFrom<(A, B, C)> for Vec<Z>
284where
285    A: Upcast<Z>,
286    B: Upcast<Z>,
287    C: Upcast<Z>,
288{
289    fn upcast_from(term: (A, B, C)) -> Self {
290        let (a, b, c) = term;
291        vec![a.upcast(), b.upcast(), c.upcast()]
292    }
293}
294
295#[macro_export]
296macro_rules! cast_impl {
297    ($e:ident :: $v:ident ($u:ty)) => {
298        impl $crate::UpcastFrom<$u> for $e {
299            fn upcast_from(v: $u) -> $e {
300                $e::$v(v)
301            }
302        }
303
304        impl $crate::DowncastTo<$u> for $e {
305            fn downcast_to(&self) -> Option<$u> {
306                match self {
307                    $e::$v(u) => Some(Clone::clone(u)),
308                    _ => None,
309                }
310            }
311        }
312    };
313
314    (impl($($p:tt)*) $e:ident ($($ep:tt)*) :: $v:ident ($u:ty)) => {
315        impl<$($p)*> $crate::UpcastFrom<$u> for $e<$($ep)*> {
316            fn upcast_from(v: $u) -> $e<$($ep)*> {
317                $e::$v(v)
318            }
319        }
320
321        impl<$($p)*> $crate::DowncastTo<$u> for $e<$($ep)*> {
322            fn downcast_to(&self) -> Option<$u> {
323                match self {
324                    $e::$v(u) => Some(Clone::clone(u)),
325                    _ => None,
326                }
327            }
328        }
329    };
330
331    (impl($($p:tt)*) $t:ty) => {
332        impl<$($p)*> $crate::UpcastFrom<$t> for $t {
333            fn upcast_from(v: $t) -> $t {
334                v
335            }
336        }
337
338        impl<$($p)*> $crate::DowncastTo<$t> for $t {
339            fn downcast_to(&self) -> Option<$t> {
340                Some(Self::clone(self))
341            }
342        }
343    };
344
345    ($t:ty) => {
346        impl $crate::UpcastFrom<$t> for $t {
347            fn upcast_from(v: $t) -> $t {
348                v
349            }
350        }
351
352        impl $crate::DowncastTo<$t> for $t {
353            fn downcast_to(&self) -> Option<$t> {
354                Some(Self::clone(self))
355            }
356        }
357    };
358
359    ($(impl($($p:tt)*))? ($bot:ty) <: ($($mid:ty),*) <: ($top:ty)) => {
360        impl$(<$($p)*>)? $crate::UpcastFrom<$bot> for $top {
361            fn upcast_from(v: $bot) -> $top {
362                $(
363                    let v: $mid = $crate::Upcast::upcast(v);
364                )*
365                $crate::Upcast::upcast(v)
366            }
367        }
368
369        impl$(<$($p)*>)? $crate::DowncastTo<$bot> for $top {
370            fn downcast_to(&self) -> Option<$bot> {
371                let v: &$top = self;
372                $(
373                    let v: &$mid = &$crate::DowncastFrom::downcast_from(v)?;
374                )*
375                $crate::DowncastFrom::downcast_from(v)
376            }
377        }
378    };
379}
380
381cast_impl!(usize);
382cast_impl!(u32);
383cast_impl!(String);
384
385impl UpcastFrom<&str> for String {
386    fn upcast_from(term: &str) -> Self {
387        term.into()
388    }
389}
390
391pub trait Upcasted<'a, T> {
392    fn upcasted(self) -> Box<dyn Iterator<Item = T> + 'a>;
393}
394
395impl<'a, T, I> Upcasted<'a, T> for I
396where
397    I: IntoIterator + 'a,
398    I::Item: Upcast<T>,
399{
400    fn upcasted(self) -> Box<dyn Iterator<Item = T> + 'a> {
401        Box::new(self.into_iter().map(|e| e.upcast()))
402    }
403}
404
405pub trait Downcasted<'a>: IntoIterator {
406    fn downcasted<T>(self) -> Box<dyn Iterator<Item = T> + 'a>
407    where
408        T: DowncastFrom<Self::Item>;
409}
410
411impl<'a, I> Downcasted<'a> for I
412where
413    I: IntoIterator + 'a,
414{
415    fn downcasted<T>(self) -> Box<dyn Iterator<Item = T> + 'a>
416    where
417        T: DowncastFrom<I::Item>,
418    {
419        Box::new(self.into_iter().filter_map(|e| T::downcast_from(&e)))
420    }
421}