derive_attribute_utils/
syn_2.rs

1
2use std::{str::FromStr, fmt::Display};
3
4use proc_macro2::{Span, Ident};
5use syn_v2::{Attribute, Meta, MetaNameValue, Expr, ExprLit, Lit, punctuated::Punctuated, token::Eq, Token, spanned::Spanned, Path, ExprArray, PathSegment};
6
7use crate::{shared::{SynVersion, GetSpan}};
8
9/// Deserialization functions & types for Syn version 1
10pub struct Syn2;
11
12impl SynVersion for Syn2 {
13    type Attribute = Attribute;
14
15    type ArgMeta = Meta;
16
17    fn deserialize_key(meta: &Self::ArgMeta) -> Option<String> {
18        meta.path().get_ident().map(|id| id.to_string())
19    }
20    fn deserialize_attr_key(meta: &Self::Attribute) -> Option<String> {
21        meta.path().get_ident().map(|id| id.to_string())
22    }
23
24    fn deserialize_integer<T>(meta: &Self::ArgMeta) -> Option<T> 
25    where
26        T: FromStr,
27        T::Err: Display
28    {
29        match meta {
30            Meta::NameValue(MetaNameValue { value: Expr::Lit(ExprLit { lit: Lit::Int(literal), .. }), .. }) => {
31                literal.base10_parse().map_or(None, Some)
32            },
33            _ => None
34        }
35    }
36    
37    fn deserialize_float<T>(meta: &Self::ArgMeta) ->  Option<T> where T: FromStr, T::Err: Display {
38        match meta {
39            Meta::NameValue(MetaNameValue { value: Expr::Lit(ExprLit { lit: Lit::Float(literal), .. }), .. }) => {
40                literal.base10_parse().map_or(None, Some)
41            },
42            _ => None
43        }
44    }
45
46    fn deserialize_string(meta: &Self::ArgMeta) -> Option<String> {
47        match meta {
48            Meta::NameValue(MetaNameValue { value: Expr::Lit(ExprLit { lit: Lit::Str(literal), .. } ), .. }) => Some(literal.value()),
49            _ => None
50        }
51    }
52    fn deserialize_bool(meta: &Self::ArgMeta) -> Option<bool> {
53        match meta {
54            Meta::Path(_) => Some(true),
55            Meta::NameValue(MetaNameValue { value: Expr::Lit( ExprLit { lit: Lit::Bool(literal), .. } ), .. }) => Some(literal.value()),
56            _ => None
57        }
58    }
59
60    fn deserialize_list_args(meta: &Self::ArgMeta) -> Option<Vec<Self::ArgMeta>> {
61        match meta {
62            Meta::List(list) => {
63                let x = list.parse_args_with(Punctuated::<Meta, Token![,]>::parse_terminated);
64                match x {
65                    Ok(x) => Some(x.into_iter().collect()),
66                    Err(_) => None
67                }
68            },
69            _ => None
70        }
71    }
72    fn deserialize_attr_args(attr: &Self::Attribute) -> Option<Vec<Self::ArgMeta>> {
73        let maybe_args = attr.parse_args_with(Punctuated::<Meta, Token![,]>::parse_terminated);
74        match maybe_args {
75            Ok(args) => Some(args.into_iter().collect()),
76            Err(_) => None
77        }
78    }
79
80    fn deserialize_array(meta: &Self::ArgMeta) -> Option<Vec<Self::ArgMeta>> {
81        match meta {
82            Meta::NameValue(MetaNameValue { value: Expr::Array(ExprArray { elems, .. }), .. }) => {
83                let list = 
84                    elems
85                        .into_iter()
86                        .map(|e| 
87                            Meta::NameValue(
88                                MetaNameValue { 
89                                    path: 
90                                        Path { 
91                                            leading_colon: None, 
92                                            segments: 
93                                                vec![PathSegment {
94                                                    ident: Ident::new("_", e.span()), 
95                                                    arguments: syn_v2::PathArguments::None 
96                                                }]
97                                                .into_iter().collect() 
98                                        }, 
99                                    eq_token: Eq { spans: [meta.span()] }, 
100                                    value: e.clone() 
101                                }
102                            )
103                        ).collect();
104                Some(list)
105            }
106            _ => None
107        }
108    }
109
110    type Error = syn_v2::Error;
111    fn convert_error(error: crate::shared::Error) -> Self::Error {
112        syn_v2::Error::new(error.location, error.msg)
113    }
114}
115
116impl GetSpan for Attribute {
117    fn get_span(&self) -> Span { self.path().span() }
118}
119
120impl GetSpan for Meta {
121    fn get_span(&self) -> Span { self.path().span() }
122}
123