1use syn::{Lit, Type};
17
18use crate::{ArgValue, Error};
19
20#[derive(Clone, Copy, Ord, PartialOrd, Eq, PartialEq, Hash, Debug)]
22pub enum ValueClass {
23 Literal(LiteralClass),
26
27 Type(TypeClass),
30
31 Expr,
33}
34
35impl From<Lit> for ValueClass {
36 fn from(lit: Lit) -> Self { ValueClass::Literal(LiteralClass::from(lit)) }
37}
38
39impl From<&Lit> for ValueClass {
40 fn from(lit: &Lit) -> Self { ValueClass::Literal(LiteralClass::from(lit)) }
41}
42
43impl From<Type> for ValueClass {
44 fn from(ty: Type) -> Self { ValueClass::Type(TypeClass::from(ty)) }
45}
46
47impl From<&Type> for ValueClass {
48 fn from(ty: &Type) -> Self { ValueClass::Type(TypeClass::from(ty)) }
49}
50
51impl From<LiteralClass> for ValueClass {
52 fn from(cls: LiteralClass) -> Self { ValueClass::Literal(cls) }
53}
54
55impl From<TypeClass> for ValueClass {
56 fn from(cls: TypeClass) -> Self { ValueClass::Type(cls) }
57}
58
59impl ValueClass {
60 pub fn str() -> ValueClass { ValueClass::Literal(LiteralClass::Str) }
63
64 pub fn byte_str() -> ValueClass { ValueClass::Literal(LiteralClass::ByteStr) }
67
68 pub fn byte() -> ValueClass { ValueClass::Literal(LiteralClass::Byte) }
71
72 pub fn int() -> ValueClass { ValueClass::Literal(LiteralClass::Int) }
75
76 pub fn float() -> ValueClass { ValueClass::Literal(LiteralClass::Float) }
79
80 pub fn char() -> ValueClass { ValueClass::Literal(LiteralClass::Char) }
83
84 pub fn bool() -> ValueClass { ValueClass::Literal(LiteralClass::Bool) }
87}
88
89impl ValueClass {
90 pub fn check(
93 self,
94 value: &ArgValue,
95 attr: impl ToString,
96 arg: impl ToString,
97 ) -> Result<(), Error> {
98 match (self, value) {
99 (ValueClass::Literal(lit), ArgValue::Literal(ref value)) => lit.check(value, attr, arg),
100 (ValueClass::Type(ty), ArgValue::Type(ref value)) => ty.check(value, attr, arg),
101 (ValueClass::Expr, ArgValue::Type(_) | ArgValue::Expr(_) | ArgValue::Literal(_)) => {
102 Ok(())
103 }
104 _ => Err(Error::ArgValueTypeMismatch {
105 attr: attr.to_string(),
106 arg: arg.to_string(),
107 }),
108 }
109 }
110}
111
112#[derive(Clone, Copy, Ord, PartialOrd, Eq, PartialEq, Hash, Debug)]
114pub enum LiteralClass {
115 Str,
117
118 ByteStr,
120
121 Byte,
123
124 Char,
126
127 Int,
129
130 Float,
132
133 Bool,
135
136 Any,
138}
139
140impl From<Lit> for LiteralClass {
141 #[inline]
142 fn from(lit: Lit) -> Self { LiteralClass::from(&lit) }
143}
144
145impl From<&Lit> for LiteralClass {
146 fn from(lit: &Lit) -> Self {
147 match lit {
148 Lit::Str(_) => LiteralClass::Str,
149 Lit::ByteStr(_) => LiteralClass::ByteStr,
150 Lit::Byte(_) => LiteralClass::Byte,
151 Lit::Char(_) => LiteralClass::Char,
152 Lit::Int(_) => LiteralClass::Int,
153 Lit::Float(_) => LiteralClass::Float,
154 Lit::Bool(_) => LiteralClass::Bool,
155 Lit::Verbatim(_) => LiteralClass::Any,
156 }
157 }
158}
159
160impl LiteralClass {
161 pub fn check(self, lit: &Lit, attr: impl ToString, arg: impl ToString) -> Result<(), Error> {
164 if self == LiteralClass::Any {
165 Ok(())
166 } else if self != LiteralClass::from(lit) {
167 Err(Error::ArgValueTypeMismatch {
168 attr: attr.to_string(),
169 arg: arg.to_string(),
170 })
171 } else {
172 Ok(())
173 }
174 }
175}
176
177#[derive(Clone, Copy, Ord, PartialOrd, Eq, PartialEq, Hash, Debug)]
179pub enum TypeClass {
180 Array,
182
183 BareFn,
185
186 Group,
188
189 ImplTrait,
192
193 Infer,
195
196 Macro,
198
199 Never,
201
202 Paren,
204
205 Path,
208
209 Ptr,
211
212 Reference,
214
215 Slice,
217
218 TraitObject,
221
222 Tuple,
224
225 Any,
227}
228
229impl From<Type> for TypeClass {
230 #[inline]
231 fn from(ty: Type) -> Self { TypeClass::from(&ty) }
232}
233
234impl From<&Type> for TypeClass {
235 fn from(ty: &Type) -> Self {
236 match ty {
237 Type::Array(_) => TypeClass::Array,
238 Type::BareFn(_) => TypeClass::BareFn,
239 Type::Group(_) => TypeClass::Group,
240 Type::ImplTrait(_) => TypeClass::ImplTrait,
241 Type::Infer(_) => TypeClass::Infer,
242 Type::Macro(_) => TypeClass::Macro,
243 Type::Never(_) => TypeClass::Never,
244 Type::Paren(_) => TypeClass::Paren,
245 Type::Path(_) => TypeClass::Path,
246 Type::Ptr(_) => TypeClass::Ptr,
247 Type::Reference(_) => TypeClass::Reference,
248 Type::Slice(_) => TypeClass::Slice,
249 Type::TraitObject(_) => TypeClass::TraitObject,
250 Type::Tuple(_) => TypeClass::Tuple,
251 Type::Verbatim(_) => TypeClass::Any,
252 _ => unreachable!(),
253 }
254 }
255}
256
257impl TypeClass {
258 pub fn check(self, ty: &Type, attr: impl ToString, arg: impl ToString) -> Result<(), Error> {
261 if self == TypeClass::Any {
262 Ok(())
263 } else if self != TypeClass::from(ty) {
264 Err(Error::ArgValueTypeMismatch {
265 attr: attr.to_string(),
266 arg: arg.to_string(),
267 })
268 } else {
269 Ok(())
270 }
271 }
272}