structmeta_derive/
to_tokens_attribute.rs1use 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}