1use std::convert::TryFrom;
17use std::fmt::{self, Debug, Formatter};
18
19use proc_macro2::Span;
20use quote::ToTokens;
21use syn::parse::{Parse, Parser};
22use syn::{
23 Expr, Ident, Lit, LitBool, LitByteStr, LitChar, LitFloat, LitInt, LitStr, Path, PathSegment,
24 Type, TypePath,
25};
26
27use crate::{Error, ValueClass};
28
29#[derive(Clone)]
33pub enum ArgValue {
34 Literal(Lit),
36
37 Type(Type),
39
40 Expr(Expr),
42
43 None,
45}
46
47impl Debug for ArgValue {
48 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
49 match self {
50 ArgValue::Literal(lit) => write!(f, "ArgValue::Literal({})", lit.to_token_stream()),
51 ArgValue::Type(ty) => write!(f, "ArgValue::Type({})", ty.to_token_stream()),
52 ArgValue::Expr(expr) => write!(f, "ArgValue::Expr({})", expr.to_token_stream()),
53 ArgValue::None => f.write_str("ArgValue::None"),
54 }
55 }
56}
57
58impl From<&str> for ArgValue {
59 fn from(val: &str) -> Self { ArgValue::Literal(Lit::Str(LitStr::new(val, Span::call_site()))) }
60}
61
62impl From<String> for ArgValue {
63 fn from(val: String) -> Self {
64 ArgValue::Literal(Lit::Str(LitStr::new(&val, Span::call_site())))
65 }
66}
67
68impl From<&[u8]> for ArgValue {
69 fn from(val: &[u8]) -> Self {
70 ArgValue::Literal(Lit::ByteStr(LitByteStr::new(val, Span::call_site())))
71 }
72}
73
74impl From<Vec<u8>> for ArgValue {
75 fn from(val: Vec<u8>) -> Self {
76 ArgValue::Literal(Lit::ByteStr(LitByteStr::new(&val, Span::call_site())))
77 }
78}
79
80impl From<char> for ArgValue {
81 fn from(val: char) -> Self {
82 ArgValue::Literal(Lit::Char(LitChar::new(val, Span::call_site())))
83 }
84}
85
86impl From<usize> for ArgValue {
87 fn from(val: usize) -> Self {
88 ArgValue::Literal(Lit::Int(LitInt::new(&val.to_string(), Span::call_site())))
89 }
90}
91
92impl From<isize> for ArgValue {
93 fn from(val: isize) -> Self {
94 ArgValue::Literal(Lit::Int(LitInt::new(&val.to_string(), Span::call_site())))
95 }
96}
97
98impl From<f64> for ArgValue {
99 fn from(val: f64) -> Self {
100 ArgValue::Literal(Lit::Float(LitFloat::new(&val.to_string(), Span::call_site())))
101 }
102}
103
104impl From<bool> for ArgValue {
105 fn from(val: bool) -> Self {
106 ArgValue::Literal(Lit::Bool(LitBool::new(val, Span::call_site())))
107 }
108}
109
110impl From<Option<LitStr>> for ArgValue {
111 fn from(val: Option<LitStr>) -> Self {
112 match val {
113 Some(val) => ArgValue::Literal(Lit::Str(val)),
114 None => ArgValue::None,
115 }
116 }
117}
118
119impl From<Ident> for ArgValue {
120 fn from(ident: Ident) -> Self {
121 Path::from(PathSegment::parse.parse2(quote! { #ident }.into()).unwrap()).into()
122 }
123}
124
125impl From<Path> for ArgValue {
126 fn from(path: Path) -> Self { ArgValue::Type(Type::Path(TypePath { qself: None, path })) }
127}
128
129impl From<Option<LitByteStr>> for ArgValue {
130 fn from(val: Option<LitByteStr>) -> Self {
131 match val {
132 Some(val) => ArgValue::Literal(Lit::ByteStr(val)),
133 None => ArgValue::None,
134 }
135 }
136}
137
138impl From<Option<LitBool>> for ArgValue {
139 fn from(val: Option<LitBool>) -> Self {
140 match val {
141 Some(val) => ArgValue::Literal(Lit::Bool(val)),
142 None => ArgValue::None,
143 }
144 }
145}
146
147impl From<Option<LitChar>> for ArgValue {
148 fn from(val: Option<LitChar>) -> Self {
149 match val {
150 Some(val) => ArgValue::Literal(Lit::Char(val)),
151 None => ArgValue::None,
152 }
153 }
154}
155
156impl From<Option<LitInt>> for ArgValue {
157 fn from(val: Option<LitInt>) -> Self {
158 match val {
159 Some(val) => ArgValue::Literal(Lit::Int(val)),
160 None => ArgValue::None,
161 }
162 }
163}
164
165impl From<Option<LitFloat>> for ArgValue {
166 fn from(val: Option<LitFloat>) -> Self {
167 match val {
168 Some(val) => ArgValue::Literal(Lit::Float(val)),
169 None => ArgValue::None,
170 }
171 }
172}
173
174impl TryFrom<ArgValue> for String {
175 type Error = Error;
176
177 fn try_from(value: ArgValue) -> Result<Self, Self::Error> {
178 match value {
179 ArgValue::Literal(Lit::Str(s)) => Ok(s.value()),
180 _ => Err(Error::ArgValueMustBeLiteral),
181 }
182 }
183}
184
185impl TryFrom<ArgValue> for Vec<u8> {
186 type Error = Error;
187
188 fn try_from(value: ArgValue) -> Result<Self, Self::Error> {
189 match value {
190 ArgValue::Literal(Lit::ByteStr(s)) => Ok(s.value()),
191 _ => Err(Error::ArgValueMustBeLiteral),
192 }
193 }
194}
195
196impl TryFrom<ArgValue> for bool {
197 type Error = Error;
198
199 fn try_from(value: ArgValue) -> Result<Self, Self::Error> {
200 match value {
201 ArgValue::Literal(Lit::Bool(b)) => Ok(b.value),
202 _ => Err(Error::ArgValueMustBeLiteral),
203 }
204 }
205}
206
207impl TryFrom<ArgValue> for char {
208 type Error = Error;
209
210 fn try_from(value: ArgValue) -> Result<Self, Self::Error> {
211 match value {
212 ArgValue::Literal(Lit::Char(c)) => Ok(c.value()),
213 _ => Err(Error::ArgValueMustBeLiteral),
214 }
215 }
216}
217
218impl TryFrom<ArgValue> for LitStr {
219 type Error = Error;
220
221 fn try_from(value: ArgValue) -> Result<Self, Self::Error> {
222 match value {
223 ArgValue::Literal(Lit::Str(s)) => Ok(s),
224 _ => Err(Error::ArgValueMustBeLiteral),
225 }
226 }
227}
228
229impl TryFrom<ArgValue> for LitByteStr {
230 type Error = Error;
231
232 fn try_from(value: ArgValue) -> Result<Self, Self::Error> {
233 match value {
234 ArgValue::Literal(Lit::ByteStr(s)) => Ok(s),
235 _ => Err(Error::ArgValueMustBeLiteral),
236 }
237 }
238}
239
240impl TryFrom<ArgValue> for LitBool {
241 type Error = Error;
242
243 fn try_from(value: ArgValue) -> Result<Self, Self::Error> {
244 match value {
245 ArgValue::Literal(Lit::Bool(s)) => Ok(s),
246 _ => Err(Error::ArgValueMustBeLiteral),
247 }
248 }
249}
250
251impl TryFrom<ArgValue> for LitChar {
252 type Error = Error;
253
254 fn try_from(value: ArgValue) -> Result<Self, Self::Error> {
255 match value {
256 ArgValue::Literal(Lit::Char(c)) => Ok(c),
257 _ => Err(Error::ArgValueMustBeLiteral),
258 }
259 }
260}
261
262impl TryFrom<ArgValue> for LitInt {
263 type Error = Error;
264
265 fn try_from(value: ArgValue) -> Result<Self, Self::Error> {
266 match value {
267 ArgValue::Literal(Lit::Int(i)) => Ok(i),
268 _ => Err(Error::ArgValueMustBeLiteral),
269 }
270 }
271}
272
273impl TryFrom<ArgValue> for LitFloat {
274 type Error = Error;
275
276 fn try_from(value: ArgValue) -> Result<Self, Self::Error> {
277 match value {
278 ArgValue::Literal(Lit::Float(f)) => Ok(f),
279 _ => Err(Error::ArgValueMustBeLiteral),
280 }
281 }
282}
283
284impl TryFrom<ArgValue> for Ident {
285 type Error = Error;
286
287 fn try_from(value: ArgValue) -> Result<Self, Self::Error> {
288 match value {
289 ArgValue::Type(Type::Path(ty)) => {
290 if let Some(ident) = ty.path.get_ident() {
291 Ok(ident.clone())
292 } else {
293 Err(Error::ArgValueMustBeType)
294 }
295 }
296 _ => Err(Error::ArgValueMustBeType),
297 }
298 }
299}
300
301impl TryFrom<ArgValue> for Path {
302 type Error = Error;
303
304 fn try_from(value: ArgValue) -> Result<Self, Self::Error> {
305 match value {
306 ArgValue::Expr(expr) => Path::parse
307 .parse2(expr.to_token_stream().into())
308 .map_err(Error::from),
309 ArgValue::Type(Type::Path(ty)) => Ok(ty.path),
310 _ => Err(Error::ArgValueMustBeType),
311 }
312 }
313}
314
315impl TryFrom<ArgValue> for Expr {
316 type Error = Error;
317
318 fn try_from(value: ArgValue) -> Result<Self, Self::Error> {
319 match value {
320 ArgValue::Literal(lit) => Expr::parse
321 .parse2(lit.to_token_stream().into())
322 .map_err(Error::from),
323 ArgValue::Type(ty) => Expr::parse
324 .parse2(ty.to_token_stream().into())
325 .map_err(Error::from),
326 ArgValue::Expr(expr) => Ok(expr),
327 ArgValue::None => Err(Error::ArgValueMustBeExpr),
328 }
329 }
330}
331
332impl TryFrom<ArgValue> for Option<LitStr> {
333 type Error = Error;
334
335 fn try_from(value: ArgValue) -> Result<Self, Self::Error> {
336 match value {
337 ArgValue::Literal(Lit::Str(s)) => Ok(Some(s)),
338 ArgValue::None => Ok(None),
339 _ => Err(Error::ArgValueMustBeLiteral),
340 }
341 }
342}
343
344impl TryFrom<ArgValue> for Option<LitByteStr> {
345 type Error = Error;
346
347 fn try_from(value: ArgValue) -> Result<Self, Self::Error> {
348 match value {
349 ArgValue::Literal(Lit::ByteStr(s)) => Ok(Some(s)),
350 ArgValue::None => Ok(None),
351 _ => Err(Error::ArgValueMustBeLiteral),
352 }
353 }
354}
355
356impl TryFrom<ArgValue> for Option<LitBool> {
357 type Error = Error;
358
359 fn try_from(value: ArgValue) -> Result<Self, Self::Error> {
360 match value {
361 ArgValue::Literal(Lit::Bool(b)) => Ok(Some(b)),
362 ArgValue::None => Ok(None),
363 _ => Err(Error::ArgValueMustBeLiteral),
364 }
365 }
366}
367
368impl TryFrom<ArgValue> for Option<LitChar> {
369 type Error = Error;
370
371 fn try_from(value: ArgValue) -> Result<Self, Self::Error> {
372 match value {
373 ArgValue::Literal(Lit::Char(c)) => Ok(Some(c)),
374 ArgValue::None => Ok(None),
375 _ => Err(Error::ArgValueMustBeLiteral),
376 }
377 }
378}
379
380impl TryFrom<ArgValue> for Option<LitInt> {
381 type Error = Error;
382
383 fn try_from(value: ArgValue) -> Result<Self, Self::Error> {
384 match value {
385 ArgValue::Literal(Lit::Int(i)) => Ok(Some(i)),
386 ArgValue::None => Ok(None),
387 _ => Err(Error::ArgValueMustBeLiteral),
388 }
389 }
390}
391
392impl TryFrom<ArgValue> for Option<LitFloat> {
393 type Error = Error;
394
395 fn try_from(value: ArgValue) -> Result<Self, Self::Error> {
396 match value {
397 ArgValue::Literal(Lit::Float(f)) => Ok(Some(f)),
398 ArgValue::None => Ok(None),
399 _ => Err(Error::ArgValueMustBeLiteral),
400 }
401 }
402}
403
404impl TryFrom<ArgValue> for Option<Ident> {
405 type Error = Error;
406
407 fn try_from(value: ArgValue) -> Result<Self, Self::Error> {
408 match value {
409 ArgValue::Type(Type::Path(ty)) => {
410 if let Some(ident) = ty.path.get_ident() {
411 Ok(Some(ident.clone()))
412 } else {
413 Err(Error::ArgValueMustBeType)
414 }
415 }
416 ArgValue::None => Ok(None),
417 _ => Err(Error::ArgValueMustBeType),
418 }
419 }
420}
421
422impl TryFrom<ArgValue> for Option<Path> {
423 type Error = Error;
424
425 fn try_from(value: ArgValue) -> Result<Self, Self::Error> {
426 match value {
427 ArgValue::Type(Type::Path(ty)) => Ok(Some(ty.path)),
428 ArgValue::Expr(expr) => Some(
429 Path::parse
430 .parse2(expr.into_token_stream().into())
431 .map_err(Error::from),
432 )
433 .transpose(),
434 ArgValue::None => Ok(None),
435 _ => Err(Error::ArgValueMustBeType),
436 }
437 }
438}
439
440impl TryFrom<ArgValue> for Option<Expr> {
441 type Error = Error;
442
443 fn try_from(value: ArgValue) -> Result<Self, Self::Error> {
444 match value {
445 ArgValue::Expr(expr) => Ok(Some(expr)),
446 ArgValue::Type(ty) => Some(
447 Expr::parse
448 .parse2(ty.into_token_stream().into())
449 .map_err(Error::from),
450 )
451 .transpose(),
452 ArgValue::Literal(lit) => Some(
453 Expr::parse
454 .parse2(lit.into_token_stream().into())
455 .map_err(Error::from),
456 )
457 .transpose(),
458 ArgValue::None => Ok(None),
459 }
460 }
461}
462
463impl ArgValue {
464 #[inline]
467 pub fn into_literal_value(self) -> Result<Lit, Error> {
468 match self {
469 ArgValue::Literal(lit) => Ok(lit),
470 ArgValue::Type(_) | ArgValue::Expr(_) | ArgValue::None => {
471 Err(Error::ArgValueMustBeLiteral)
472 }
473 }
474 }
475
476 #[inline]
479 pub fn into_type_value(self) -> Result<Type, Error> {
480 match self {
481 ArgValue::Literal(_) | ArgValue::Expr(_) | ArgValue::None => {
482 Err(Error::ArgValueMustBeType)
483 }
484 ArgValue::Type(ty) => Ok(ty),
485 }
486 }
487
488 #[inline]
491 pub fn into_type_expr(self) -> Result<Expr, Error> {
492 match self {
493 ArgValue::Literal(_) | ArgValue::Type(_) | ArgValue::None => {
494 Err(Error::ArgValueMustBeExpr)
495 }
496 ArgValue::Expr(expr) => Ok(expr),
497 }
498 }
499
500 #[inline]
503 pub fn to_literal_value(&self) -> Result<Lit, Error> {
504 match self {
505 ArgValue::Literal(lit) => Ok(lit.clone()),
506 ArgValue::Type(_) | ArgValue::Expr(_) | ArgValue::None => {
507 Err(Error::ArgValueMustBeLiteral)
508 }
509 }
510 }
511
512 #[inline]
515 pub fn to_type_value(&self) -> Result<Type, Error> {
516 match self {
517 ArgValue::Literal(_) | ArgValue::Expr(_) | ArgValue::None => {
518 Err(Error::ArgValueMustBeType)
519 }
520 ArgValue::Type(ty) => Ok(ty.clone()),
521 }
522 }
523
524 #[inline]
527 pub fn to_type_expr(&self) -> Result<Expr, Error> {
528 match self {
529 ArgValue::Literal(_) | ArgValue::Type(_) | ArgValue::None => {
530 Err(Error::ArgValueMustBeExpr)
531 }
532 ArgValue::Expr(expr) => Ok(expr.clone()),
533 }
534 }
535
536 #[inline]
539 pub fn as_literal_value(&self) -> Option<&Lit> {
540 match self {
541 ArgValue::Literal(ref lit) => Some(lit),
542 ArgValue::Type(_) | ArgValue::Expr(_) | ArgValue::None => None,
543 }
544 }
545
546 #[inline]
549 pub fn as_type_value(&self) -> Option<&Type> {
550 match self {
551 ArgValue::Literal(_) | ArgValue::Expr(_) | ArgValue::None => None,
552 ArgValue::Type(ref ty) => Some(ty),
553 }
554 }
555
556 #[inline]
559 pub fn as_type_expr(&self) -> Option<&Expr> {
560 match self {
561 ArgValue::Literal(_) | ArgValue::Type(_) | ArgValue::None => None,
562 ArgValue::Expr(ref expr) => Some(expr),
563 }
564 }
565
566 #[inline]
568 pub fn is_none(&self) -> bool {
569 #[allow(clippy::match_like_matches_macro)]
570 match self {
572 ArgValue::None => true,
573 _ => false,
574 }
575 }
576
577 #[inline]
579 pub fn is_some(&self) -> bool {
580 #[allow(clippy::match_like_matches_macro)]
582 match self {
583 ArgValue::None => false,
584 _ => true,
585 }
586 }
587
588 #[inline]
590 pub fn value_class(&self) -> Option<ValueClass> {
591 match self {
592 ArgValue::Literal(lit) => Some(ValueClass::from(lit)),
593 ArgValue::Type(ty) => Some(ValueClass::from(ty)),
594 ArgValue::Expr(_) => Some(ValueClass::Expr),
595 ArgValue::None => None,
596 }
597 }
598}