1use proc_macro2::{Spacing, Span, TokenStream, TokenTree};
2use quote::{quote, ToTokens};
3use syn::Ident;
4
5#[derive(Clone, Default)]
8pub enum MaybeVoid {
9 Some(TokenStream),
10 #[default]
11 Void,
12}
13
14impl MaybeVoid {
15 pub fn replace(&mut self, stream: TokenStream) -> MaybeVoid {
16 std::mem::replace(self, MaybeVoid::Some(stream))
17 }
18
19 pub fn take(&mut self) -> MaybeVoid {
20 std::mem::replace(self, MaybeVoid::Void)
21 }
22}
23
24impl ToTokens for MaybeVoid {
25 fn to_tokens(&self, out: &mut TokenStream) {
26 match self {
27 MaybeVoid::Some(stream) => out.extend(stream.clone()),
28 MaybeVoid::Void => out.extend(quote!(())),
29 }
30 }
31
32 fn to_token_stream(&self) -> TokenStream {
33 match self {
34 MaybeVoid::Some(stream) => stream.clone(),
35 MaybeVoid::Void => quote!(()),
36 }
37 }
38
39 fn into_token_stream(self) -> TokenStream {
40 match self {
41 MaybeVoid::Some(stream) => stream,
42 MaybeVoid::Void => quote!(()),
43 }
44 }
45}
46
47pub fn is_punct(tt: &TokenTree, expect: char) -> bool {
48 matches!(tt, TokenTree::Punct(punct) if punct.as_char() == expect && punct.spacing() == Spacing::Alone)
49}
50
51pub fn expect_punct(tt: Option<TokenTree>, expect: char) -> Option<TokenTree> {
53 tt.filter(|tt| !is_punct(tt, expect))
54}
55
56pub trait ToIdent {
57 fn to_ident(&self) -> Ident;
58}
59
60impl ToIdent for str {
61 fn to_ident(&self) -> Ident {
62 Ident::new(self, Span::call_site())
63 }
64}