macro_input_core/
convert.rs1use proc_macro2::Ident;
2use syn::{Error, Lit, Meta, NestedMeta, Result};
3
4pub trait FromMeta: Sized {
6 fn from(meta: Option<Meta>) -> Result<Self>;
11}
12
13impl FromMeta for Option<()> {
14 fn from(meta: Option<Meta>) -> Result<Self> {
15 meta.map_or(Ok(None), |m| {
16 if matches!(m, Meta::Path(_)) {
17 Ok(Some(()))
18 } else {
19 Err(Error::new_spanned(m, "unexpected value"))
20 }
21 })
22 }
23}
24
25impl FromMeta for Vec<Ident> {
26 fn from(meta: Option<Meta>) -> Result<Self> {
27 meta.map_or(Ok(Vec::new()), |m| {
28 if let Meta::List(list) = m {
29 list.nested
30 .iter()
31 .map(|m| {
32 if let NestedMeta::Meta(Meta::Path(m)) = m {
33 m.get_ident()
34 .cloned()
35 .ok_or_else(|| Error::new_spanned(m, "expected ident"))
36 } else {
37 Err(Error::new_spanned(m, "expected ident"))
38 }
39 })
40 .collect()
41 } else {
42 Err(Error::new_spanned(m, "expected idents"))
43 }
44 })
45 }
46}
47
48impl FromMeta for Option<Vec<Ident>> {
49 fn from(meta: Option<Meta>) -> Result<Self> {
50 meta.map_or(Ok(None), |m| {
51 if let Meta::List(list) = m {
52 list.nested
53 .iter()
54 .map(|m| {
55 if let NestedMeta::Meta(Meta::Path(m)) = m {
56 m.get_ident()
57 .cloned()
58 .ok_or_else(|| Error::new_spanned(m, "expected ident"))
59 } else {
60 Err(Error::new_spanned(m, "expected ident"))
61 }
62 })
63 .collect::<Result<_>>()
64 .map(Some)
65 } else {
66 Err(Error::new_spanned(m, "expected idents"))
67 }
68 })
69 }
70}
71
72pub trait FromLit: Sized {
76 fn from(lit: Option<Lit>) -> Result<Self>;
81}
82
83impl<F: FromLit> FromMeta for F {
84 fn from(meta: Option<Meta>) -> Result<Self> {
85 let lit = meta
86 .map(|m| match m {
87 Meta::NameValue(mnv) => Ok(mnv.lit),
88 _ => Err(Error::new_spanned(m, "expected named value")),
89 })
90 .transpose()?;
91 Self::from(lit)
92 }
93}
94
95impl FromLit for Option<Lit> {
96 fn from(lit: Option<Lit>) -> Result<Self> {
97 Ok(lit)
98 }
99}
100
101impl FromLit for String {
102 fn from(lit: Option<Lit>) -> Result<Self> {
103 if let Some(Lit::Str(v)) = lit {
104 Ok(v.value())
105 } else {
106 Err(Error::new_spanned(lit, "expected string"))
107 }
108 }
109}
110
111impl FromLit for Vec<u8> {
112 fn from(lit: Option<Lit>) -> Result<Self> {
113 if let Some(Lit::ByteStr(v)) = lit {
114 Ok(v.value())
115 } else {
116 Err(Error::new_spanned(lit, "expected bytes"))
117 }
118 }
119}
120
121impl FromLit for u8 {
122 fn from(lit: Option<Lit>) -> Result<Self> {
123 if let Some(Lit::Byte(v)) = lit {
124 Ok(v.value())
125 } else {
126 Err(Error::new_spanned(lit, "expected byte"))
127 }
128 }
129}
130
131impl FromLit for char {
132 fn from(lit: Option<Lit>) -> Result<Self> {
133 if let Some(Lit::Char(v)) = lit {
134 Ok(v.value())
135 } else {
136 Err(Error::new_spanned(lit, "expected char"))
137 }
138 }
139}
140
141impl FromLit for i32 {
142 fn from(lit: Option<Lit>) -> Result<Self> {
143 if let Some(Lit::Int(v)) = &lit {
144 v.base10_parse()
145 } else {
146 Err(Error::new_spanned(lit, "expected i32"))
147 }
148 }
149}
150
151impl FromLit for f32 {
152 fn from(lit: Option<Lit>) -> Result<Self> {
153 if let Some(Lit::Float(v)) = &lit {
154 v.base10_parse()
155 } else {
156 Err(Error::new_spanned(lit, "expected f32"))
157 }
158 }
159}
160
161impl FromLit for bool {
162 fn from(lit: Option<Lit>) -> Result<Self> {
163 if let Some(Lit::Bool(v)) = lit {
164 Ok(v.value)
165 } else {
166 Err(Error::new_spanned(lit, "expected bool"))
167 }
168 }
169}
170
171impl<V: FromLit> FromLit for Option<V> {
172 fn from(lit: Option<Lit>) -> Result<Self> {
173 if lit.is_some() {
174 Some(V::from(lit)).transpose()
175 } else {
176 Ok(None)
177 }
178 }
179}