1use crate::*;
2
3pub trait ExprExt {
4 fn as_string(&self) -> syn::Result<String>;
5 fn as_path(&self) -> syn::Result<&Path>;
6 fn as_int<N>(&self) -> syn::Result<N>
7 where
8 N: FromStr,
9 N::Err: Display;
10 fn as_closure(&self) -> syn::Result<&ExprClosure>;
11 fn as_call_or_closure(&self) -> syn::Result<CallOrClosure>;
12 fn as_call(&self) -> syn::Result<&ExprCall>;
13 fn as_path_or_closure(&self) -> syn::Result<PathOrClosure>;
14 fn as_range(&self) -> syn::Result<&ExprRange>;
15}
16
17impl ExprExt for Expr {
18 fn as_range(&self) -> syn::Result<&ExprRange> {
19 if let Expr::Range(range) = &self {
20 Ok(range)
21 } else {
22 Err(error!(self, "Expected a range expression"))
23 }
24 }
25
26 fn as_path_or_closure(&self) -> syn::Result<PathOrClosure> {
27 match self {
28 Expr::Closure(closure) => Ok(PathOrClosure::Closure(closure.to_token_stream())),
29 Expr::Path(expr_path) => Ok(PathOrClosure::Path(expr_path.path.to_token_stream())),
30 _ => Err(error!(self, "Expected a path or a closure")),
31 }
32 }
33
34 fn as_call(&self) -> syn::Result<&ExprCall> {
35 if let Expr::Call(call) = self {
36 Ok(call)
37 } else {
38 Err(error!(self, "Expected a function call"))
39 }
40 }
41 fn as_string(&self) -> syn::Result<String> {
42 if let Expr::Lit(expr_lit) = self && let Lit::Str(value) = &expr_lit.lit {
43 Ok(value.value())
44 } else {
45 Err(error!(self, "Expected a string literal"))
46 }
47 }
48
49 fn as_path(&self) -> syn::Result<&Path> {
50 if let Expr::Path(expr_path) = self {
51 Ok(&expr_path.path)
52 } else {
53 Err(error!(self, "Expected a path"))
54 }
55 }
56
57 fn as_int<N>(&self) -> syn::Result<N>
58 where
59 N: FromStr,
60 N::Err: Display,
61 {
62 if let Expr::Lit(expr_lit) = self && let Lit::Int(value) = &expr_lit.lit {
63 Ok(value.base10_parse::<N>()?)
64 } else {
65 Err(error!(self, "Expected an integer literal"))
66 }
67 }
68
69 fn as_closure(&self) -> syn::Result<&ExprClosure> {
70 if let Expr::Closure(closure) = self {
71 Ok(closure)
72 } else {
73 Err(error!(self, "Expected a closure"))
74 }
75 }
76
77 fn as_call_or_closure(&self) -> syn::Result<CallOrClosure> {
78 match self {
79 Expr::Closure(closure) => Ok(CallOrClosure::Closure(closure.to_token_stream())),
80 Expr::Call(call) => Ok(CallOrClosure::Call(call.to_token_stream())),
81 _ => Err(error!(self, "Expected a function call or a closure")),
82 }
83 }
84}