Skip to main content

bon_macros/builder/builder_gen/top_level_config/
generics.rs

1use crate::parsing::{ItemSigConfig, ItemSigConfigParsing};
2use crate::util::prelude::*;
3use darling::FromMeta;
4
5#[derive(Debug, Clone, Default)]
6pub(crate) struct GenericsConfig {
7    pub(crate) setters: Option<ItemSigConfig<String>>,
8}
9
10impl FromMeta for GenericsConfig {
11    fn from_meta(meta: &syn::Meta) -> Result<Self> {
12        meta.require_list()?.require_parens_delim()?;
13
14        #[derive(FromMeta)]
15        struct Parsed {
16            #[darling(default, with = parse_setters_config, map = Some)]
17            setters: Option<ItemSigConfig<String>>,
18        }
19
20        let parsed = Parsed::from_meta(meta)?;
21
22        Ok(Self {
23            setters: parsed.setters,
24        })
25    }
26}
27
28fn parse_setters_config(meta: &syn::Meta) -> Result<ItemSigConfig<String>> {
29    if !cfg!(feature = "experimental-generics-setters") {
30        bail!(
31            meta,
32            "🔬 `generics(setters(...))` attribute is experimental and requires \
33             \"experimental-generics-setters\" cargo feature to be enabled",
34        );
35    }
36
37    const DOCS_CONTEXT: &str = "builder struct's impl block";
38    let config: ItemSigConfig<String> =
39        ItemSigConfigParsing::new(meta, Some(DOCS_CONTEXT)).parse()?;
40
41    // Validate that name is provided and contains the placeholder
42    let name_pattern = config.name.as_ref().ok_or_else(|| {
43        err!(
44            meta,
45            "`name` parameter is required for `generics(setters(...))`; \
46             specify a pattern like `name = \"conv_{{}}\"` where `{{}}` will be \
47             replaced with the snake_case name of each generic parameter"
48        )
49    })?;
50
51    if !name_pattern.value.contains("{}") {
52        bail!(
53            &name_pattern.key,
54            "the `name` pattern must contain the `{{}}` placeholder, \
55             which will be replaced with the snake_case name of each generic parameter"
56        );
57    }
58
59    Ok(config)
60}