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