Skip to main content

object_rainbow/
map_extra.rs

1use std::collections::BTreeSet;
2
3use crate::*;
4
5#[derive(
6    Debug,
7    ToOutput,
8    InlineOutput,
9    Tagged,
10    ListHashes,
11    Topological,
12    Clone,
13    Copy,
14    Size,
15    MaybeHasNiche,
16    PartialEq,
17    Eq,
18    Default,
19)]
20pub struct MappedExtra<T, M = ()>(pub M, pub T);
21
22impl<T, M: Default> From<T> for MappedExtra<T, M> {
23    fn from(inner: T) -> Self {
24        Self(Default::default(), inner)
25    }
26}
27
28impl<T: IntoIterator, M> IntoIterator for MappedExtra<T, M> {
29    type Item = T::Item;
30
31    type IntoIter = T::IntoIter;
32
33    fn into_iter(self) -> Self::IntoIter {
34        self.1.into_iter()
35    }
36}
37
38impl<T, U: Equivalent<T>, M> Equivalent<MappedExtra<T, M>> for MappedExtra<U, M> {
39    fn into_equivalent(self) -> MappedExtra<T, M> {
40        MappedExtra(self.0, self.1.into_equivalent())
41    }
42
43    fn from_equivalent(mapped: MappedExtra<T, M>) -> Self {
44        Self(mapped.0, mapped.1.equivalent_for())
45    }
46}
47
48impl<T, M> Deref for MappedExtra<T, M> {
49    type Target = T;
50
51    fn deref(&self) -> &Self::Target {
52        &self.1
53    }
54}
55
56impl<T, M> DerefMut for MappedExtra<T, M> {
57    fn deref_mut(&mut self) -> &mut Self::Target {
58        &mut self.1
59    }
60}
61
62#[derive_for_wrapped]
63pub trait Map<Arg: 'static + Clone = ()> {
64    type Mapped: 'static + Clone;
65    fn map(&self, arg: Arg) -> Self::Mapped;
66}
67
68pub trait TryMap<Arg: 'static + Clone> {
69    type Mapped: 'static + Clone;
70    fn map(&self, arg: Arg) -> crate::Result<Self::Mapped>;
71}
72
73impl<Arg: 'static + Clone, M: Map<Arg>> TryMap<Arg> for M {
74    type Mapped = M::Mapped;
75
76    fn map(&self, arg: Arg) -> crate::Result<Self::Mapped> {
77        Ok(self.map(arg))
78    }
79}
80
81impl<
82    M: 'static + Send + Sync + Clone + ParseInline<I> + TryMap<X, Mapped = E>,
83    E: 'static + Send + Sync + Clone,
84    X: 'static + Send + Sync + Clone,
85    T: Parse<J>,
86    I: PointInput<Extra = X, WithExtra<E> = J>,
87    J: ParseInput,
88> Parse<I> for MappedExtra<T, M>
89{
90    fn parse(mut input: I) -> crate::Result<Self> {
91        let m = input.parse_inline::<M>()?;
92        let x = input.extra().clone();
93        let t = input.parse_extra(m.map(x)?)?;
94        Ok(Self(m, t))
95    }
96}
97
98impl<
99    M: 'static + Send + Sync + Clone + ParseInline<I> + TryMap<X, Mapped = E>,
100    E: 'static + Send + Sync + Clone,
101    X: 'static + Send + Sync + Clone,
102    T: ParseInline<J>,
103    I: PointInput<Extra = X, WithExtra<E> = J>,
104    J: ParseInput,
105> ParseInline<I> for MappedExtra<T, M>
106{
107    fn parse_inline(input: &mut I) -> crate::Result<Self> {
108        let m = input.parse_inline::<M>()?;
109        let x = input.extra().clone();
110        let t = input.parse_inline_extra(m.map(x)?)?;
111        Ok(Self(m, t))
112    }
113}
114
115pub trait StaticMap<T> {
116    type Mapped;
117    fn static_map(x: T) -> Self::Mapped;
118}
119
120mod private {
121    use ghost::phantom;
122
123    #[phantom]
124    #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Default)]
125    pub struct SmExtra<M>;
126
127    #[phantom]
128    pub struct StaticFMap<M>;
129
130    #[phantom]
131    pub struct StaticCompose<A, B>;
132
133    #[phantom]
134    pub struct StaticCollect<C>;
135}
136#[doc(hidden)]
137pub use self::private::*;
138
139pub type SmExtra<M> = private::SmExtra<M>;
140
141impl<M: StaticMap<T>, T> StaticMap<T> for SmExtra<M> {
142    type Mapped = M::Mapped;
143
144    fn static_map(x: T) -> Self::Mapped {
145        M::static_map(x)
146    }
147}
148
149impl<M> ToOutput for SmExtra<M> {
150    fn to_output(&self, _: &mut (impl ?Sized + Output)) {}
151}
152
153impl<M> InlineOutput for SmExtra<M> {}
154impl<M> Tagged for SmExtra<M> {}
155impl<M> ListHashes for SmExtra<M> {}
156impl<M> Topological for SmExtra<M> {}
157
158impl<M> Size for SmExtra<M> {
159    const SIZE: usize = 0;
160    type Size = typenum::U0;
161}
162
163impl<M> Monostate for SmExtra<M> {}
164
165impl<M> FromSized for SmExtra<M> {
166    fn from_sized(data: &GenericArray<u8, Self::Size>) -> Self {
167        let [] = (*data).into();
168        Self::default()
169    }
170}
171
172impl<M> MaybeHasNiche for SmExtra<M> {
173    type MnArray = NoNiche<ZeroNoNiche<<Self as Size>::Size>>;
174}
175
176impl<M> ByteOrd for SmExtra<M> {
177    fn bytes_cmp(&self, _: &Self) -> Ordering {
178        Ordering::Equal
179    }
180}
181
182impl<M, I: ParseInput> Parse<I> for SmExtra<M> {
183    fn parse(input: I) -> crate::Result<Self> {
184        ParseInline::parse_as_inline(input)
185    }
186}
187
188impl<M, I: ParseInput> ParseInline<I> for SmExtra<M> {
189    fn parse_inline(_: &mut I) -> crate::Result<Self> {
190        Ok(SmExtra)
191    }
192}
193
194impl<M: StaticMap<E, Mapped: 'static + Clone>, E: 'static + Clone> Map<E> for SmExtra<M> {
195    type Mapped = M::Mapped;
196
197    fn map(&self, e: E) -> Self::Mapped {
198        M::static_map(e)
199    }
200}
201
202pub struct StaticReturn;
203
204impl<T> StaticMap<T> for StaticReturn {
205    type Mapped = T;
206
207    fn static_map(x: T) -> Self::Mapped {
208        x
209    }
210}
211
212pub type Return = SmExtra<StaticReturn>;
213
214pub struct StaticToHash;
215
216impl<T: FullHash> StaticMap<T> for StaticToHash {
217    type Mapped = Hash;
218
219    fn static_map(x: T) -> Self::Mapped {
220        x.full_hash()
221    }
222}
223
224pub type ToHash = SmExtra<StaticToHash>;
225
226pub type StaticFMap<M> = private::StaticFMap<M>;
227
228impl<T, I: IntoIterator<Item = T>, M: StaticMap<T>> StaticMap<I> for StaticFMap<M> {
229    type Mapped = Vec<M::Mapped>;
230
231    fn static_map(it: I) -> Self::Mapped {
232        it.into_iter().map(M::static_map).collect()
233    }
234}
235
236pub type FMap<M> = SmExtra<StaticFMap<M>>;
237
238pub type StaticCompose<A, B> = private::StaticCompose<A, B>;
239
240impl<T, A: StaticMap<T>, B: StaticMap<A::Mapped>> StaticMap<T> for StaticCompose<A, B> {
241    type Mapped = B::Mapped;
242
243    fn static_map(x: T) -> Self::Mapped {
244        B::static_map(A::static_map(x))
245    }
246}
247
248pub type Compose<A, B> = SmExtra<StaticCompose<A, B>>;
249
250pub struct StaticUniqueSorted;
251
252impl<T: Ord, I: IntoIterator<Item = T>> StaticMap<I> for StaticUniqueSorted {
253    type Mapped = BTreeSet<T>;
254
255    fn static_map(it: I) -> Self::Mapped {
256        it.into_iter().collect()
257    }
258}
259
260pub type UniqueSorted = SmExtra<StaticUniqueSorted>;
261
262pub struct StaticFlatten;
263
264impl<A: IntoIterator<Item = B>, B: IntoIterator<Item = C>, C> StaticMap<A> for StaticFlatten {
265    type Mapped = Vec<C>;
266
267    fn static_map(a: A) -> Self::Mapped {
268        a.into_iter().flatten().collect()
269    }
270}
271
272pub type Flatten = SmExtra<StaticFlatten>;
273
274pub type StaticCollect<C> = private::StaticCollect<C>;
275
276impl<T, I: IntoIterator<Item = T>, C: FromIterator<T>> StaticMap<I> for StaticCollect<C> {
277    type Mapped = C;
278
279    fn static_map(it: I) -> Self::Mapped {
280        C::from_iter(it)
281    }
282}
283
284pub type Collect<C> = SmExtra<StaticCollect<C>>;
285
286pub struct StaticItem0;
287
288impl<T: IntoIterator> StaticMap<T> for StaticItem0 {
289    type Mapped = Option<T::Item>;
290
291    fn static_map(x: T) -> Self::Mapped {
292        x.into_iter().next()
293    }
294}
295
296pub type Item0 = SmExtra<StaticItem0>;
297
298pub type OptionMap<M> = Compose<FMap<M>, Item0>;