1 | use quote::ToTokens; |
2 | |
3 | use crate::{Error, FromMeta, Result}; |
4 | |
5 | /// Either a path or a closure. |
6 | /// |
7 | /// This type is useful for options that historically took a path, |
8 | /// e.g. `#[darling(with = ...)]` or `#[serde(skip_serializing_if = ...)]` |
9 | /// and now want to also allow using a closure to avoid needing a separate |
10 | /// function declaration. |
11 | /// |
12 | /// In `darling`, this value is wrapped in [`core::convert::identity`] before usage; |
13 | /// this allows treatment of the closure and path cases as equivalent, and prevents |
14 | /// a closure from accessing locals in the generated code. |
15 | #[derive (Debug, Clone)] |
16 | pub struct Callable { |
17 | /// The callable |
18 | call: syn::Expr, |
19 | } |
20 | |
21 | impl AsRef<syn::Expr> for Callable { |
22 | fn as_ref(&self) -> &syn::Expr { |
23 | &self.call |
24 | } |
25 | } |
26 | |
27 | impl From<syn::ExprPath> for Callable { |
28 | fn from(value: syn::ExprPath) -> Self { |
29 | Self { |
30 | call: syn::Expr::Path(value), |
31 | } |
32 | } |
33 | } |
34 | |
35 | impl From<syn::ExprClosure> for Callable { |
36 | fn from(value: syn::ExprClosure) -> Self { |
37 | Self { |
38 | call: syn::Expr::Closure(value), |
39 | } |
40 | } |
41 | } |
42 | |
43 | impl From<Callable> for syn::Expr { |
44 | fn from(value: Callable) -> Self { |
45 | value.call |
46 | } |
47 | } |
48 | |
49 | impl FromMeta for Callable { |
50 | fn from_expr(expr: &syn::Expr) -> Result<Self> { |
51 | match expr { |
52 | syn::Expr::Path(_) | syn::Expr::Closure(_) => Ok(Self { call: expr.clone() }), |
53 | _ => Err(Error::unexpected_expr_type(expr)), |
54 | } |
55 | } |
56 | } |
57 | |
58 | impl ToTokens for Callable { |
59 | fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) { |
60 | self.call.to_tokens(tokens); |
61 | } |
62 | } |
63 | |