structmeta_derive/
to_tokens_attribute.rs

1use proc_macro2::Span;
2use syn::{
3    parenthesized, parse::Parse, punctuated::Punctuated, spanned::Spanned, LitStr, Result, Token,
4};
5
6pub struct ToTokensAttribute {
7    pub dump: Option<Span>,
8    pub token: Vec<LitStr>,
9}
10impl Parse for ToTokensAttribute {
11    fn parse(input: syn::parse::ParseStream) -> Result<Self> {
12        let content;
13        parenthesized!(content in input);
14        let args: Punctuated<ToTokensAttributeArg, Token![,]> =
15            content.parse_terminated(ToTokensAttributeArg::parse)?;
16        let mut token = Vec::new();
17        let mut dump = None;
18        for arg in args.into_iter() {
19            match arg {
20                ToTokensAttributeArg::Token(token_value) => {
21                    token.push(token_value);
22                }
23                ToTokensAttributeArg::Dump(kw_dump) => {
24                    if dump.is_none() {
25                        dump = Some(kw_dump.span());
26                    }
27                }
28            }
29        }
30        Ok(Self { dump, token })
31    }
32}
33
34mod kw {
35    use syn::custom_keyword;
36    custom_keyword!(dump);
37}
38
39enum ToTokensAttributeArg {
40    Token(LitStr),
41    Dump(kw::dump),
42}
43impl Parse for ToTokensAttributeArg {
44    fn parse(input: syn::parse::ParseStream) -> Result<Self> {
45        if input.peek(LitStr) {
46            Ok(Self::Token(input.parse()?))
47        } else if input.peek(kw::dump) {
48            Ok(Self::Dump(input.parse()?))
49        } else {
50            Err(input.error("expected string literal."))
51        }
52    }
53}
54
55pub fn to_close(c: char) -> char {
56    match c {
57        '(' => ')',
58        '[' => ']',
59        '{' => '}',
60        _ => panic!("not found closing delimiter for {c}"),
61    }
62}