1 use proc_macro2::{Spacing, Span, TokenStream, TokenTree};
2 use quote::{quote, ToTokens};
3 use syn::Ident;
4 
5 /// Analog to Option<TokenStream>, except when put into the quote!
6 /// macro, `MaybeVoid::Void` will produce `()`
7 #[derive(Clone)]
8 pub enum MaybeVoid {
9     Some(TokenStream),
10     Void,
11 }
12 
13 impl Default for MaybeVoid {
default() -> MaybeVoid14     fn default() -> MaybeVoid {
15         MaybeVoid::Void
16     }
17 }
18 
19 impl MaybeVoid {
replace(&mut self, stream: TokenStream) -> MaybeVoid20     pub fn replace(&mut self, stream: TokenStream) -> MaybeVoid {
21         std::mem::replace(self, MaybeVoid::Some(stream))
22     }
23 
take(&mut self) -> MaybeVoid24     pub fn take(&mut self) -> MaybeVoid {
25         std::mem::replace(self, MaybeVoid::Void)
26     }
27 }
28 
29 impl ToTokens for MaybeVoid {
to_tokens(&self, out: &mut TokenStream)30     fn to_tokens(&self, out: &mut TokenStream) {
31         match self {
32             MaybeVoid::Some(stream) => out.extend(stream.clone()),
33             MaybeVoid::Void => out.extend(quote!(())),
34         }
35     }
36 
to_token_stream(&self) -> TokenStream37     fn to_token_stream(&self) -> TokenStream {
38         match self {
39             MaybeVoid::Some(stream) => stream.clone(),
40             MaybeVoid::Void => quote!(()),
41         }
42     }
43 
into_token_stream(self) -> TokenStream44     fn into_token_stream(self) -> TokenStream {
45         match self {
46             MaybeVoid::Some(stream) => stream,
47             MaybeVoid::Void => quote!(()),
48         }
49     }
50 }
51 
is_punct(tt: &TokenTree, expect: char) -> bool52 pub fn is_punct(tt: &TokenTree, expect: char) -> bool {
53     match tt {
54         TokenTree::Punct(punct)
55             if punct.as_char() == expect && punct.spacing() == Spacing::Alone =>
56         {
57             true
58         }
59         _ => false,
60     }
61 }
62 
63 /// If supplied `tt` is a punct matching a char, returns `None`, else returns `tt`
expect_punct(tt: Option<TokenTree>, expect: char) -> Option<TokenTree>64 pub fn expect_punct(tt: Option<TokenTree>, expect: char) -> Option<TokenTree> {
65     tt.filter(|tt| !is_punct(&tt, expect))
66 }
67 
68 pub trait ToIdent {
to_ident(&self) -> Ident69     fn to_ident(&self) -> Ident;
70 }
71 
72 impl ToIdent for str {
to_ident(&self) -> Ident73     fn to_ident(&self) -> Ident {
74         Ident::new(self, Span::call_site())
75     }
76 }
77