bon_macros/parsing/
simple_closure.rs
1use super::reject_syntax;
2use crate::util::prelude::*;
3use darling::FromMeta;
4
5#[derive(Debug)]
9pub(crate) struct SimpleClosure {
10 pub(crate) inputs: Vec<SimpleClosureInput>,
11 pub(crate) body: Box<syn::Expr>,
12 pub(crate) output: syn::ReturnType,
13}
14
15#[derive(Debug)]
16pub(crate) struct SimpleClosureInput {
17 pub(crate) pat: syn::PatIdent,
18 pub(crate) ty: Option<Box<syn::Type>>,
19}
20
21impl FromMeta for SimpleClosure {
22 fn from_meta(meta: &syn::Meta) -> Result<Self> {
23 let err = || {
24 let path = darling::util::path_to_string(meta.path());
25 err!(
26 meta,
27 "expected a closure e.g. `{path} = |param: T| expression`"
28 )
29 };
30
31 let meta = match meta {
32 syn::Meta::NameValue(meta) => meta,
33 _ => return Err(err()),
34 };
35
36 let closure = match &meta.value {
37 syn::Expr::Closure(closure) => closure,
38 _ => return Err(err()),
39 };
40
41 reject_syntax("`for<...>` syntax", &closure.lifetimes)?;
42 reject_syntax("`const` keyword", &closure.constness)?;
43 reject_syntax("`static` keyword", &closure.movability)?;
44 reject_syntax("`async` keyword", &closure.asyncness)?;
45 reject_syntax("`move` keyword", &closure.capture)?;
46 reject_syntax("attribute", &closure.attrs.first())?;
47
48 let inputs = closure
49 .clone()
50 .inputs
51 .into_iter()
52 .map(|input| match input {
53 syn::Pat::Ident(pat) => SimpleClosureInput::from_pat_ident(pat),
54 syn::Pat::Type(pat) => SimpleClosureInput::from_pat_type(pat),
55 _ => bail!(&input, "expected a simple identifier pattern"),
56 })
57 .collect::<Result<_>>()?;
58
59 Ok(Self {
60 inputs,
61 body: closure.body.clone(),
62 output: closure.output.clone(),
63 })
64 }
65}
66
67impl SimpleClosureInput {
68 fn from_pat_ident(pat: syn::PatIdent) -> Result<Self> {
69 reject_syntax("attribute", &pat.attrs.first())?;
70 reject_syntax("`ref` keyword", &pat.by_ref)?;
71 Ok(Self { pat, ty: None })
72 }
73
74 fn from_pat_type(input: syn::PatType) -> Result<Self> {
75 reject_syntax("attribute", &input.attrs.first())?;
76
77 let ident = match *input.pat {
78 syn::Pat::Ident(pat) => Self::from_pat_ident(pat)?.pat,
79 _ => bail!(&input.pat, "expected a simple identifier pattern"),
80 };
81
82 Ok(Self {
83 pat: ident,
84 ty: Some(input.ty),
85 })
86 }
87}