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 MapExtra<Extra: 'static + Clone = ()> {
64    type Mapped: 'static + Clone;
65    fn map_extra(&self, extra: Extra) -> Self::Mapped;
66}
67
68impl<
69    M: 'static + Send + Sync + Clone + ParseInline<I> + MapExtra<X, Mapped = E>,
70    E: 'static + Send + Sync + Clone,
71    X: 'static + Send + Sync + Clone,
72    T: Parse<J>,
73    I: PointInput<Extra = X, WithExtra<E> = J>,
74    J: ParseInput,
75> Parse<I> for MappedExtra<T, M>
76{
77    fn parse(mut input: I) -> crate::Result<Self> {
78        let m = input.parse_inline::<M>()?;
79        let x = input.extra().clone();
80        let t = input.parse_extra(m.map_extra(x))?;
81        Ok(Self(m, t))
82    }
83}
84
85impl<
86    M: 'static + Send + Sync + Clone + ParseInline<I> + MapExtra<X, Mapped = E>,
87    E: 'static + Send + Sync + Clone,
88    X: 'static + Send + Sync + Clone,
89    T: ParseInline<J>,
90    I: PointInput<Extra = X, WithExtra<E> = J>,
91    J: ParseInput,
92> ParseInline<I> for MappedExtra<T, M>
93{
94    fn parse_inline(input: &mut I) -> crate::Result<Self> {
95        let m = input.parse_inline::<M>()?;
96        let x = input.extra().clone();
97        let t = input.parse_inline_extra(m.map_extra(x))?;
98        Ok(Self(m, t))
99    }
100}
101
102pub trait StaticMap<T> {
103    type Mapped;
104    fn static_map(x: T) -> Self::Mapped;
105}
106
107#[allow(clippy::repr_packed_without_abi)]
108mod private {
109    use ghost::phantom;
110
111    #[phantom]
112    #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Default)]
113    pub struct SmExtra<M>;
114
115    #[phantom]
116    pub struct StaticFMap<M>;
117
118    #[phantom]
119    pub struct StaticCompose<A, B>;
120
121    #[phantom]
122    pub struct StaticCollect<C>;
123}
124#[doc(hidden)]
125pub use self::private::*;
126
127pub type SmExtra<M> = private::SmExtra<M>;
128
129impl<M: StaticMap<T>, T> StaticMap<T> for SmExtra<M> {
130    type Mapped = M::Mapped;
131
132    fn static_map(x: T) -> Self::Mapped {
133        M::static_map(x)
134    }
135}
136
137impl<M> ToOutput for SmExtra<M> {
138    fn to_output(&self, _: &mut impl Output) {}
139}
140
141impl<M> InlineOutput for SmExtra<M> {}
142impl<M> Tagged for SmExtra<M> {}
143impl<M> ListHashes for SmExtra<M> {}
144impl<M> Topological for SmExtra<M> {}
145
146impl<M> Size for SmExtra<M> {
147    const SIZE: usize = 0;
148    type Size = typenum::U0;
149}
150
151impl<M> Monostate for SmExtra<M> {}
152
153impl<M> FromSized for SmExtra<M> {
154    fn from_sized(data: &GenericArray<u8, Self::Size>) -> Self {
155        let [] = (*data).into();
156        Self::default()
157    }
158}
159
160impl<M> MaybeHasNiche for SmExtra<M> {
161    type MnArray = NoNiche<ZeroNoNiche<<Self as Size>::Size>>;
162}
163
164impl<M> ByteOrd for SmExtra<M> {
165    fn bytes_cmp(&self, _: &Self) -> Ordering {
166        Ordering::Equal
167    }
168}
169
170impl<M, I: ParseInput> Parse<I> for SmExtra<M> {
171    fn parse(input: I) -> crate::Result<Self> {
172        ParseInline::parse_as_inline(input)
173    }
174}
175
176impl<M, I: ParseInput> ParseInline<I> for SmExtra<M> {
177    fn parse_inline(_: &mut I) -> crate::Result<Self> {
178        Ok(SmExtra)
179    }
180}
181
182impl<M: StaticMap<E, Mapped: 'static + Clone>, E: 'static + Clone> MapExtra<E> for SmExtra<M> {
183    type Mapped = M::Mapped;
184
185    fn map_extra(&self, e: E) -> Self::Mapped {
186        M::static_map(e)
187    }
188}
189
190pub struct StaticReturn;
191
192impl<T> StaticMap<T> for StaticReturn {
193    type Mapped = T;
194
195    fn static_map(x: T) -> Self::Mapped {
196        x
197    }
198}
199
200pub type Return = SmExtra<StaticReturn>;
201
202pub struct StaticToHash;
203
204impl<T: FullHash> StaticMap<T> for StaticToHash {
205    type Mapped = Hash;
206
207    fn static_map(x: T) -> Self::Mapped {
208        x.full_hash()
209    }
210}
211
212pub type ToHash = SmExtra<StaticToHash>;
213
214pub type StaticFMap<M> = private::StaticFMap<M>;
215
216impl<T, I: IntoIterator<Item = T>, M: StaticMap<T>> StaticMap<I> for StaticFMap<M> {
217    type Mapped = Vec<M::Mapped>;
218
219    fn static_map(it: I) -> Self::Mapped {
220        it.into_iter().map(M::static_map).collect()
221    }
222}
223
224pub type FMap<M> = SmExtra<StaticFMap<M>>;
225
226pub type StaticCompose<A, B> = private::StaticCompose<A, B>;
227
228impl<T, A: StaticMap<T>, B: StaticMap<A::Mapped>> StaticMap<T> for StaticCompose<A, B> {
229    type Mapped = B::Mapped;
230
231    fn static_map(x: T) -> Self::Mapped {
232        B::static_map(A::static_map(x))
233    }
234}
235
236pub type Compose<A, B> = SmExtra<StaticCompose<A, B>>;
237
238pub struct StaticUniqueSorted;
239
240impl<T: Ord, I: IntoIterator<Item = T>> StaticMap<I> for StaticUniqueSorted {
241    type Mapped = BTreeSet<T>;
242
243    fn static_map(it: I) -> Self::Mapped {
244        it.into_iter().collect()
245    }
246}
247
248pub type UniqueSorted = SmExtra<StaticUniqueSorted>;
249
250pub struct StaticFlatten;
251
252impl<A: IntoIterator<Item = B>, B: IntoIterator<Item = C>, C> StaticMap<A> for StaticFlatten {
253    type Mapped = Vec<C>;
254
255    fn static_map(a: A) -> Self::Mapped {
256        a.into_iter().flatten().collect()
257    }
258}
259
260pub type Flatten = SmExtra<StaticFlatten>;
261
262pub type StaticCollect<C> = private::StaticCollect<C>;
263
264impl<T, I: IntoIterator<Item = T>, C: FromIterator<T>> StaticMap<I> for StaticCollect<C> {
265    type Mapped = C;
266
267    fn static_map(it: I) -> Self::Mapped {
268        C::from_iter(it)
269    }
270}
271
272pub type Collect<C> = SmExtra<StaticCollect<C>>;