1use quote::ToTokens;
23use crate::{Error, FromMeta, Result};
45/// 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)]
16pub struct Callable {
17/// The callable
18call: syn::Expr,
19}
2021impl AsRef<syn::Expr> for Callable {
22fn as_ref(&self) -> &syn::Expr {
23&self.call
24 }
25}
2627impl From<syn::ExprPath> for Callable {
28fn from(value: syn::ExprPath) -> Self {
29Self {
30 call: syn::Expr::Path(value),
31 }
32 }
33}
3435impl From<syn::ExprClosure> for Callable {
36fn from(value: syn::ExprClosure) -> Self {
37Self {
38 call: syn::Expr::Closure(value),
39 }
40 }
41}
4243impl From<Callable> for syn::Expr {
44fn from(value: Callable) -> Self {
45 value.call
46 }
47}
4849impl FromMeta for Callable {
50fn from_expr(expr: &syn::Expr) -> Result<Self> {
51match expr {
52 syn::Expr::Path(_) | syn::Expr::Closure(_) => Ok(Self { call: expr.clone() }),
53_ => Err(Error::unexpected_expr_type(expr)),
54 }
55 }
56}
5758impl ToTokens for Callable {
59fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
60self.call.to_tokens(tokens);
61 }
62}