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, 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>>;