bon_macros/builder/builder_gen/member/config/
getter.rs
1use crate::parsing::SpannedKey;
2use crate::util::prelude::*;
3use darling::FromMeta;
4
5#[derive(Debug, Default)]
6pub(crate) struct GetterConfig {
7 pub(crate) name: Option<SpannedKey<syn::Ident>>,
8 pub(crate) vis: Option<SpannedKey<syn::Visibility>>,
9 pub(crate) docs: Option<SpannedKey<Vec<syn::Attribute>>>,
10
11 pub(crate) kind: Option<SpannedKey<GetterKind>>,
13}
14
15#[derive(Debug)]
16pub(crate) enum GetterKind {
17 Copy,
19
20 Clone,
22
23 Deref(Option<syn::Type>),
26}
27
28impl FromMeta for GetterConfig {
29 fn from_meta(meta: &syn::Meta) -> Result<Self> {
30 if let syn::Meta::Path(_) = meta {
31 return Ok(Self::default());
32 }
33
34 crate::parsing::require_non_empty_paren_meta_list_or_name_value(meta)?;
36
37 #[derive(FromMeta)]
39 struct Parsed {
40 name: Option<SpannedKey<syn::Ident>>,
41 vis: Option<SpannedKey<syn::Visibility>>,
42
43 #[darling(rename = "doc", default, with = parse_docs, map = Some)]
44 docs: Option<SpannedKey<Vec<syn::Attribute>>>,
45
46 copy: Option<SpannedKey<()>>,
47 clone: Option<SpannedKey<()>>,
48
49 #[darling(default, map = Some, with = parse_deref)]
50 deref: Option<SpannedKey<Option<syn::Type>>>,
51 }
52
53 let Parsed {
54 name,
55 vis,
56 docs,
57 copy,
58 clone,
59 deref,
60 } = Parsed::from_meta(meta)?;
61
62 let kinds = [
63 copy.map(|cfg| cfg.with_value(GetterKind::Copy)),
64 clone.map(|cfg| cfg.with_value(GetterKind::Clone)),
65 deref.map(|ty| ty.map_value(GetterKind::Deref)),
66 ];
67
68 let kinds = kinds.into_iter().flatten().collect::<Vec<_>>();
69
70 if let [kind1, kind2, ..] = kinds.as_slice() {
71 bail!(
72 &kind1.key,
73 "`{}` can't be specified together with `{}`",
74 kind1.key,
75 kind2.key
76 );
77 }
78
79 let kind = kinds.into_iter().next();
80
81 Ok(Self {
82 name,
83 vis,
84 docs,
85 kind,
86 })
87 }
88}
89
90fn parse_deref(meta: &syn::Meta) -> Result<SpannedKey<Option<syn::Type>>> {
91 let value = match meta {
92 syn::Meta::NameValue(_) => bail!(
93 meta,
94 "expected `getter(deref)` or `getter(deref(...))` syntax"
95 ),
96 syn::Meta::Path(_) => None,
97 syn::Meta::List(meta) => Some(syn::parse2(meta.tokens.clone())?),
98 };
99
100 SpannedKey::new(meta.path(), value)
101}
102
103fn parse_docs(meta: &syn::Meta) -> Result<SpannedKey<Vec<syn::Attribute>>> {
104 crate::parsing::parse_docs_without_self_mentions("builder struct's impl block", meta)
105}