object_rainbow/
map_extra.rs1use 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>>;