bon_macros/builder/builder_gen/member/config/with/
mod.rs
1mod closure;
2
3pub(crate) use closure::*;
4
5use crate::util::prelude::*;
6use darling::FromMeta;
7
8#[derive(Debug)]
9pub(crate) enum WithConfig {
10 Closure(SetterClosure),
12
13 Some(syn::Path),
15
16 FromIter(syn::ExprPath),
18}
19
20impl WithConfig {
21 pub(crate) fn as_closure(&self) -> Option<&SetterClosure> {
22 match self {
23 Self::Closure(closure) => Some(closure),
24 _ => None,
25 }
26 }
27}
28
29impl FromMeta for WithConfig {
30 fn from_meta(meta: &syn::Meta) -> darling::Result<Self> {
31 let err = || {
32 err!(
33 meta,
34 "expected a closure e.g. `#[builder(with = |param: T| expression)]` or \
35 a well-known function path which could be one of:\n\
36 - #[builder(with = Some)]\n\
37 - #[builder(with = FromIterator::from_iter)]\n\
38 - #[builder(with = <_>::from_iter)] (same as above, but shorter)",
39 )
40 };
41
42 let name_val = match meta {
43 syn::Meta::NameValue(meta) => meta,
44 _ => return Err(err()),
45 };
46
47 if let syn::Expr::Closure(_) = name_val.value {
48 return SetterClosure::from_meta(meta).map(Self::Closure);
49 }
50
51 let path = match &name_val.value {
52 syn::Expr::Path(path) => path,
53 _ => return Err(err()),
54 };
55
56 crate::parsing::reject_syntax("attribute", &path.attrs.first())?;
57
58 if *path == syn::parse_quote!(Some) {
59 return Ok(Self::Some(path.path.clone()));
60 }
61
62 if *path == syn::parse_quote!(FromIterator::from_iter)
63 || *path == syn::parse_quote!(<_>::from_iter)
64 {
65 return Ok(Self::FromIter(path.clone()));
66 }
67
68 Err(err())
69 }
70}