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