darling_core/util/
callable.rs1use quote::ToTokens;
2use syn::{parse::Parse, Expr, ExprClosure, ExprLit, ExprPath, Lit, Path};
3
4use crate::{Error, FromMeta, Result};
5
6#[derive(Debug, Clone)]
17pub struct Callable {
18 call: Expr,
20}
21
22impl AsRef<Expr> for Callable {
23 fn as_ref(&self) -> &Expr {
24 &self.call
25 }
26}
27
28impl From<Path> for Callable {
29 fn from(path: Path) -> Self {
30 Self::from(ExprPath {
31 attrs: vec![],
32 qself: None,
33 path,
34 })
35 }
36}
37
38impl From<ExprPath> for Callable {
39 fn from(value: ExprPath) -> Self {
40 Self {
41 call: Expr::Path(value),
42 }
43 }
44}
45
46impl From<ExprClosure> for Callable {
47 fn from(value: ExprClosure) -> Self {
48 Self {
49 call: Expr::Closure(value),
50 }
51 }
52}
53
54impl Parse for Callable {
55 fn parse(input: syn::parse::ParseStream<'_>) -> syn::Result<Self> {
56 Ok(Self {
57 call: input.parse()?,
58 })
59 }
60}
61
62impl From<Callable> for Expr {
63 fn from(value: Callable) -> Self {
64 value.call
65 }
66}
67
68impl FromMeta for Callable {
69 fn from_expr(expr: &Expr) -> Result<Self> {
70 match expr {
71 Expr::Path(_) | Expr::Closure(_) => Ok(Self { call: expr.clone() }),
72 Expr::Lit(ExprLit {
73 lit: Lit::Str(s), ..
74 }) => s
75 .parse::<Path>()
76 .map_err(|e| {
77 Error::custom(format!("must be a path if it's a string: {}", e)).with_span(s)
78 })
79 .map(Self::from),
80 _ => Err(Error::unexpected_expr_type(expr)),
81 }
82 }
83}
84
85impl ToTokens for Callable {
86 fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
87 self.call.to_tokens(tokens);
88 }
89}