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