1use proc_macro2::{TokenTree, TokenStream};
2
3use crate::{FromMacro, abort, Error};
4
5#[derive(Debug)]
10pub enum OneOrMany<TOne, TMany>{
11 One(TOne),
12 Many(TMany),
13}
14
15impl<TOne, TMany> FromMacro for OneOrMany<TOne, TMany> where TOne: FromMacro, TMany: FromMacro{
16 fn from_one(tt: TokenTree) -> Result<Self, Error> {
17 Ok(Self::One(TOne::from_one(tt)?))
18 }
19
20 fn from_many(tokens: TokenStream) -> Result<Self, Error> {
21 Ok(Self::Many(TMany::from_many(tokens)?))
22 }
23}
24
25pub type EitherStream = OneOrMany<TokenTree, TokenStream>;
27
28
29
30macro_rules! impl_choice {
31 ($name: ident {$($fields: ident),*}) => {
32
33#[derive(Debug)]
37pub enum $name<$($fields: FromMacro),*>{
38 $($fields($fields)),*
39}
40
41impl<$($fields),*> FromMacro for $name<$($fields),*> where $($fields: FromMacro),* {
42 fn from_one(tt: proc_macro2::TokenTree) -> Result<Self, crate::Error> {
43 let span = tt.span();
44 $(
45 if $fields::peek(&tt) {
46 if let Ok(x) = $fields::from_one(tt.clone()) {
47 return Ok(Self::$fields(x));
48 }
49 }
50 )*
51 abort!(span, FailedToMatch(tt.to_string()))
52 }
53
54 fn from_many(tokens: proc_macro2::TokenStream) -> Result<Self, crate::Error> {
55 $(if let Ok(x) = $fields::from_many(tokens.clone()) {
56 return Ok(Self::$fields(x));
57 })*
58 abort!(call_site, FailedToMatch(tokens.to_string()))
59 }
60}
61
62impl<$($fields),*> Default for $name<$($fields),*> where A: Default, $($fields: FromMacro),*{
63 fn default() -> Self {
64 Self::A(A::default())
65 }
66}
67
68
69#[cfg(feature="quote")]
70impl<$($fields),*> quote::ToTokens for $name<$($fields),*>where $($fields: FromMacro + quote::ToTokens),*{
71 #[allow(nonstandard_style)]
72 fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
73 match self {
74 $($name::$fields($fields) => $fields.to_tokens(tokens)),*
75 }
76 }
77}
78 };
79}
80
81impl_choice!(Either {A, B});
82impl_choice!(Either3 {A, B, C});
83impl_choice!(Either4 {A, B, C, D});
84impl_choice!(Either5 {A, B, C, D, E});
85impl_choice!(Either6 {A, B, C, D, E, F});
86impl_choice!(Either7 {A, B, C, D, E, F, G});
87impl_choice!(Either8 {A, B, C, D, E, F, G, H});
88impl_choice!(Either9 {A, B, C, D, E, F, G, H, I});
89