1use crate::{Error, Invalid, Nothing, Parse, Parser, Result, ToTokens, TokenIter, TokenStream};
8
9#[derive(Clone)]
12pub struct Cons<A, B, C = Nothing, D = Nothing> {
13 pub first: A,
15 pub second: B,
17 pub third: C,
19 pub fourth: D,
21}
22
23impl<A, B, C: 'static, D: 'static> Cons<A, B, C, D> {
24 fn used_conjunctions() -> usize {
31 let mut len = 2;
32 let nothing = std::any::TypeId::of::<Nothing>();
34 if std::any::TypeId::of::<C>() != nothing {
35 len += 1;
36 }
37 if std::any::TypeId::of::<D>() != nothing {
38 assert_ne!(
39 std::any::TypeId::of::<C>(),
40 nothing,
41 "If C is not Nothing then D must be Nothing"
42 );
43 len += 1;
44 }
45 len
46 }
47}
48
49impl<A: Parse, B: Parse, C: Parse, D: Parse> Parser for Cons<A, B, C, D> {
50 fn parser(tokens: &mut TokenIter) -> Result<Self> {
51 Ok(Self {
52 first: A::parser(tokens)?,
53 second: B::parser(tokens)?,
54 third: C::parser(tokens)?,
55 fourth: D::parser(tokens)?,
56 })
57 }
58}
59
60impl<A: ToTokens, B: ToTokens, C: ToTokens, D: ToTokens> ToTokens for Cons<A, B, C, D> {
61 fn to_tokens(&self, tokens: &mut TokenStream) {
62 self.first.to_tokens(tokens);
63 self.second.to_tokens(tokens);
64 self.third.to_tokens(tokens);
65 self.fourth.to_tokens(tokens);
66 }
67}
68
69impl<A, B> From<Cons<A, B>> for (A, B) {
70 fn from(cons: Cons<A, B>) -> Self {
71 (cons.first, cons.second)
72 }
73}
74
75impl<A, B, C> From<Cons<A, B, C>> for (A, B, C) {
76 fn from(cons: Cons<A, B, C>) -> Self {
77 (cons.first, cons.second, cons.third)
78 }
79}
80
81impl<A, B, C, D> From<Cons<A, B, C, D>> for (A, B, C, D) {
82 fn from(cons: Cons<A, B, C, D>) -> Self {
83 (cons.first, cons.second, cons.third, cons.fourth)
84 }
85}
86
87#[mutants::skip]
88impl<A, B, C, D> std::fmt::Debug for Cons<A, B, C, D>
89where
90 A: std::fmt::Debug,
91 B: std::fmt::Debug,
92 C: std::fmt::Debug + 'static,
93 D: std::fmt::Debug + 'static,
94{
95 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
96 match Self::used_conjunctions() {
97 1 | 2 => f
98 .debug_struct(&format!(
99 "Cons<{}, {}>",
100 std::any::type_name::<A>(),
101 std::any::type_name::<B>(),
102 ))
103 .field("first", &self.first)
104 .field("second", &self.second)
105 .finish(),
106 3 => f
107 .debug_struct(&format!(
108 "Cons<{}, {}, {}>",
109 std::any::type_name::<A>(),
110 std::any::type_name::<B>(),
111 std::any::type_name::<C>(),
112 ))
113 .field("first", &self.first)
114 .field("second", &self.second)
115 .field("third", &self.third)
116 .finish(),
117 _ => f
118 .debug_struct(&format!(
119 "Cons<{}, {}, {}, {}>",
120 std::any::type_name::<A>(),
121 std::any::type_name::<B>(),
122 std::any::type_name::<C>(),
123 std::any::type_name::<D>(),
124 ))
125 .field("first", &self.first)
126 .field("second", &self.second)
127 .field("third", &self.third)
128 .field("fourth", &self.fourth)
129 .finish(),
130 }
131 }
132}
133
134#[derive(Clone)]
137pub enum Either<A, B, C = Invalid, D = Invalid> {
138 First(A),
140 Second(B),
142 Third(C),
144 Fourth(D),
146}
147
148impl<A, B, C: 'static, D: 'static> Either<A, B, C, D> {
149 fn used_disjunctions() -> usize {
156 let mut len = 2;
157 let invalid = std::any::TypeId::of::<Invalid>();
159 if std::any::TypeId::of::<C>() != invalid {
160 len += 1;
161 }
162 if std::any::TypeId::of::<D>() != invalid {
163 assert_ne!(
164 std::any::TypeId::of::<C>(),
165 invalid,
166 "If C is not Invalid then D must be Invalid"
167 );
168 len += 1;
169 }
170 len
171 }
172
173 pub fn fold2<R, FA, FB>(self, first_fn: FA, second_fn: FB) -> R
192 where
193 FA: FnOnce(A) -> R,
194 FB: FnOnce(B) -> R,
195 {
196 debug_assert_eq!(Self::used_disjunctions(), 2);
197 match self {
198 Either::First(a) => first_fn(a),
199 Either::Second(b) => second_fn(b),
200 _ => unimplemented!(),
201 }
202 }
203
204 pub fn fold3<R, FA, FB, FC>(self, first_fn: FA, second_fn: FB, third_fn: FC) -> R
211 where
212 FA: FnOnce(A) -> R,
213 FB: FnOnce(B) -> R,
214 FC: FnOnce(C) -> R,
215 {
216 debug_assert_eq!(Self::used_disjunctions(), 3);
217 match self {
218 Either::First(a) => first_fn(a),
219 Either::Second(b) => second_fn(b),
220 Either::Third(c) => third_fn(c),
221 Either::Fourth(_) => unimplemented!(),
222 }
223 }
224
225 pub fn fold4<R, FA, FB, FC, FD>(
228 self,
229 first_fn: FA,
230 second_fn: FB,
231 third_fn: FC,
232 fourth_fn: FD,
233 ) -> R
234 where
235 FA: FnOnce(A) -> R,
236 FB: FnOnce(B) -> R,
237 FC: FnOnce(C) -> R,
238 FD: FnOnce(D) -> R,
239 {
240 debug_assert_eq!(Self::used_disjunctions(), 4);
241 match self {
242 Either::First(a) => first_fn(a),
243 Either::Second(b) => second_fn(b),
244 Either::Third(c) => third_fn(c),
245 Either::Fourth(d) => fourth_fn(d),
246 }
247 }
248
249 pub fn into2<T>(self) -> T
265 where
266 A: Into<T>,
267 B: Into<T>,
268 {
269 debug_assert_eq!(Self::used_disjunctions(), 2);
270 match self {
271 Either::First(a) => a.into(),
272 Either::Second(b) => b.into(),
273 _ => unimplemented!(),
274 }
275 }
276
277 pub fn into3<T>(self) -> T
284 where
285 A: Into<T>,
286 B: Into<T>,
287 C: Into<T>,
288 {
289 debug_assert_eq!(Self::used_disjunctions(), 3);
290 match self {
291 Either::First(a) => a.into(),
292 Either::Second(b) => b.into(),
293 Either::Third(c) => c.into(),
294 Either::Fourth(_) => unimplemented!(),
295 }
296 }
297
298 pub fn into4<T>(self) -> T
301 where
302 A: Into<T>,
303 B: Into<T>,
304 C: Into<T>,
305 D: Into<T>,
306 {
307 debug_assert_eq!(Self::used_disjunctions(), 4);
308 match self {
309 Either::First(a) => a.into(),
310 Either::Second(b) => b.into(),
311 Either::Third(c) => c.into(),
312 Either::Fourth(d) => d.into(),
313 }
314 }
315}
316
317impl<A, B, C, D> Parser for Either<A, B, C, D>
318where
319 A: Parse,
320 B: Parse,
321 C: Parse,
322 D: Parse,
323{
324 fn parser(tokens: &mut TokenIter) -> Result<Self> {
325 let mut err = Error::no_error();
326
327 if let Ok(first) = err.upgrade(A::parse(tokens)) {
328 Ok(Either::First(first))
329 } else if let Ok(second) = err.upgrade(B::parse(tokens)) {
330 Ok(Either::Second(second))
331 } else if let Ok(third) = err.upgrade(C::parse(tokens)) {
332 Ok(Either::Third(third))
333 } else if let Ok(fourth) = err.upgrade(D::parse(tokens)) {
334 Ok(Either::Fourth(fourth))
335 } else {
336 Err(err)
337 }
338 }
339}
340
341impl<A, B, C, D> ToTokens for Either<A, B, C, D>
342where
343 A: ToTokens,
344 B: ToTokens,
345 C: ToTokens,
346 D: ToTokens,
347{
348 fn to_tokens(&self, tokens: &mut TokenStream) {
349 match self {
350 Either::First(a) => a.to_tokens(tokens),
351 Either::Second(b) => b.to_tokens(tokens),
352 Either::Third(c) => c.to_tokens(tokens),
353 Either::Fourth(d) => d.to_tokens(tokens),
354 }
355 }
356}
357
358#[mutants::skip]
359impl<A, B, C, D> std::fmt::Debug for Either<A, B, C, D>
360where
361 A: std::fmt::Debug,
362 B: std::fmt::Debug,
363 C: std::fmt::Debug + 'static,
364 D: std::fmt::Debug + 'static,
365{
366 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
367 let typename = match Self::used_disjunctions() {
368 1 | 2 => format!(
369 "Either<{}, {}>",
370 std::any::type_name::<A>(),
371 std::any::type_name::<B>()
372 ),
373 3 => format!(
374 "Either<{}, {}, {}>",
375 std::any::type_name::<A>(),
376 std::any::type_name::<B>(),
377 std::any::type_name::<C>()
378 ),
379 _ => format!(
380 "Either<{}, {}, {}, {}>",
381 std::any::type_name::<A>(),
382 std::any::type_name::<B>(),
383 std::any::type_name::<C>(),
384 std::any::type_name::<D>()
385 ),
386 };
387
388 match self {
389 Either::First(a) => f.debug_tuple(&typename).field(a).finish(),
390 Either::Second(b) => f.debug_tuple(&typename).field(b).finish(),
391 Either::Third(c) => f.debug_tuple(&typename).field(c).finish(),
392 Either::Fourth(d) => f.debug_tuple(&typename).field(d).finish(),
393 }
394 }
395}
396
397#[test]
398fn test_either_into_tt() {
399 use crate::{LiteralInteger, TokenTree};
400 let either = Either::<LiteralInteger, TokenTree>::First(LiteralInteger::new(42));
401 let _tt: TokenTree = either.into2();
402
403 let either = Either::<TokenTree, LiteralInteger>::Second(LiteralInteger::new(43));
404 let _tt: TokenTree = either.into2();
405}
406
407#[cfg(test)]
408mod tests {
409 use crate::*;
410 #[test]
411 fn test_cons_used_conjunctions() {
412 assert_eq!(Cons::<Punct, Ident>::used_conjunctions(), 2);
413 assert_eq!(Cons::<Punct, Ident, LiteralInteger>::used_conjunctions(), 3);
414 assert_eq!(
415 Cons::<Punct, Ident, LiteralInteger, LiteralCharacter>::used_conjunctions(),
416 4
417 );
418 }
419
420 #[test]
421 #[should_panic(expected = "If C is not Nothing then D must be Nothing")]
422 fn test_cons_invalid_nothing() {
423 Cons::<Punct, Ident, Nothing, LiteralInteger>::used_conjunctions();
424 }
425
426 #[test]
427 fn test_either_used_disjunctions() {
428 assert_eq!(Either::<Punct, Ident>::used_disjunctions(), 2);
429 assert_eq!(
430 Either::<Punct, Ident, LiteralInteger>::used_disjunctions(),
431 3
432 );
433 assert_eq!(
434 Either::<Punct, Ident, LiteralInteger, LiteralCharacter>::used_disjunctions(),
435 4
436 );
437 }
438
439 #[test]
440 #[should_panic(expected = "If C is not Invalid then D must be Invalid")]
441 fn test_either_invalid_invalid() {
442 Either::<Punct, Ident, Invalid, LiteralInteger>::used_disjunctions();
443 }
444}