staged_builder_internals/
lib.rs

1use heck::{ToSnakeCase, ToUpperCamelCase};
2use proc_macro2::{Span, TokenStream};
3use quote::quote;
4use structmeta::{NameArgs, NameValue, StructMeta};
5use syn::parse::{Parse, ParseStream};
6use syn::spanned::Spanned;
7use syn::{
8    parse_macro_input, Attribute, Data, DeriveInput, Error, Expr, Field, Fields, FieldsNamed,
9    Ident, Path, Type, Visibility,
10};
11
12/// Creates a staged builder interface for structs.
13///
14/// The macro will create a submodule with the `snake_case` version of the type's name containing the builder types, and
15/// add a `builder` constructor function to the type. Each required field of the struct will correspond to a builder
16/// type named after it, with an additional "final" stage to set optional fields and construct the final value.
17///
18/// By default, all fields are considered required and their setters will simply take their declared type by-value. This
19/// behavior can be customized with field options.
20///
21/// # Struct options
22///
23/// Options can be applied at the struct level via the `#[builder(...)]` attribute as a comma-separated sequence:
24///
25/// * `validate` - The final `build` method will return a `Result`, calling the type's `Validate` implementation before
26///     returning the constructed value.
27/// * `update` - The completed stage of the builder will have setters for all fields, and a `From` impl will be created
28///     to allow an instance of the struct to be converted back into the builder type for further updates.
29/// * `crate` - Indicates the path to the `staged_builder` crate root. Useful when reexporting the macro from another
30///     crate. Defaults to `::staged_builder`.
31/// * `mod` - The name of the submodule that will contain the generated builder types. Defaults to the struct's name
32///     converted to `snake_case`.
33/// * `inline` - Causes the generated builder types to be defined in the same module as the struct, rather than a
34///     submodule.
35/// * `builder` - Sets the name of the generated builder type. Defaults to `Builder`.
36/// * `complete` - Sets the name of the generated complete stage type. Defaults to `Complete`.
37///
38/// # Field options
39///
40/// Options can be applied to individual fields via the `#[builder(...)]` attribute as a comma-separated sequence:
41///
42/// * `default` - Causes the field to be considered optional. The [`Default`] trait is normally used to generate the
43///     default field value. A custom default can be specified with `default = <expr>`, where `<expr>` is an expression.
44/// * `into` - Causes the setter method for the field to take `impl Into<FieldType>` rather than `FieldType` directly.
45/// * `custom` - Causes the setter method to perform an arbitrary conversion for the field. The option expects a `type`
46///     which will be used as the argument type in the setter, and a `convert` callable expression which will be invoked
47///     by the setter. For example, the annotation `#[builder(into)]` on a field of type `T` is equivalent to the
48///     annotation `#[builder(custom(type = impl Into<T>, convert = Into::into))]`.
49/// * `list` - Causes the field to be treated as a "list style" type. It will default to an empty collection, and three
50///     setter methods will be generated: `push_foo` to add a single value, `foo` to set the contents, and `extend_foo`
51///     to exend the collection with new values. The underlying type must have a `push` method, a [`FromIterator`]
52///     implementation, and an [`Extend`] implementation. The item type must be configured in the attribute:
53///     `#[builder(list(item(type = YourItemType)))]`.
54/// * `set` - Causes the field to be treated as a "set style" type. It will default to an empty collection, and three
55///     setter methods will be generated: `insert_foo` to add a single value, `foo` to set the contents, and
56///     `extend_foo` to exend the collection with new values. The underlying type must have an `insert` method, a
57///     [`FromIterator`] implementation, and an [`Extend`] implementation. The item type must be configured in the
58///     attribute: `#[builder(set(item(type = YourItemType)))]`.
59/// * `map` - Causes the field to be treated as a "map style" type. It will default to an empty collection, and three
60///     setter methods will be generated: `insert_foo` to add a single entry, `foo` to set the contents, and
61///     `extend_foo` to exend the collection with new entries. The underlying type must have an `insert` method, a
62///     [`FromIterator`] implementation, and an [`Extend`] implementation. The key and value types must be configured in
63///     the attribute: `#[builder(map(key(type = YourKeyType), value(type = YourValueType)))]`.
64/// * `stage`- Sets the name of the generated stage type. Defaults to the name of the field converted to `PascalCase`
65///     with `Stage` appended.
66///
67/// # Collection type options
68///
69/// Options can be applied to the item types of collections as a comma-separated sequence:
70///
71/// * `type` - Indicates the type of the item in the collection. Required unless using `custom`.
72/// * `into` - Causes setter methods to take `impl<Into<ItemType>>` rather than `ItemType` directly.
73/// * `custom` - Causes the setter methods to perform an arbitrary conversion for the field.
74///
75/// # Example expansion
76///
77/// ```ignore
78/// use staged_builder::staged_builder;
79///
80/// #[staged_builder]
81/// pub struct MyStruct {
82///     required_field: u32,
83///     #[builder(into)]
84///     into_required_field: String,
85///     #[builder(default)]
86///     standard_optional_field: bool,
87///     #[builder(default = "foobar".to_string())]
88///     custom_default_field: String,
89///     #[builder(list(item(type = i32)))]
90///     list_field: Vec<i32>,
91/// }
92/// ```
93///
94/// Will expand into:
95///
96/// ```ignore
97/// pub struct MyStruct {
98///     required_field: u32,
99///     into_required_field: String,
100///     standard_optional_field: bool,
101///     custom_default_field: String,
102///     list_field: Vec<i32>,
103/// }
104///
105/// impl MyStruct {
106///     pub fn builder() -> my_struct::Builder<my_struct::RequiredFieldStage> {
107///         // ...
108///     }
109/// }
110///
111/// pub mod my_struct {
112///     pub struct Builder<T> {
113///         // ...
114///     }
115///
116///     impl Default for Builder<RequiredFieldStage> {
117///         fn default() -> Self {
118///             // ...
119///         }
120///     }
121///
122///     impl Builder<RequiredFieldStage> {
123///         pub fn required_field(self, required_field: u32) -> Builder<IntoRequiredFieldStage> {
124///             // ...
125///         }
126///     }
127///
128///     impl Builder<IntoRequiredFieldStage> {
129///         pub fn into_required_field(self, into_required_field: impl Into<String>) -> Builder<FinalStage> {
130///             // ...
131///         }
132///     }
133///
134///     impl Builder<FinalStage> {
135///         pub fn standard_optional_field(self, standard_optional_field: bool) -> Self {
136///             // ...
137///         }
138///
139///         pub fn custom_default_field(self, custom_default_field: String) -> Self {
140///             // ...
141///         }
142///
143///         pub fn push_list_field(self, list_field: i32) -> Self {
144///             // ...
145///         }
146///
147///         pub fn list_field(self, list_field: impl IntoIterator<Item = i32>) -> Self {
148///             // ...
149///         }
150///
151///         pub fn extend_list_field(self, list_field: impl IntoIterator<Item = i32>) -> Self {
152///             // ...
153///         }
154///
155///         pub fn build(self) -> super::MyStruct {
156///             // ...
157///         }
158///     }
159///
160///     pub struct RequiredFieldStage {
161///         // ...
162///     }
163///
164///     pub struct IntoRequiredFieldStage {
165///         // ...
166///     }
167///
168///     pub struct FinalStage {
169///         // ...
170///     }
171/// }
172/// ```
173#[proc_macro_attribute]
174pub fn staged_builder(
175    _args: proc_macro::TokenStream,
176    input: proc_macro::TokenStream,
177) -> proc_macro::TokenStream {
178    let input = parse_macro_input!(input as AttrInput);
179
180    let attrs = input.attrs;
181
182    let overrides = match StructOverrides::new(&attrs) {
183        Ok(overrides) => overrides,
184        Err(e) => return e.into_compile_error().into(),
185    };
186    let crate_ = overrides.crate_();
187
188    let body = input.body;
189    quote! {
190        #[derive(#crate_ ::__StagedBuilderInternalDerive)]
191        #(#attrs)*
192        #body
193    }
194    .into()
195}
196
197struct AttrInput {
198    attrs: Vec<Attribute>,
199    body: TokenStream,
200}
201
202impl Parse for AttrInput {
203    fn parse(input: ParseStream) -> syn::Result<Self> {
204        let attrs = input.call(Attribute::parse_outer)?;
205        let body = input.parse()?;
206
207        Ok(AttrInput { attrs, body })
208    }
209}
210
211// Not public API.
212#[doc(hidden)]
213#[proc_macro_derive(__StagedBuilderInternalDerive, attributes(builder))]
214pub fn __internal_derive_staged_builder(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
215    let input = parse_macro_input!(input as DeriveInput);
216
217    expand(input)
218        .unwrap_or_else(|e| e.into_compile_error())
219        .into()
220}
221
222fn expand(input: DeriveInput) -> Result<TokenStream, Error> {
223    let struct_ = match &input.data {
224        Data::Struct(struct_) => struct_,
225        _ => {
226            return Err(Error::new_spanned(
227                &input,
228                "staged builders can only be derived on structs",
229            ))
230        }
231    };
232
233    let fields = match &struct_.fields {
234        Fields::Named(fields) => fields,
235        _ => {
236            return Err(Error::new_spanned(
237                &input,
238                "staged builders cannot be derived on tuple or unit structs",
239            ))
240        }
241    };
242
243    let overrides = StructOverrides::new(&input.attrs)?;
244    let fields = resolve_fields(&overrides, fields)?;
245
246    let builder_impl = builder_impl(&input, &overrides, &fields);
247    let module = module(&input, &overrides, &fields);
248
249    let tokens = quote! {
250        #builder_impl
251        #module
252    };
253
254    Ok(tokens)
255}
256
257fn module(
258    input: &DeriveInput,
259    overrides: &StructOverrides,
260    fields: &[ResolvedField<'_>],
261) -> TokenStream {
262    let builder = builder(input, overrides);
263    let default = default_impl(overrides, fields);
264    let stages = fields
265        .iter()
266        .enumerate()
267        .filter(|(_, f)| f.default.is_none())
268        .map(|(i, _)| stage(input, overrides, i, fields));
269    let final_stage = final_stage(input, overrides, fields);
270
271    let parts = quote! {
272        #builder
273        #default
274        #(#stages)*
275        #final_stage
276    };
277
278    if overrides.inline {
279        return parts;
280    }
281
282    let vis = &input.vis;
283    let module_name = module_name(overrides, input);
284
285    let module_docs = format!("Builder types for [`{}`].", &input.ident);
286
287    quote! {
288        #[doc = #module_docs]
289        #vis mod #module_name {
290            use super::*;
291
292            #parts
293        }
294    }
295}
296
297fn module_name(overrides: &StructOverrides, input: &DeriveInput) -> Ident {
298    overrides
299        .mod_
300        .clone()
301        .unwrap_or_else(|| Ident::new(&input.ident.to_string().to_snake_case(), input.ident.span()))
302}
303
304fn builder_impl(
305    input: &DeriveInput,
306    overrides: &StructOverrides,
307    fields: &[ResolvedField<'_>],
308) -> TokenStream {
309    let name = &input.ident;
310    let vis = &input.vis;
311
312    let builder_name = builder_name(overrides);
313    let module_path = if overrides.inline {
314        quote!()
315    } else {
316        let module_name = module_name(overrides, input);
317        quote!(#module_name::)
318    };
319    let stage_name = initial_stage(fields).unwrap_or_else(|| final_name(overrides));
320    let private = overrides.private();
321
322    quote! {
323        impl #name {
324            /// Returns a new builder.
325            #[inline]
326            #vis fn builder() -> #module_path #builder_name<#module_path #stage_name> {
327                #private::Default::default()
328            }
329        }
330    }
331}
332
333fn initial_stage(fields: &[ResolvedField<'_>]) -> Option<Ident> {
334    fields
335        .iter()
336        .find(|f| f.default.is_none())
337        .map(|f| f.stage.clone())
338}
339
340fn builder(input: &DeriveInput, overrides: &StructOverrides) -> TokenStream {
341    let link = if overrides.inline {
342        format!("[{}]", input.ident)
343    } else {
344        format!("[{0}](super::{0})", input.ident)
345    };
346
347    let docs = format!("A builder for {link}");
348
349    let vis = stage_vis(&input.vis, overrides);
350    let builder_name = builder_name(overrides);
351
352    quote! {
353        #[doc = #docs]
354        #vis struct #builder_name<T>(T);
355    }
356}
357
358fn default_impl(overrides: &StructOverrides, fields: &[ResolvedField<'_>]) -> TokenStream {
359    let (stage, initializers) = match initial_stage(fields) {
360        Some(stage) => (stage, quote!()),
361        None => (final_name(overrides), default_field_initializers(fields)),
362    };
363    let builder_name = builder_name(overrides);
364
365    let private = overrides.private();
366
367    quote! {
368        impl #private::Default for #builder_name<#stage> {
369            #[inline]
370            fn default() -> Self {
371                #builder_name(#stage {
372                    #initializers
373                })
374            }
375        }
376    }
377}
378
379fn default_field_initializers(fields: &[ResolvedField<'_>]) -> TokenStream {
380    let fields = fields.iter().filter_map(|f| {
381        f.default.as_ref().map(|default| {
382            let name = f.field.ident.as_ref().unwrap();
383            quote!(#name: #default)
384        })
385    });
386
387    quote!(#(#fields,)*)
388}
389
390fn stage(
391    input: &DeriveInput,
392    overrides: &StructOverrides,
393    idx: usize,
394    fields: &[ResolvedField<'_>],
395) -> TokenStream {
396    let vis = stage_vis(&input.vis, overrides);
397    let field = &fields[idx];
398    let name = field.field.ident.as_ref().unwrap();
399
400    let (type_, assign) = match &field.mode {
401        FieldMode::Normal { type_, assign } => (type_, assign),
402        _ => unreachable!(),
403    };
404
405    let stage_name = &field.stage;
406
407    let existing_fields = fields[..idx]
408        .iter()
409        .filter(|f| f.default.is_none())
410        .collect::<Vec<_>>();
411
412    let existing_names = existing_fields
413        .iter()
414        .map(|f| f.field.ident.as_ref().unwrap())
415        .collect::<Vec<_>>();
416    let existing_types = existing_fields.iter().map(|f| &f.field.ty);
417
418    let (next_stage, optional_fields) = match fields[idx + 1..].iter().find(|f| f.default.is_none())
419    {
420        Some(field) => (field.stage.clone(), quote!()),
421        None => (final_name(overrides), default_field_initializers(fields)),
422    };
423
424    let builder_name = builder_name(overrides);
425    let struct_docs = format!("The `{name}` stage for [`{builder_name}`].");
426    let setter_docs = format!("Sets the `{name}` field.");
427
428    quote! {
429        #[doc = #struct_docs]
430        #vis struct #stage_name {
431            #(#existing_names: #existing_types,)*
432        }
433
434        impl #builder_name<#stage_name> {
435            #[doc = #setter_docs]
436            #[inline]
437            pub fn #name(self, #name: #type_) -> #builder_name<#next_stage> {
438                #builder_name(#next_stage {
439                    #(#existing_names: self.0.#existing_names,)*
440                    #name: #assign,
441                    #optional_fields
442                })
443            }
444        }
445    }
446}
447
448fn stage_vis(vis: &Visibility, overrides: &StructOverrides) -> TokenStream {
449    if overrides.inline {
450        return quote!(#vis);
451    }
452
453    match vis {
454        Visibility::Public(_) => quote!(#vis),
455        Visibility::Restricted(restricted) => {
456            let path = &restricted.path;
457            if path.leading_colon.is_some()
458                || path.segments.first().map_or(false, |i| i.ident == "crate")
459            {
460                quote!(#vis)
461            } else if restricted.path.is_ident("self") {
462                quote!(pub (super))
463            } else {
464                let path = &restricted.path;
465                quote!(pub (in super::#path))
466            }
467        }
468        Visibility::Inherited => quote!(pub (super)),
469    }
470}
471
472fn builder_name(overrides: &StructOverrides) -> Ident {
473    overrides
474        .builder
475        .clone()
476        .unwrap_or_else(|| Ident::new("Builder", Span::call_site()))
477}
478
479fn final_name(overrides: &StructOverrides) -> Ident {
480    overrides
481        .complete
482        .clone()
483        .unwrap_or_else(|| Ident::new("Complete", Span::call_site()))
484}
485
486fn final_stage(
487    input: &DeriveInput,
488    overrides: &StructOverrides,
489    fields: &[ResolvedField<'_>],
490) -> TokenStream {
491    let vis = stage_vis(&input.vis, overrides);
492    let builder_name = builder_name(overrides);
493    let stage_name = final_name(overrides);
494    let struct_name = &input.ident;
495    let names = fields.iter().map(|f| f.field.ident.as_ref().unwrap());
496    let types = fields.iter().map(|f| &f.field.ty).collect::<Vec<_>>();
497
498    let struct_docs = format!("The final stage for [`{struct_name}`](super::{struct_name}).");
499
500    let setters = fields
501        .iter()
502        .filter(|f| overrides.update || f.default.is_some())
503        .map(|f| final_stage_setter(overrides, f));
504
505    let build_docs =
506        format!("Consumes the builder, returning a [`{struct_name}`](super::{struct_name}).");
507
508    let build = if overrides.validate {
509        validated_build(input, overrides, fields)
510    } else {
511        unvalidated_build(input, overrides, fields)
512    };
513
514    let update_from_impl = if overrides.update {
515        update_from_impl(input, overrides, fields)
516    } else {
517        quote!()
518    };
519
520    quote! {
521        #[doc = #struct_docs]
522        #vis struct #stage_name {
523            #(#names: #types,)*
524        }
525
526        impl #builder_name<#stage_name> {
527            #(#setters)*
528
529            #[doc = #build_docs]
530            #build
531        }
532
533        #update_from_impl
534    }
535}
536
537fn final_stage_setter(
538    struct_overrides: &StructOverrides,
539    field: &ResolvedField<'_>,
540) -> TokenStream {
541    let name = field.field.ident.as_ref().unwrap();
542
543    match &field.mode {
544        FieldMode::Normal { type_, assign } => {
545            let docs = format!("Sets the `{name}` field.");
546            quote! {
547                #[doc = #docs]
548                #[inline]
549                pub fn #name(mut self, #name: #type_) -> Self {
550                    self.0.#name = #assign;
551                    self
552                }
553            }
554        }
555        FieldMode::Seq { push, item } => {
556            let type_ = &item.type_;
557            let convert = item.convert(struct_overrides, name);
558            let convert_iter = item.convert_iter(struct_overrides, name);
559
560            let push_docs = format!("Adds a value to the `{name}` field.");
561            let push_method = Ident::new(&format!("{push}_{name}"), name.span());
562
563            let docs = format!("Sets the `{name}` field.");
564
565            let extend_docs = format!("Adds values to the `{name}` field.");
566            let extend_method = Ident::new(&format!("extend_{name}"), name.span());
567
568            let private = struct_overrides.private();
569
570            quote! {
571                #[doc = #push_docs]
572                #[inline]
573                pub fn #push_method(mut self, #name: #type_) -> Self {
574                    self.0.#name.#push(#convert);
575                    self
576                }
577
578                #[doc = #docs]
579                #[inline]
580                pub fn #name(
581                    mut self,
582                    #name: impl #private::IntoIterator<Item = #type_>,
583                ) -> Self
584                {
585                    self.0.#name = #private::FromIterator::from_iter(#convert_iter);
586                    self
587                }
588
589                #[doc = #extend_docs]
590                #[inline]
591                pub fn #extend_method(
592                    mut self,
593                    #name: impl #private::IntoIterator<Item = #type_>,
594                ) -> Self
595                {
596                    #private::Extend::extend(&mut self.0.#name, #convert_iter);
597                    self
598                }
599            }
600        }
601        FieldMode::Map { key, value } => {
602            let key_name = Ident::new("key", Span::call_site());
603            let key_type = &key.type_;
604            let key_convert = key.convert(struct_overrides, &key_name);
605
606            let value_name = Ident::new("value", Span::call_site());
607            let value_type = &value.type_;
608            let value_convert = value.convert(struct_overrides, &value_name);
609
610            let private = struct_overrides.private();
611
612            let iter_convert = if key.convert.is_some() || value.convert.is_some() {
613                quote! {
614                    #private::Iterator::map(
615                        #private::IntoIterator::into_iter(#name),
616                        |(#key_name, #value_name)| (#key_convert, #value_convert)
617                    )
618                }
619            } else {
620                quote!(#name)
621            };
622
623            let insert_docs = format!("Adds an entry to the `{name}` field.");
624            let insert_method = Ident::new(&format!("insert_{name}"), name.span());
625
626            let docs = format!("Sets the `{name}` field.");
627
628            let extend_docs = format!("Adds entries to the `{name}` field.");
629            let extend_method = Ident::new(&format!("extend_{name}"), name.span());
630
631            quote! {
632                #[doc = #insert_docs]
633                #[inline]
634                pub fn #insert_method(mut self, #key_name: #key_type, #value_name: #value_type) -> Self {
635                    self.0.#name.insert(#key_convert, #value_convert);
636                    self
637                }
638
639                #[doc = #docs]
640                #[inline]
641                pub fn #name(
642                    mut self,
643                    #name: impl #private::IntoIterator<Item = (#key_type, #value_type)>,
644                ) -> Self {
645                    self.0.#name = #private::FromIterator::from_iter(#iter_convert);
646                    self
647                }
648
649                #[doc = #extend_docs]
650                #[inline]
651                pub fn #extend_method(
652                    mut self,
653                    #name: impl #private::IntoIterator<Item = (#key_type, #value_type)>,
654                ) -> Self
655                {
656                    #private::Extend::extend(&mut self.0.#name, #iter_convert);
657                    self
658                }
659            }
660        }
661    }
662}
663
664fn validated_build(
665    input: &DeriveInput,
666    overrides: &StructOverrides,
667    fields: &[ResolvedField<'_>],
668) -> TokenStream {
669    let struct_name = &input.ident;
670    let struct_path = if overrides.inline {
671        quote!(#struct_name)
672    } else {
673        quote!(super::#struct_name)
674    };
675    let names = fields
676        .iter()
677        .map(|f| f.field.ident.as_ref().unwrap())
678        .collect::<Vec<_>>();
679
680    let crate_ = overrides.crate_();
681    let private = overrides.private();
682
683    quote! {
684        #[inline]
685        pub fn build(
686            self,
687        ) -> #private::Result<
688            #struct_path,
689            <#struct_path as #crate_::Validate>::Error,
690        > {
691            let value = #struct_path {
692                #(#names: self.0.#names,)*
693            };
694            #crate_::Validate::validate(&value)?;
695            #private::Result::Ok(value)
696        }
697    }
698}
699
700fn unvalidated_build(
701    input: &DeriveInput,
702    overrides: &StructOverrides,
703    fields: &[ResolvedField<'_>],
704) -> TokenStream {
705    let struct_name = &input.ident;
706    let struct_path = if overrides.inline {
707        quote!(#struct_name)
708    } else {
709        quote!(super::#struct_name)
710    };
711    let names = fields
712        .iter()
713        .map(|f| f.field.ident.as_ref().unwrap())
714        .collect::<Vec<_>>();
715
716    quote! {
717        #[inline]
718        pub fn build(self) -> #struct_path {
719            #struct_path {
720                #(#names: self.0.#names,)*
721            }
722        }
723    }
724}
725
726fn update_from_impl(
727    input: &DeriveInput,
728    overrides: &StructOverrides,
729    fields: &[ResolvedField<'_>],
730) -> TokenStream {
731    let private = overrides.private();
732    let struct_name = &input.ident;
733    let struct_path = if overrides.inline {
734        quote!(#struct_name)
735    } else {
736        quote!(super::#struct_name)
737    };
738
739    let builder = builder_name(overrides);
740    let complete = final_name(overrides);
741    let fields = fields.iter().map(|f| f.field.ident.as_ref().unwrap());
742
743    quote! {
744        impl #private::From<#struct_path> for #builder<#complete> {
745            #[inline]
746            fn from(v: #struct_path) -> Self {
747                #builder(#complete {
748                    #(#fields: v.#fields,)*
749                })
750            }
751        }
752    }
753}
754
755fn resolve_fields<'a>(
756    overrides: &StructOverrides,
757    fields: &'a FieldsNamed,
758) -> Result<Vec<ResolvedField<'a>>, Error> {
759    let mut resolved_fields = vec![];
760    let mut error = None::<Error>;
761
762    for field in &fields.named {
763        match ResolvedField::new(overrides, field) {
764            Ok(field) => resolved_fields.push(field),
765            Err(e) => match &mut error {
766                Some(error) => error.combine(e),
767                None => error = Some(e),
768            },
769        }
770    }
771
772    match error {
773        Some(error) => Err(error),
774        None => Ok(resolved_fields),
775    }
776}
777
778#[derive(StructMeta, Default)]
779struct StructOverrides {
780    validate: bool,
781    #[struct_meta(name = "crate")]
782    crate_: Option<Path>,
783    #[struct_meta(name = "mod")]
784    mod_: Option<Ident>,
785    inline: bool,
786    builder: Option<Ident>,
787    complete: Option<Ident>,
788    update: bool,
789}
790
791impl StructOverrides {
792    fn new(attrs: &[Attribute]) -> Result<Self, Error> {
793        attrs
794            .iter()
795            .filter(|a| a.meta.path().is_ident("builder"))
796            .map(|a| a.parse_args())
797            .next()
798            .transpose()
799            .map(|o| o.unwrap_or_default())
800    }
801
802    fn crate_(&self) -> TokenStream {
803        match &self.crate_ {
804            Some(crate_) => quote!(#crate_),
805            None => quote!(::staged_builder),
806        }
807    }
808
809    fn private(&self) -> TokenStream {
810        let crate_ = self.crate_();
811        quote!(#crate_::__private)
812    }
813}
814
815struct ResolvedField<'a> {
816    field: &'a Field,
817    default: Option<TokenStream>,
818    stage: Ident,
819    mode: FieldMode,
820}
821
822enum FieldMode {
823    Normal {
824        type_: TokenStream,
825        assign: TokenStream,
826    },
827    Seq {
828        push: TokenStream,
829        item: ParamConfig,
830    },
831    Map {
832        key: ParamConfig,
833        value: ParamConfig,
834    },
835}
836
837struct ParamConfig {
838    type_: TokenStream,
839    convert: Option<Expr>,
840}
841
842impl ParamConfig {
843    fn new(
844        struct_overrides: &StructOverrides,
845        overrides: NameArgs<ParamOverrides>,
846    ) -> Result<Self, Error> {
847        match overrides.args.custom {
848            Some(custom) => {
849                let type_ = custom.args.type_;
850                let convert = custom.args.convert;
851                Ok(ParamConfig {
852                    type_: quote!(#type_),
853                    convert: Some(convert),
854                })
855            }
856            None => {
857                let type_ = overrides.args.type_.as_ref().ok_or_else(|| {
858                    Error::new(overrides.name_span, "missing `type` configuration")
859                })?;
860
861                let (type_, convert) = if overrides.args.into {
862                    let private = struct_overrides.private();
863                    (
864                        quote!(impl #private::Into<#type_>),
865                        Some(syn::parse2(quote!(#private::Into::into)).unwrap()),
866                    )
867                } else {
868                    (quote!(#type_), None)
869                };
870
871                Ok(ParamConfig { type_, convert })
872            }
873        }
874    }
875
876    fn convert(&self, struct_overrides: &StructOverrides, name: &Ident) -> TokenStream {
877        match &self.convert {
878            Some(convert_fn) => call_convert(struct_overrides, name, convert_fn),
879            None => quote!(#name),
880        }
881    }
882
883    fn convert_iter(&self, struct_overrides: &StructOverrides, name: &Ident) -> TokenStream {
884        match &self.convert {
885            Some(convert_fn) => {
886                let private = struct_overrides.private();
887                quote! {
888                    #private::Iterator::map(
889                        #private::IntoIterator::into_iter(#name),
890                        #convert_fn,
891                    )
892                }
893            }
894            None => quote!(#name),
895        }
896    }
897}
898
899// Directly-invoked closures don't infer properly:
900// https://internals.rust-lang.org/t/directly-invoked-closure-inference-weirdness/20235
901fn call_convert(struct_overrides: &StructOverrides, name: &Ident, expr: &Expr) -> TokenStream {
902    match expr {
903        Expr::Closure(closure) => {
904            let private = struct_overrides.private();
905            quote!(#private::call_hack(#closure, #name))
906        }
907        expr => quote!(#expr(#name)),
908    }
909}
910
911impl<'a> ResolvedField<'a> {
912    fn new(
913        struct_overrides: &StructOverrides,
914        field: &'a Field,
915    ) -> Result<ResolvedField<'a>, Error> {
916        let name = field.ident.as_ref().unwrap();
917        let ty = &field.ty;
918
919        let stage = format!(
920            "{}Stage",
921            field
922                .ident
923                .as_ref()
924                .unwrap()
925                .to_string()
926                .to_upper_camel_case()
927        );
928        let stage = Ident::new(&stage, field.span());
929
930        let mut resolved = ResolvedField {
931            field,
932            default: None,
933            stage,
934            mode: FieldMode::Normal {
935                type_: quote!(#ty),
936                assign: quote!(#name),
937            },
938        };
939
940        let overrides = FieldOverrides::new(&field.attrs)?;
941
942        if let Some(default) = overrides.default {
943            let default = match default.value {
944                Some(v) => quote!(#v),
945                None => {
946                    let private = struct_overrides.private();
947                    quote!(#private::Default::default())
948                }
949            };
950            resolved.default = Some(default)
951        }
952
953        if overrides.into {
954            let private = struct_overrides.private();
955            resolved.mode = FieldMode::Normal {
956                type_: quote!(impl #private::Into<#ty>),
957                assign: quote!(#private::Into::into(#name)),
958            }
959        } else if let Some(custom) = overrides.custom {
960            let type_ = custom.args.type_;
961            let convert = custom.args.convert;
962            resolved.mode = FieldMode::Normal {
963                type_: quote!(#type_),
964                assign: call_convert(struct_overrides, name, &convert),
965            }
966        } else if let Some(list) = overrides.list {
967            if resolved.default.is_none() {
968                let private = struct_overrides.private();
969                resolved.default = Some(quote!(#private::Default::default()));
970            }
971            resolved.mode = FieldMode::Seq {
972                push: quote!(push),
973                item: ParamConfig::new(struct_overrides, list.args.item)?,
974            }
975        } else if let Some(set) = overrides.set {
976            if resolved.default.is_none() {
977                let private = struct_overrides.private();
978                resolved.default = Some(quote!(#private::Default::default()));
979            }
980            resolved.mode = FieldMode::Seq {
981                push: quote!(insert),
982                item: ParamConfig::new(struct_overrides, set.args.item)?,
983            }
984        } else if let Some(map) = overrides.map {
985            if resolved.default.is_none() {
986                let private = struct_overrides.private();
987                resolved.default = Some(quote!(#private::Default::default()));
988            }
989            resolved.mode = FieldMode::Map {
990                key: ParamConfig::new(struct_overrides, map.args.key)?,
991                value: ParamConfig::new(struct_overrides, map.args.value)?,
992            }
993        }
994
995        if let Some(stage) = overrides.stage {
996            resolved.stage = stage;
997        }
998
999        Ok(resolved)
1000    }
1001}
1002
1003#[derive(StructMeta, Default)]
1004struct FieldOverrides {
1005    default: Option<NameValue<Option<Expr>>>,
1006    into: bool,
1007    custom: Option<NameArgs<CustomOverrides>>,
1008    list: Option<NameArgs<SeqOverrides>>,
1009    set: Option<NameArgs<SeqOverrides>>,
1010    map: Option<NameArgs<MapOverrides>>,
1011    stage: Option<Ident>,
1012}
1013
1014impl FieldOverrides {
1015    fn new(attrs: &[Attribute]) -> Result<Self, Error> {
1016        attrs
1017            .iter()
1018            .filter(|a| a.meta.path().is_ident("builder"))
1019            .map(|a| a.parse_args())
1020            .next()
1021            .transpose()
1022            .map(|o| o.unwrap_or_default())
1023    }
1024}
1025
1026#[derive(StructMeta)]
1027struct CustomOverrides {
1028    #[struct_meta(name = "type")]
1029    type_: Type,
1030    convert: Expr,
1031}
1032
1033#[derive(StructMeta)]
1034struct SeqOverrides {
1035    item: NameArgs<ParamOverrides>,
1036}
1037
1038#[derive(StructMeta)]
1039struct ParamOverrides {
1040    #[struct_meta(name = "type")]
1041    type_: Option<Type>,
1042    into: bool,
1043    custom: Option<NameArgs<CustomOverrides>>,
1044}
1045
1046#[derive(StructMeta)]
1047struct MapOverrides {
1048    key: NameArgs<ParamOverrides>,
1049    value: NameArgs<ParamOverrides>,
1050}