Skip to main content

tor_config/
derive.rs

1//! Derive-deftly macro for deriving configuration objects.
2//!
3//! The macro defined here makes a configuration object
4//! able to participate in the arti configuration system by giving
5//! it a Builder type implementing the appropriate serde traits.
6//!
7//! It is more ergonomic and less error-prone for our purposes than
8//! `derive_builder`.
9//!
10//! ## Basic usage:
11//!
12//! ```
13//! use derive_deftly::Deftly;
14//! use tor_config::derive::prelude::*;
15//!
16//! #[derive(Deftly, Clone, Debug, PartialEq)]
17//! #[derive_deftly(TorConfig)]
18//! pub struct ExampleConfig {
19//!     #[deftly(tor_config(default))]
20//!     owner_uid: Option<u32>,
21//!
22//!     #[deftly(tor_config(default = { "~".to_string() }))]
23//!     path: String,
24//! }
25//! ```
26//! For topic-specific information, see one of the following:
27//!
28//! * [How to declare a configuration type](doc_howto)
29//! * [Code generated by the tor_config macro](doc_generated_code)
30//! * [Reference: Attributes supported by the tor_config macro](doc_ref_attrs)
31//! * [Differences from derive_builder](doc_differences)
32//! * [Types with magic handling](doc_magic_types)
33
34/// How to declare a configuration type
35///
36/// ## Getting started
37///
38/// Every configuration type should implement at least `Clone` and `Debug`;
39/// it should almost[^partialeq-notest] always implement `PartialEq` too.
40/// In addition to these, you should use `derive(Deftly)` and `derive_deftly(TorConfig)`
41/// to use this macro.
42///
43/// You can start out by copying this template:
44///
45/// ```
46/// use derive_deftly::Deftly;
47/// use tor_config::derive::prelude::*;
48///
49/// #[derive(Deftly, Clone, Debug, PartialEq)]
50/// #[derive_deftly(TorConfig)]
51/// pub struct XyzzyConfig {
52///     // ...
53/// }
54/// ```
55///
56/// ## Declaring fields
57///
58/// At this point, you start declaring the fields that should appear in the configuration.
59/// You declare them as struct fields (as usual);
60/// but to avoid mistakes, you need to specify the default behavior for each field.
61/// You typically do this in one of the following ways:
62///
63/// ```
64/// # use derive_deftly::Deftly;
65/// # use tor_config::derive::prelude::*;
66/// # fn some_function() -> u32 { 7 }
67/// # #[derive(Deftly, Clone, Debug, PartialEq)]
68/// # #[derive_deftly(TorConfig)]
69/// # pub struct Foo {
70///
71/// // If the user doesn't set this field, we set it by calling some_function().
72/// #[deftly(tor_config(default=some_function()))]
73/// value1: u32,
74///
75/// // If the user doesn't set this field, we set it by calling Default::default().
76/// #[deftly(tor_config(default))]
77/// value2: String,
78///
79/// // This field has no default!  It's an error if the user doesn't set this.
80/// // (See warnings on no_default below.)
81/// #[deftly(tor_config(no_default))]
82/// value3: u16,
83/// # }
84/// ```
85///
86/// Notes:
87/// - There is no "default" behavior for the unset fields: you need to say which one you want.
88///   This requirement is meant to avoid programming errors.
89/// - Try to avoid using `no_default` on any configuration element unless you truly want the user
90///   to specify it in their configuration file every time this section exists.
91///   It's okay to use `no_default`
92///   on something like the address of a fallback directory
93///   (where each one needs to be fully specified)
94///   or the nickname of an onion service
95///   (which needs to be specified for every onion service that exists).
96/// - If you use `no_default`, you will need to use [`no_default_trait`] on the structure
97///   as a whole.
98///
99/// ## Other things you can do
100///
101/// There are many other attributes you can set on struct and fields
102/// to control their behavior.
103/// See [the reference](doc_ref_attrs) for more information.
104///
105/// <!-- TODO: Write a cookbook for common patterns. -->
106///
107/// [^partialeq-notest]: If you decide not to implement `PartialEq` for some reason,
108///    you will need to use the [`no_test_default`] attribute to suppress a test that requires it.
109///    (I do not really know why you would do this.  Just implement `PartialEq`, or
110///    edit this documentation to explain why people would sometimes not want to implement it.)
111///
112/// [`no_default_trait`]: crate::derive::doc_ref_attrs#tmeta:no_default_trait
113/// [`no_test_default`]: crate::derive::doc_ref_attrs#tmeta:no_test_default
114pub mod doc_howto {}
115
116/// Code generated by the tor_config macro
117///
118/// > Here we describe the code generated by the `derive_deftly(TorConfig)` macro.
119/// > Note that this is the _default_ behavior;
120/// > particular [attributes](doc_ref_attrs) not described here will override it.
121///
122/// <!-- TODO: Add "See: X" notes links to the options that override each thing? -->
123///
124/// The `tor_config` macro generates a Builder struct, with a name formed by appending
125/// `Builder` to the name of the configuration struct.
126/// That is, if the configuration struct is `MyConfig`,
127/// the macro generates `MyConfigBuilder`.
128///
129/// The builder struct has the same visibility as the configuration struct.
130/// The builder struct has,
131/// for every ordinary field[^ordinary] of type T in the configuration struct,
132/// a field with the same name and type `Option<T>`.
133/// For every [sub-builder] field in the configuration struct of type `T`,
134/// it has a field with the same name and the type `TBuilder`.
135/// These fields are private.
136///
137/// The builder struct implements [`serde::Serialize`] and [`serde::Deserialize`].
138/// Every field is marked with `#[serde(default)]` to allow it to be absent
139/// in the toml configuration.
140///
141/// The builder struct implements [`derive_deftly::Deftly`].
142///
143/// The builder struct derives `Default`, `Clone`, and `Debug`.
144/// It also has a `new()` method that calls `Default::default()`.
145///
146/// The builder struct implements
147/// [`Builder`](crate::load::Builder),
148/// [`ConfigBuilder`](crate::load::ConfigBuilder),
149/// [`ExtendBuilder`](crate::extend_builder::ExtendBuilder)
150/// and [`Flattenable`](crate::Flattenable).
151///
152/// The _configuration struct_ receives a generated "builder" method,
153/// of type `fn () -> MyConfigBuilder`.
154/// This function calls the builder's `Default::default()` method.
155///
156/// For every ordinary[^ordinary] field of type T in the configuration struct,
157/// the builder has a **setter method** with the same name,
158/// of type `fn (&mut self, value: T) -> &mut Self`.
159/// The setter method sets the corresponding field in `self` to `Some(value)`,
160/// and returns `self``.
161///
162/// For every [sub-builder] field of type SubCfg in the configuration struct,
163/// the builder has an accessor method with the same name,
164/// returning `&mut SubCfgBuilder`.
165///
166/// The builder has a **build method**, with the name `build`,
167/// of type `fn (&self) -> Result<MyConfig, ConfigBuildError>`.
168/// It has the same visibility as the builder struct.
169/// For every field in the builder of value `Some(x)`,
170/// it sets the corresponding field in the configuration object to `x`.
171/// For every field in the builder of value `None`,
172/// it sets the corresponding field in the configuration object to its default,
173/// or returns an error,
174/// depending on the attributes set on the field.
175/// For every field in the builder with a [sub-builder],
176/// it invokes the build method on that sub-builder,
177/// and sets the corresponding field in the configuration object to its result.
178///
179/// A new `#[cfg(test)]` module is generated, with tests for the builder behavior.
180/// This module is called `test_my_config_builder`, with `my_config` replaced with the
181/// snake-case name of your actual configuration type.
182///
183/// [^ordinary]: For the purpose of this documentation,
184///     a field is "ordinary" if it does not have a [sub-builder].
185///
186///
187/// [sub-builder]: crate::derive::doc_ref_attrs#fmeta:sub_builder
188pub mod doc_generated_code {}
189
190/// Reference: Attributes supported by the tor_config macro
191///
192/// * [Top-level attributes](crate::derive::doc_ref_attrs#tmeta)
193/// * [Field-level attributes](crate::derive::doc_ref_attrs#fmeta)
194///
195/// <div id="tmeta">
196///
197/// ## Top-level attributes
198///
199/// </div>
200///
201/// These attributes can be provided at the top-level, right after
202/// `derive_deftly(TorConfig)` and before `pub struct FooConfig`.
203///
204/// <div id="tmeta:no_serialize_trait">
205///
206/// ### `deftly(tor_config(no_serialize_trait))`  — Don't derive Serialize for the builder struct
207///
208/// </div>
209///
210/// By default, the generated Builder will derive [`serde::Serialize`].
211/// This attribute suppresses that behavior.
212///
213///
214/// <div id="tmeta:no_deserialize_trait">
215///
216/// ### `deftly(tor_config(no_deserialize_trait))` — Don't derive Deserialize for the builder struct
217///
218/// </div>
219///
220/// By default, the generated Builder will implement [`serde::Deserialize`].
221/// This attribute suppresses that behavior.
222///
223/// Using this option will prevent your type from participating directly
224/// in the Arti configuration system.
225///
226///
227/// <div id="tmeta:no_flattenable_trait">
228///
229/// ### `deftly(tor_config(no_flattenable_trait))`  — Don't derive Flattenable for the builder struct
230///
231/// </div>
232///
233/// By default, the generated Builder will derive [`Flattenable`](crate::Flattenable).
234/// This attribute suppresses that behavior.
235///
236/// <div id="tmeta:no_extendbuilder_trait">
237///
238/// ### `deftly(tor_config(no_extendbuilder_trait))`  — Don't derive ExtendBuilder for the builder struct
239///
240/// </div>
241///
242/// By default, the generated Builder will derive [`ExtendBuilder`].
243/// This attribute suppresses that behavior.
244///
245/// <div id="tmeta:no_default_trait">
246///
247/// ### `deftly(tor_config(no_default_trait))` — Don't derive Default for the config struct
248///
249/// </div>
250///
251/// By default, the macro will derive [`Default`] on the configuration type
252/// by creating a default builder, and constructing the configuration type with it.
253///
254/// <div id="tmeta:no_test_default">
255///
256/// ### `deftly(tor_config(no_test_default))` — Don't test Default for the config struct
257///
258/// </div>
259///
260/// By default, the macro will implement a test to make sure that its generated `Default`
261/// implementation produces the same result as deserializing an empty configuration builder,
262/// and building it.
263/// This attribute prevents that test from being generated.
264///
265/// The test is also omitted when [`no_default_trait`] or [`no_deserialize_trait`] is given.
266///
267/// > Note: You must specify this option if the configuration type has any generic parameters.
268/// > Otherwise, it's best to avoid this attribute.
269/// >
270/// > TODO: We should remove this limitation if we can.
271///
272/// <div id="tmeta:no_builder_trait">
273///
274/// ### `deftly(tor_config(no_builder_trait))` — Don't derive Builder for the builder struct
275///
276/// </div>
277///
278/// By default, the builder will implement [`tor_config::load::Builder`](crate::load::Builder).
279/// This attribute suppresses that behavior.
280///
281/// > This attribute's name ends with `_trait` to remind the caller that the Builder struct itself
282/// > will still be implemented.
283///
284/// <div id="tmeta:no_buildable_trait">
285///
286/// ### `deftly(tor_config(no_buildable_trait))` — Don't derive Buildable for the config struct
287///
288/// </div>
289///
290/// By default, the configuration struct will implement
291/// [`tor_config::load::Buildable`](crate::load::Buildable).
292/// This attribute suppresses that behavior.
293///
294/// <div id="tmeta:attr">
295///
296/// ### `deftly(tor_config(attr = ..))` — Apply attribute(s) to the builder struct
297///
298/// </div>
299///
300/// This attribute passes its contents through to a new attribute on the derived builder struct.
301/// `tor_config(attr = ..)` maybe specified more than once, to apply multiple attributes.
302///
303/// For example, you can make the builder derive `PartialOrd` and `Ord` by saying
304///
305/// ```no_compile
306/// #[deftly(tor_config(attr= { derive(PartialOrd) }))]
307/// #[deftly(tor_config(attr= #[derive(Ord)]))]
308/// ```
309///
310/// (See also [`attr`](crate::derive::doc_ref_attrs#fmeta:attr) for fields.)
311///
312/// <div id="tmeta:pre_build">
313///
314/// ### `deftly(tor_config(pre_build = ..))` — Call a function before building
315///
316/// </div>
317///
318/// This attribute makes the generated `build()` method call a validation function on itself
319/// **before** it builds the configuration.  The function must take `&FooBuilder`
320/// as an argument, and return `Result<(),ConfigBuildError>`.  If the function
321/// returns an error, then the build method fails with that error.
322///
323/// Example:
324/// ```
325/// # use derive_deftly::Deftly;
326/// # use tor_config::{derive::prelude::*, ConfigBuildError};
327/// #[derive(Clone,Debug,PartialEq,Deftly)]
328/// #[derive_deftly(TorConfig)]
329/// #[deftly(tor_config(pre_build=Self::must_be_odd))]
330/// pub struct FavoriteOddNumber {
331///     #[deftly(tor_config(default=23))]
332///     my_favorite: u32,
333/// }
334///
335/// impl FavoriteOddNumberBuilder {
336///     fn must_be_odd(&self) -> Result<(), ConfigBuildError> {
337///         let Some(fav) = self.my_favorite else { return Ok(()); };
338///         if fav % 2 != 1 {
339///             return Err(ConfigBuildError::Invalid {
340///                 field: "my_favorite".to_string(),
341///                 problem: format!("{fav} was not an odd number")
342///             })
343///         }
344///         Ok(())
345///     }
346/// }
347/// ```
348///
349/// See also [`post_build`].
350///
351/// <div id="tmeta:post_build">
352///
353/// ### `deftly(tor_config(post_build = ..))` — Call a function after building
354///
355/// </div>
356///
357/// This attribute makes the generated `build()` method call a validation function
358/// on the configuration **after** it is built.
359/// The function must take the configuration
360/// _by value_ as an argument,
361/// and `Result<`(the configuration)`,ConfigBuildError>`.  If the function
362/// returns an error, then the build method fails with that error.
363///
364/// Example:
365/// ```
366/// # use derive_deftly::Deftly;
367/// # use tor_config::{derive::prelude::*, ConfigBuildError};
368/// #[derive(Clone,Debug,PartialEq,Deftly)]
369/// #[derive_deftly(TorConfig)]
370/// #[deftly(tor_config(post_build=FavoriteEvenNumber::must_be_even))]
371/// pub struct FavoriteEvenNumber {
372///     #[deftly(tor_config(default=86))]
373///     my_favorite: u32,
374/// }
375///
376/// impl FavoriteEvenNumber {
377///     fn must_be_even(self) -> Result<Self, ConfigBuildError> {
378///         if self.my_favorite % 2 != 0 {
379///             return Err(ConfigBuildError::Invalid {
380///                 field: "my_favorite".to_string(),
381///                 problem: format!("{} was not an even number", self.my_favorite)
382///             })
383///         }
384///         Ok(self)
385///     }
386/// }
387/// ```
388///
389/// > Note:
390/// > You can also use this attribute to clean up or normalize the configuration object.
391///
392/// <div id="tmeta:vis">
393///
394/// ### `deftly(tor_config(vis = ..))` — Change visibility of the builder
395///
396/// </div>
397///
398/// By default, the builder struct is generated with the same visibility as the
399/// configuration struct.
400/// You can use this attribute to change its visibility.
401///
402///
403/// <div id="tmeta:build_fn_name">
404///
405/// ### `deftly(tor_config(build_fn(name = ..)))` — Change name of the build method
406///
407/// </div>
408///
409/// By default, the generated build method is called `build`.
410/// You can use this attribute to change its name.
411///
412/// <div id="tmeta:build_fn_vis">
413///
414/// ### `deftly(tor_config(build_fn(vis = ..)))` — Change visibility of the build method
415///
416/// </div>
417///
418/// By default, the `build()` method has the same visibility as the builder struct.
419/// You can use this attribute to change its visibility.
420///
421/// See also:
422/// * [`deftly(tor_config(vis = ..))`](crate::derive::doc_ref_attrs#tmeta:vis)
423///
424/// <div id="tmeta:build_fn_error">
425///
426/// ### `deftly(tor_config(build_fn(error = ..)))` — Change return error type of the build method.
427///
428/// </div>
429///
430/// By default, the `build()` method returns [`ConfigBuildError`
431/// on failure.  You can change the error type with this attribute.
432///
433/// You will probably need to use this attribute along with [`build_fn(missing_field)`],
434/// if any of your fields are mandatory.
435///
436/// <div id="tmeta:build_fn_missing_field">
437///
438/// ### `deftly(tor_config(build_fn(missing_field = ..)))` — Code to generate a missing field error.
439///
440/// </div>
441///
442/// By default, when a required field is not set, the `build()` method returns
443/// `Err(E::MissingField { field: "field_name".to_string() })`,
444/// where `E` is [`ConfigBuildError`] or the type configured with [`build_fn(error)`].
445/// You can use this attribute to override this behavior.
446/// Its value should be an expression evaluating to a closure of type
447/// `FnOnce(&str) -> E`.
448///
449/// > For compatibility with `derive_builder`'s version of `build_fn(error)``, you can say:
450/// > ```no_compile
451/// > #[build_fn(error="SomeError",
452/// >            missing_field=
453/// >     r#"|fname| derive_builder::UninitializedFieldError(
454/// >                                  fname.to_string()
455/// >                ).into()"
456/// > )]
457/// > ```
458///
459/// <div id="fmeta">
460///
461/// ## Field-level attributes
462///
463/// </div>
464///
465/// <div id="fmeta:default_default">
466///
467/// ### `deftly(tor_config(default)))` — Use Default::default() when no value is provided
468///
469/// </div>
470///
471/// When this attribute is provided, if the given field is absent in the builder,
472/// the `build()` method will set its value to `Default::default()`.
473///
474/// For each field, you must specify exactly one of
475/// [`default`], [`default =`], [`no_default`], [`build`], [`try_build`], or [`sub_builder`].
476///
477/// <div id="fmeta:default_equals">
478///
479/// ### `deftly(tor_config(default = ..)))` — Use a given value when no value is provided
480///
481/// </div>
482///
483/// When this attribute is provided, if the given field is absent in the builder,
484/// the `build()` method will set its value to the value of the provided expression.
485/// The expression may invoke a function, but cannot use `self`.
486///
487/// The type of the default must match the type of the field _in the builder_.
488/// Usually this is the same type as in the built configuration, but for some
489/// ["magic" types](crate::derive::doc_magic_types), the two can differ.
490/// (If this is the case, we note the fact with the "magic" type's documentation.)
491///
492/// For each field, you must specify exactly one of
493/// [`default`], [`default =`], [`no_default`], [`build`], [`try_build`], or [`sub_builder`].
494///
495///
496/// <div id="fmeta:no_default">
497///
498/// ### `deftly(tor_config(no_default))` — Do not provide a default for this field.
499///
500/// </div>
501///
502/// When this attribute is provided, if the given field is absent in the builder,
503/// the `build()` method will fail with an error.
504///
505/// For each field, you must specify exactly one of
506/// [`default`], [`default =`], [`no_default`], [`build`], [`try_build`], or [`sub_builder`].
507///
508/// > When you set this attribute on a field, you must also set the top-level
509/// > [`no_default_trait`] attribute,
510/// > since there will not be a meaningful value for the configuration struct.
511/// >
512/// > Don't use this option on any config struct that's always present with a multiplicity of one,
513/// > or else the empty configuration will become invalid.
514///
515/// <div id="fmeta:build">
516///
517/// ### `deftly(tor_config(build = ..))` — Call a function to build this field.
518///
519/// </div>
520///
521/// When this attribute is provided, you can completely override the way that this field is constructed.
522/// The expression must evaluate to a function taking `&Builder` as an argument,
523/// and returning the type of the field.
524///
525/// For each field, you must specify exactly one of
526/// [`default`], [`default =`], [`no_default`], [`build`], [`try_build`], or [`sub_builder`].
527///
528/// > Be careful with this attribute: it can lead to counterintuitive behavior for the end user.
529///
530/// Example:
531///
532/// ```
533/// # use derive_deftly::Deftly;
534/// # use tor_config::{derive::prelude::*, ConfigBuildError};
535/// #[derive(Clone,Debug,PartialEq,Deftly)]
536/// #[derive_deftly(TorConfig)]
537/// pub struct LowercaseExample {
538///     #[deftly(tor_config(build=Self::build_lc))]
539///     lc: String,
540/// }
541/// impl LowercaseExampleBuilder {
542///     fn build_lc(&self) -> String {
543///         let s = self.lc.as_ref().map(String::as_str).unwrap_or("");
544///         s.to_lowercase()
545///     }
546/// }
547/// ```
548///
549/// <div id="fmeta:try_build">
550///
551/// ### `deftly(tor_config(try_build = ..))` — Call a fallible function to build this field.
552///
553/// </div>
554///
555/// When this attribute is provided, you can completely override the way that this field is constructed.
556/// The expression must evaluate to a function taking `&Builder` as an argument,
557/// and returning `Result<T, ConfigBuildError>`, where `T` is the type of the field.
558///
559/// For each field, you must specify exactly one of
560/// [`default`], [`default =`], [`no_default`], [`build`], [`try_build`], or [`sub_builder`].
561///
562/// > Be careful with this attribute: it can lead to counterintuitive behavior for the end user.
563///
564/// Example:
565///
566/// ```
567/// # use derive_deftly::Deftly;
568/// # use tor_config::{derive::prelude::*, ConfigBuildError};
569/// #[derive(Clone,Debug,PartialEq,Deftly)]
570/// #[derive_deftly(TorConfig)]
571/// pub struct SqrtExample {
572///     #[deftly(tor_config(try_build=Self::build_sqrt))]
573///     val: f64,
574/// }
575/// impl SqrtExampleBuilder {
576///     fn build_sqrt(&self) -> Result<f64, ConfigBuildError> {
577///         let v = self.val.unwrap_or(0.0).sqrt();
578///         if v.is_nan() {
579///             return Err(ConfigBuildError::Invalid {
580///                 field: "val".to_string(),
581///                 problem: format!("{v} was negative")
582///             })
583///         }
584///         Ok(v)
585///     }
586/// }
587/// ```
588///
589/// <div id="fmeta:sub_builder">
590///
591/// ### `deftly(tor_config(sub_builder))` — Declare a field to contain a nested configuration
592///
593/// </div>
594///
595/// This attribute is what allows configuration structures to nest.
596/// When you set this attribute on a field of type `InnerCfg`,
597/// the builder structure will contain a field of type `InnerCfgBuilder`.
598/// In order to construct the field, the `build()` method will call
599/// `InnerCfgBuilder::build()`.
600///
601/// For each field, you must specify exactly one of
602/// [`default`], [`default =`], [`no_default`], [`build`], [`try_build`], or [`sub_builder`].
603///
604/// <div id="fmeta:sub_builder_build_fn">
605///
606/// ### `deftly(tor_config(sub_builder(build_fn = ..)))` — Call a different function on this sub-builder
607///
608/// </div>
609///
610/// By default, when [`sub_builder`] is in use,
611/// the `build()` method is used to generate the inner configuration object.
612/// This attribute changes the name of the function that is called on the inner builder.
613///
614/// <div id="fmeta:no_sub_builder">
615///
616/// ### `deftly(tor_config(no_sub_builder))` — Allow a Buildable field _without_ a sub_builder.
617///
618/// </div>
619///
620/// By default, the `TorConfig` macro inserts code to checks whether each field
621/// implements [`Buildable`], and causes a compile-time error if any such field
622/// does not have an explicit [`sub_builder`], [`build`], [`try_build`],
623/// or [`no_magic`] declaration.
624/// This attribute overrides this check, and allows you to have a field
625/// implementing [`Buildable`] without using the `sub_builder` pattern.
626///
627///
628/// <div id="fmeta:list">
629///
630/// ### `deftly(tor_config(list))` — Declare a field to contain a nested list of items.
631///
632/// </div>
633///
634/// This attribute should be used on every field containing a `Vec`,
635/// `BTreeSet`, `HashSet`, or similar.
636/// It causes the an appropriate [list-builder](crate::list_builder)
637/// and set of accessors to be generated.
638///
639/// When using this attribute, you must also provide a [`default =`] producing a `Vec`
640/// of the builder type, and either [`list(element(build))`] or [`list(element(clone))`].
641///
642/// Examples:
643///
644/// ```no_compile
645/// // The builder and the constructed list will both contain u32.
646/// #[deftly(tor_config(list(element(clone)), default = vec![7]))]
647/// integers: Vec<u32>,
648///
649/// // The builder will contain a Vec<MyTypeBuilder>;.
650/// #[deftly(tor_config(list(), (element(build)), default = vec![]))]
651/// objects: Vec<MyType>
652/// ```
653///
654/// <div id="fmeta:list_listtype">
655///
656/// ### `deftly(tor_config(list(listtype = ...)))`
657///
658/// </div>
659///
660/// Usually, the name of the list type alias and builder object  based on the struct and the field name.
661/// You can provide a different name for the list type alias using this attribute, as in
662/// `listtype = TypeName`.
663/// The list builder will then be constructed with the list type name, suffixed with `Builder`.
664///
665///  <!-- TODO:
666///    We could support a third option, where we give an explicit closure to build elements.
667///    We could support an option where the types in the builder vec are listed explicitly.
668/// -->
669///
670/// <div id="fmeta:list_element_build">
671///
672/// ### `deftly(tor_config(list(element(build)))` — Declare that the list builder contains sub-builders.
673///
674/// </div>
675///
676/// Used along with [`list`],
677/// and indicates the elements of the built list should be constructed via
678/// builders themselves.  When this attribute is used, the builder structure
679/// will contain a Vec of builders for the list's elements.
680///
681/// If this attribute is given a value, it will be used as the name of the
682/// "build" method for the list elements.
683///
684/// <div id="fmeta:list_element_clone">
685///
686/// ### `deftly(tor_config(list(element(clone)))` — Declare that the list builder objects should be cloned directly.
687///
688/// </div>
689///
690/// Used along with [`list`],
691/// and indicates the elements of the built list should be cloned directly
692/// from those in the builder.  When this attribute is used, the builder structure
693/// will contain a Vec whose elements are the same type as those of the genated list.
694///
695/// <div id="fmeta:map">
696///
697/// ### `deftly(tor_config(map))` — Use a map-builder pattern.
698///
699/// </div>
700///
701/// This attribute should be used on every field containing a `HashMap` or `BTreeMap`
702/// whose key is a `String`, and whose value type is a [`Buildable`].
703/// It causes the template to generate a map builder type and corresponding accessor functions.
704/// The map builder behaves like a map from String to the builder type.
705///
706/// If a value is provided for this attribute, it is used as the name of the
707/// map type alias, and suffixed with `Builder` to get the name for the builder type.
708/// Otherwise, the map type alias is derived from the name of the struct and the field.
709///
710/// The [`default =`] attribute is mandatory with this attribute.
711///
712/// For more information on the generated code, see
713/// [`define_map_builder`](crate::define_map_builder).
714///
715/// <div id="fmeta:map_maptype">
716///
717/// ### `deftly(tor_config(list(maptype = ...)))`
718///
719/// </div>
720///
721/// Usually, the name of the map type alias and builder object  based on the struct and the field name.
722/// You can provide a different name for the map type alias using this attribute, as in
723/// `maptype = TypeName`.
724/// The map builder will then be constructed with the map type name, suffixed with `Builder`.
725///
726/// <div id = "fmeta:setter_name">
727///
728/// ### `deftly(tor_config(setter(name = ..)))` — Change the name of the setter function
729///
730/// </div>
731///
732/// By default, the setter function for a field has the same name as its field.
733/// You can provide a different name in this attribute.
734///
735/// <div id="fmeta:setter_vis">
736///
737/// ### `deftly(tor_config(setter(vis = ..)))` — Change the visibility of the setter function
738///
739/// </div>
740///
741/// By default, the setter function for a field has the same visibility as the builder type.
742/// You can provide a different visibility in this attribute.
743///
744/// <div id="fmeta:setter_skip">
745///
746/// ### `deftly(tor_config(setter(skip)))` — Do not generate a setter function
747///
748/// </div>
749///
750/// By default, the builder generates a setter function for every field.
751/// You can tell it not to do so for a single field by providing this attribute.
752///
753/// <div id="fmeta:setter_into">
754///
755/// ### `deftly(tor_config(setter(into)))` — Have the setter function accept `impl Into<T>`
756///
757/// </div>
758///
759/// By default, the setter function expects an argument of type `T`,
760/// where `T` is the same type of the field.
761/// When this option is provided, the setter instead expects an argument of type `impl Into<T>`,
762/// and calls [`Into::into`] on it to set the field.
763///
764/// <div id="fmeta:setter_try_into">
765///
766/// ### `deftly(tor_config(setter(try_into)))` — Have the setter function accept `impl TryInto<T>`
767///
768/// </div>
769///
770/// By default, the setter function expects an argument of type `T`,
771/// where `T` is the same type of the field.
772/// When this option is provided, the setter instead expects an argument of type `impl TryInto<T>`,
773/// and calls [`TryInto::try_into`] on it to set the field.
774/// If `try_into` returns an error, the setter function returns that error.
775///
776/// <div id="fmeta:setter_strip_option">
777///
778/// ### `deftly(tor_config(setter(strip_option)))` — Have the setter for `Option<T>` accept `T`
779///
780/// </div>
781///
782/// This attribute requires that the field itself have type `Option<T>` for some `T`.
783/// Instead of taking `Option<T>` as an argument, the setter now accepts `T`.
784///
785/// <!-- TODO -- Do we still want this, given that option magic should take care of it for us,
786/// and will do a better job? -->
787///
788/// <div id="fmeta:field_ty">
789///
790/// ### `deftly(tor_config(field(ty = ..)))` — Change the type of a field in the builder
791///
792/// </div>
793///
794/// By default, for every field of type `T` in the configuration,
795/// the builder has a field of type `Option<T>`.
796/// This attribute changes the type of the field in the builder to the provided type.
797///
798/// > This attribute has no effect on the generated setter or builder code.
799/// > Therefore, you will typically need to use it along with
800/// > the [`setter(skip)`], [`build`], and [`extend_with`] field attributes.
801///
802/// Example:
803///
804/// ```
805/// # #![allow(unexpected_cfgs)]
806/// # use derive_deftly::Deftly;
807/// # use tor_config::{derive::prelude::*, ConfigBuildError};
808/// #[derive(Clone,Debug,PartialEq)]
809/// pub struct ParsedValue {
810///    // ...
811/// }
812/// impl std::str::FromStr for ParsedValue {
813///     type Err = String;
814///     fn from_str(s: &str) -> Result<Self, Self::Err> {
815///         // ...
816/// #       unimplemented!()
817///     }
818/// }
819///
820/// #[derive(Clone,Debug,PartialEq,Deftly)]
821/// #[derive_deftly(TorConfig)]
822/// pub struct MyConfig {
823///     #[deftly(tor_config(
824///         try_build = Self::try_build_behavior,
825///         field(ty = { Option<String> }),
826///         setter(skip)
827///     ))]
828///     behavior: ParsedValue,
829/// }
830///
831/// impl MyConfigBuilder {
832///     pub fn behavior(&mut self, s: impl AsRef<str>) -> &mut Self {
833///         self.behavior = Some(s.as_ref().to_string());
834///         self
835///     }
836///     fn try_build_behavior(&self) -> Result<ParsedValue, ConfigBuildError> {
837///         self.behavior
838///             .as_ref()
839///             .map(String::as_str)
840///             .unwrap_or("Leave the macro processor. Take the cannoli.")
841///             .parse()
842///             .map_err(|problem| ConfigBuildError::Invalid {
843///                 field: "behavior".to_string(),
844///                 problem,
845///             })
846///     }
847/// }
848/// ```
849///
850/// <div id="fmeta:apply_field_default">
851///
852/// ### `deftly(tor_config(apply_field_default = { FIELD_DEFAULT }))` — Apply a default for a specialized builder.
853///
854/// </div>
855///
856/// By default, the builder's generated [`apply_defaults()`] method
857/// does nothing for fields with [`build`] or [`try_build`] attributes,
858/// and recursively calls [`apply_defaults()`]
859/// for [`sub_builder`] fields.
860///
861/// This attribute replaces that behavior for a single field.
862/// FIELD_DEFAULT must be an expression that expands to a closure taking `&mut Self` as an argument.
863/// It checks whether the field is set,
864/// and sets it to a reasonable default otherwise.
865/// It must return Result<(), E>, where E is some type implementing `Into<ConfigBuildError>`.
866/// Within `FIELD_DEFAUlT`, `self` refers to the `Builder`.
867/// The [`build`] or [`try_build`] functions for that field may assume
868/// that the FIELD_DEFAULT has already been executed.
869///
870/// The code in this attribute is invoked after earlier fields are set to their defaults,
871/// and before later fields are set to theirs.
872///
873/// It is an error to use this attribute along with [`default`] or [`no_default`].
874///
875/// <div id="fmeta:field_vis">
876///
877/// ### `deftly(tor_config(field(vis = ..)))` — Change the visibility of a field in the builder
878///
879/// </div>
880///
881/// By default, fields in the builder are private.
882/// This attribute changes their visibility to the one provided.
883///
884///
885/// <div id="fmeta:skip">
886///
887/// ### `deftly(tor_config(skip))` — Do not generate the field in the builder
888///
889/// </div>
890///
891/// If this attribute is present, no field is generated in the builder for this field.
892/// Implies [`setter(skip)`].  Requires [`build`].
893///
894/// <div id="fmeta:attr">
895///
896/// ### `deftly(tor_config(attr = { .. })))` — Apply an attribute to the field in the builder
897///
898/// </div>
899///
900/// Any attribute provided here is applied to the declared field in the builder.
901///
902/// Example:
903/// ```no_compile
904/// #[deftly(tor_config(attr = { allow(deprecated) }))]
905/// x: SomeDeprecatedType,
906/// ```
907///
908/// <!-- TODO: write up a list of recommended serde attributes -->
909///
910/// See also the [`cfg`](crate::derive::doc_ref_attrs#fmeta:cfg) attribute.
911///
912/// <div id="fmeta:serde">
913///
914/// ### `deftly(tor_config(serde = { .. })))` — Apply a serde attribute (deprecated)
915///
916/// </div>
917///
918/// **Deprecated**: use
919/// [`#[deftly(tor_config(attrs = serde(...)))]`(crate::derive::doc_ref_attrs#fmeta:attrs) instead.
920///
921/// Any serde attribute provided here is applied to the declared field in the builder.
922///
923/// Example:
924/// ```no_compile
925/// #[deftly(tor_config(serde = { alias = old_name_of_field }))]
926/// current_name_of_field: String,
927/// ```
928///
929/// Attributes applied with `serde` apply after any specified with
930/// [`attr`](crate::derive::doc_ref_attrs#fmeta:attr) instead.
931///
932/// <div id="fmeta:extend_with">
933///
934/// ### `deftly(tor_config(extend_with = ..))` — Change the ExtendBuilder behavior for a field.
935///
936/// </div>
937///
938/// Unless you specify [`no_extendbuilder_trait`], the builder type will
939/// implement [`ExtendBuilder`],
940/// and will need a way to replace or extend every field in the builder with
941/// the value from another builder.
942/// This attribute lets you override the default behavior for a single field.
943/// It expects an expression that evaluates to type
944/// `FnOnce(&mut T, T, `[`ExtendStrategy`]`)`,
945/// where `T` is the type of the field in the builder.
946///
947/// <div id="fmeta:cfg">
948///
949/// ### `deftly(tor_config(cfg = { .. })))` — Mark a field as conditionally present
950///
951/// </div>
952///
953/// This option causes a field in the builder to be conditionally present or absent at compile time,
954/// similar to the ordinary [`cfg`] attribute.
955/// However, unlike with the ordinary `cfg` attribute,
956/// if the user provides any configuration values for this field when it is disabled,
957/// the generated `build()` code will emit a warning via [`tracing`] at runtime telling them
958/// what feature they would need to turn on.
959///
960/// If an error is more appropriate than a warning, additionally use
961/// [`cfg_reject`].
962///
963/// > Note that you _cannot_ use this along with a regular [`cfg`] attribute,
964/// > since a regular [`cfg`] attribute would suppress the field altogether.
965/// > Therefore, the field will still be present in the configuration struct
966/// > even when the `cfg` condition is false.
967/// > To work around this limitation, it's conventional to arrange for the type of the field
968/// > to be `()` when the `cfg` condition is false.
969///
970/// The `tor_config(cfg_desc)` attribute is mandatory to use along with `cfg`.
971/// It should contain a short prepositional phrase
972/// describing how the program needs to be built with
973/// in order to make this feature present.
974/// Examples might be "with RPC support" or "for Windows".
975///
976///
977/// Example:
978/// ```
979/// # #![allow(unexpected_cfgs)]
980/// # use derive_deftly::Deftly;
981/// # use tor_config::{derive::prelude::*, ConfigBuildError};
982/// #[cfg(feature = "rpc")]
983/// pub type RpcOptionType = String;
984///
985/// #[cfg(not(feature = "rpc"))]
986/// type RpcOptionType = ();
987///
988/// #[derive(Clone,Debug,PartialEq,Deftly)]
989/// #[derive_deftly(TorConfig)]
990/// pub struct OnionSoupConfig {
991///     #[deftly(tor_config(cfg = { feature="rpc" }, cfg_desc = "with RPC support"))]
992///     #[deftly(tor_config(default))]
993///     rpc_option: RpcOptionType,
994/// }
995/// ```
996///
997/// <!-- TODO: This is a warning now, since it is in general only a warning
998///      to use an option that is not recognized.
999///      We may want to provide a variant that produces an error instead. -->
1000///
1001/// <div id="fmeta:cfg_reject">
1002///
1003/// ### `deftly(tor_config(cfg_reject))` — Reject the configuration when a feature is missing.
1004///
1005/// </div>
1006///
1007/// Used alongside [`tor_config(cfg)`](#fmeta:cfg); see also that attribute's documentation.
1008///
1009/// Usually, `tor_config(cfg)` causes a warning if values are provided
1010/// for a compiled-out configuration option.
1011/// When this attribute is present, then `tor_config(cfg)` causes an error instead.
1012///
1013/// <div id="fmeta:cfg_desc">
1014///
1015/// ### `deftly(tor_config(cfg_desc = "..")))` — Description of when a field is present.
1016///
1017/// </div>
1018///
1019/// Used along with [`tor_config(cfg)`](#fmeta:cfg); see that attribute's documentation.
1020///
1021/// <div id="fmeta:no_magic">
1022///
1023/// ### `deftly(tor_config(no_magic)))` — Disable magic handling based on a field's type
1024///
1025/// </div>
1026///
1027/// This attribute disables [type-based magic behavior](crate::derive::doc_magic_types)
1028/// for the current field.
1029///
1030/// [`apply_defaults()`]: crate::load::ConfigBuilder::apply_defaults
1031/// [`build_fn(error)`]:  crate::derive::doc_ref_attrs#tmeta:build_fn_error
1032/// [`build_fn(missing_field)`]:  crate::derive::doc_ref_attrs#tmeta:build_fn_missing_field
1033/// [`build`]: crate::derive::doc_ref_attrs#fmeta:build
1034/// [`Buildable`]: crate::load::Buildable
1035/// [`ConfigBuildError`]: crate::ConfigBuildError
1036/// [`cfg_reject`]: crate::derive::doc_ref_attrs#fmeta:cfg_reject
1037/// [`default =`]: crate::derive::doc_ref_attrs#fmeta:default_equals
1038/// [`default`]: crate::derive::doc_ref_attrs#fmeta:default_default
1039/// [`extend_with`]: crate::derive::doc_ref_attrs#fmeta:extend_with
1040/// [`ExtendBuilder`]: crate::extend_builder::ExtendBuilder
1041/// [`ExtendStrategy`]: crate::extend_builder::ExtendStrategy
1042/// [`list`]: crate::derive::doc_ref_attrs#fmeta:list
1043/// [`list(listtype)`]: crate::derive::doc_ref_attrs#fmeta:list_listtype
1044/// [`list(element(build))`]:  crate::derive::doc_ref_attrs#fmeta:list_element_build
1045/// [`list(element(clone))`]:  crate::derive::doc_ref_attrs#fmeta:list_element_clone
1046/// [`no_default`]: crate::derive::doc_ref_attrs#fmeta:no_default
1047/// [`no_default_trait`]: crate::derive::doc_ref_attrs#tmeta:no_default_trait
1048/// [`no_deserialize_trait`]: crate::derive::doc_ref_attrs#tmeta:no_deserialize_trait
1049/// [`no_extendbuilder_trait`]: crate::derive::doc_ref_attrs#tmeta:no_extendbuilder_trait
1050/// [`no_flattenable_trait`]: crate::derive::doc_ref_attrs#tmeta:no_flattenable_trait
1051/// [`no_magic`]: crate::derive::doc_ref_attrs#fmeta:no_default
1052/// [`post_build`]: crate::derive::doc_ref_attrs#tmeta:post_build
1053/// [`serde`]:  crate::derive::doc_ref_attrs#fmeta:serde
1054/// [`setter(skip)`]: crate::derive::doc_ref_attrs#fmeta:setter_skip
1055/// [`sub_builder`]: crate::derive::doc_ref_attrs#fmeta:sub_builder
1056/// [`try_build`]: crate::derive::doc_ref_attrs#fmeta:try_build
1057pub mod doc_ref_attrs {}
1058
1059/// Differences from `derive_builder`
1060///
1061/// * Not all derive_builder attributes have been cloned: only the ones that we used.
1062/// * Attributes have been adjusted where possible to be easier to use.
1063/// * It is not necessary to use `impl_standard_builder!`
1064/// * The appropriate `serde` attributes are automatically provided on the builder.
1065/// * Every field must have some default behavior specified, or must have the `no_default` option given.
1066///   (With `derive_builder`, `no_default` is the default, which can result in confusing test failures.)
1067/// * Sub-builders are supported.
1068/// * The `cfg` attribute can be used to warn when the user
1069///   tries to provide a value for an compiled-out field.
1070/// * There is (limited) support for generics.
1071/// * The generated documentation is a little better.
1072/// * `validate` has been renamed to `pre_build`.
1073/// * There is `post_build` attribute to replace the pattern where we would rename the build function,
1074///   make it private, and wrap it.
1075/// * A top-level `build_fn` does not override the build function on sub-builders.
1076/// * The list builder and map builder patterns are supported via attributes; you don't need separate
1077///   macros for them.
1078/// * Builders automatically derive `ExtendBuilder`, `Flattenable`, and `Builder`.
1079/// * The configuration type automatically derives `Buildable`.
1080/// * Visibility is set more reasonably.
1081/// * For many types, we automatically generate setters or serde code that conforms
1082///   to our standards.
1083pub mod doc_differences {}
1084
1085/// # Types with "magic" handling
1086///
1087/// The `derive_deftly(TorConfig)` macro currently has automatic "magic"
1088/// handling for a few types, and a few other types where it can "magically"
1089/// detect that you forgot to use a certain option that you probably wanted.
1090///
1091/// To override the magic handling for a field, use the [`tor_config(no_magic)`]
1092/// attribute on that field.
1093///
1094/// These types are handled on a best-effort basis by matching their names.
1095/// If you define a field to have another type that is an alias one of these,
1096/// the macro won't be able to handle it.
1097/// To prevent this case, we use [`assert_not_impl`]
1098/// to insure that you will get a compile-time error if you use one of these
1099/// types under a different name without specifying [`tor_config(no_magic)`].
1100///
1101/// The types with magic handling are:
1102///
1103/// ## `String`
1104///
1105/// The setter for each [`String`] field takes `impl `[`StringOrStr`] as its argument.
1106/// This trait is implemented by `String` and `&str`.
1107///
1108/// > Earlier we had considered having it take `AsRef<str>`, but this is too general
1109/// > and can lead to unwanted surprises.
1110///
1111/// ## `NonZero<T>`
1112///
1113/// The setter for a [`NonZero`]`<T>` field takes
1114/// `impl `[`PossiblyBoundsChecked`]`<T>` as its argument.
1115/// This trait is implemented by `T` and by [`NonZero`]`<T>`.
1116///
1117/// The default for a `NonZero<T>` should be of type `T`.
1118/// (Passing the value `0` will cause a test failure.)
1119///
1120/// When the build() function is called, it returns an error if the provided
1121/// value was zero.
1122///
1123/// ## `Duration`
1124///
1125/// The serde implementations for a [`Duration`](std::time::Duration) field
1126/// use [`humantime_serde`] to accept and generate human-readable strings.
1127///
1128/// ## `Option`
1129///
1130/// For an `Option<T>` field, the setter accepts both `T` and `Option<T>`.
1131/// It does so by requiring that the argument implement traits as follows:
1132///
1133/// | Field type           | Setter arg trait                     | Implemented by |
1134/// | -------------------- | ------------------------------------ | -------------- |
1135/// | `Option<String>`     | [`OptionStringOrStr`]                | `String, &str, Option<String>, Option<&str>` |
1136/// | `Option<NonZero<T>>` | [`OptionPossiblyBoundsChecked`]`<T>` | `T, NonZero<T>, Option<T>, Option<NonZero<T>> `|
1137/// | `Option<T>`          | [`PossiblyOption`]`<T>`              | `T, Option<T>` |
1138///
1139/// ## `impl Buildable`
1140///
1141/// Any type that implements buildable must either use a the [`sub_builder`] attribute,
1142/// or opt out of it with [`no_sub_builder`] or [`no_magic`].
1143///
1144/// ## `Vec`, `HashSet`, `BTreeSet`
1145///
1146/// These types require you to either use the [`list`] attribute,
1147/// or to opt out of it with [`no_sub_builder`] or [`no_magic`].
1148///
1149/// ## `HashMap<String, impl Buildable>`, `BTreeMap<String, impl Buildable>`
1150///
1151/// These types require you to either use the [`map`] attribute,
1152/// or to opt out of it with [`no_sub_builder`] or [`no_magic`].
1153///
1154/// ## `Option<Duration>`
1155///
1156/// This type will cause a compile-time error unless you set [`no_magic`],
1157/// since there is not actually a way to
1158/// set a None in toml (other than omitting the value).
1159///
1160/// > (TODO: Doesn't) that logic apply to _all_ Option types?
1161///
1162/// ## Container of `Duration`.
1163///
1164/// These are currently disallowed unless you provide [`no_magic`],
1165/// and will cause a compile-time error,
1166/// since we cannot apply our regular serde magic.
1167///
1168/// [`StringOrStr`]: crate::setter_traits::StringOrStr
1169/// [`OptionStringOrStr`]: crate::setter_traits::OptionStringOrStr
1170/// [`PossiblyBoundsChecked`]: crate::setter_traits::PossiblyBoundsChecked
1171/// [`OptionPossiblyBoundsChecked`]: crate::setter_traits::OptionPossiblyBoundsChecked
1172/// [`PossiblyOption`]: crate::setter_traits::PossiblyOption
1173/// [`NonZero`]: std::num::NonZero
1174/// [`tor_config(no_magic)`]: crate::derive::doc_ref_attrs#fmeta:no_magic
1175/// [`list`]: crate::derive::doc_ref_attrs#fmeta:list
1176/// [`map`]: crate::derive::doc_ref_attrs#fmeta:map
1177/// [`sub_builder`]: crate::derive::doc_ref_attrs#fmeta:sub_builder
1178/// [`no_sub_builder`]: crate::derive::doc_ref_attrs#fmeta:no_sub_builder
1179/// [`no_magic`]: crate::derive::doc_ref_attrs#fmeta:no_magic
1180pub mod doc_magic_types {}
1181
1182// TODO:
1183// - Can I replace cfg() with a single FeatureNotSupported type, or a family of such types?
1184//   (See #2298.)
1185// - We must decide before merging whether we actually _want_ to always accept T
1186//   for setters on `NonZero<T>`.  There are some places in our code where we do this now:
1187//   so if we were to stop doing so, we'd be breaking backward compat in the `arti` crate.
1188//   But that doesn't  mean we need to continue to do so everywhere.
1189//   (See #2296)
1190
1191use derive_deftly::define_derive_deftly;
1192
1193/// Values used by the tor_config derive_deftly template.
1194#[doc(hidden)]
1195pub mod exports {
1196    pub use super::{
1197        ShouldBeCaughtAsSerdeSpecialCase, ShouldBeCaughtAsSpecialCase, ShouldNotBeUsed,
1198        ShouldUseListBuilder, ShouldUseMapBuilder, assert_not_impl, bld_magic_check_type,
1199        bld_magic_cvt, bld_magic_setter_arg_type, bld_magic_setter_cvt, bld_magic_setter_docs,
1200        bld_magic_type, list_element, normalize_and_invoke, strip_option,
1201    };
1202    pub use crate::flatten::derive_deftly_template_Flattenable;
1203    pub use crate::{
1204        ConfigBuildError, define_list_builder_accessors, define_list_builder_helper,
1205        define_map_builder,
1206        extend_builder::{ExtendBuilder, ExtendStrategy},
1207        impl_standard_builder,
1208        load::Buildable as BuildableTrait,
1209        load::Builder as BuilderTrait,
1210        load::ConfigBuilder,
1211    };
1212    pub use derive_deftly::Deftly;
1213    pub use figment;
1214    pub use humantime_serde;
1215    pub use serde::{Deserialize, Deserializer, Serialize, Serializer};
1216    pub use serde_value;
1217    pub use std::{
1218        clone::Clone,
1219        convert::{AsRef, Into, TryInto},
1220        default::Default,
1221        fmt::Debug,
1222        option::Option,
1223        result::Result,
1224    };
1225    pub use tracing;
1226    pub use void;
1227}
1228
1229/// Module to import in order to use the tor_config template.
1230pub mod prelude {
1231    pub use super::derive_deftly_template_TorConfig;
1232}
1233
1234/// Helper to implement `strip_option`: Takes a single argument whose type is an Option<T>,
1235/// and yields T.
1236#[doc(hidden)]
1237#[macro_export]
1238macro_rules! strip_option {
1239    { $($($(::)? std::)? option::)? Option $(::)? < $t:ty >  } => { $t };
1240    { $t:ty } => { compile_error!{"'strip_option' only works on a type that is an Option<X>"} }
1241}
1242pub use strip_option;
1243
1244/// Helper: Takes a @command name, a {type}, and a list of arguments.
1245/// Determines which macro corresponds to the type,
1246/// and invokes that macro with arguments: @command {type} args.
1247///
1248/// The macros corresponding to types are [`string_typemagic`] for `String`,
1249/// [`nonzero_typemagic`] for `NonZero*`,
1250/// and [`no_typemagic`] for everything else.
1251///
1252/// Recognized @commands are:
1253///  - `@build_type {ty}` - The type that should be used as `T` for the builder field's `Option<T>`.
1254///  - `@setter_arg_type {ty}` - The type that the setter should take as an argument.
1255///  - `@setter_cvt {ty} {e}`- Code to run inside the setter to convert {e} into a `@build_type {ty}`
1256///  - `@build_field {ty} {e} {name}` - Code to convert `@build_type {ty}` into {ty}.  Uses the
1257///    field name `{fname}` to generate errors.
1258///  - `@check_type {ty}` - Make sure that it is not a bug for this type to have reached this position.
1259///    Give a compile-time error if it is.
1260///  - `@setter_docs {ty}` - A string to add to the setter documentation.
1261#[doc(hidden)]
1262#[macro_export]
1263macro_rules! normalize_and_invoke {
1264    // HEY YOU! DON'T ADD OR REMOVE ANY TYPES WITHOUT READING THE COMMENT BELOW!
1265    { @$cmd:ident {$( $($(::)? std::)? option:: )? Option $(::)?
1266        < $( $($(::)? std::)? num:: )? NonZero $(::)? < $t:ty > >
1267    } $($args:tt)*}                                                                   => { $crate::derive::opt_nz_typemagic!    { @$cmd {$t} $($args)* } };
1268    { @$cmd:ident {$( $($(::)? std::)? option:: )? Option $(::)?
1269        < $( $($(::)? std::)? num:: )? NonZeroU8 >
1270    } $($args:tt)*}                                                                    => { $crate::derive::opt_nz_typemagic!   { @$cmd {u8} $($args)* } };
1271    { @$cmd:ident {$( $($(::)? std::)? option:: )? Option $(::)?
1272        < $( $($(::)? std::)? num:: )? NonZeroU16 >
1273    } $($args:tt)*}                                                                    => { $crate::derive::opt_nz_typemagic!   { @$cmd {u16} $($args)* } };
1274    { @$cmd:ident {$( $($(::)? std::)? option:: )? Option $(::)?
1275        < $( $($(::)? std::)? num:: )? NonZeroU32 >
1276    } $($args:tt)*}                                                                    => { $crate::derive::opt_nz_typemagic!   { @$cmd {u32} $($args)* } };
1277    { @$cmd:ident {$( $($(::)? std::)? option:: )? Option $(::)?
1278        < $( $($(::)? std::)? num:: )? NonZeroU64 >
1279    } $($args:tt)*}                                                                    => { $crate::derive::opt_nz_typemagic!   { @$cmd {u64} $($args)* } };
1280    { @$cmd:ident {$( $($(::)? std::)? option:: )? Option $(::)?
1281        < $( $($(::)? std::)? num:: )? NonZeroU128 >
1282    } $($args:tt)*}                                                                    => { $crate::derive::opt_nz_typemagic!   { @$cmd {u128} $($args)* } };
1283    { @$cmd:ident {$( $($(::)? std::)? option:: )? Option $(::)?
1284        < $( $($(::)? std::)? string:: )? String >
1285    } $($args:tt)*}                                                                    => { $crate::derive::opt_str_typemagic!  { @$cmd $($args)* } };
1286    { @$cmd:ident {$( $($(::)? std::)? option:: )? Option $(::)?
1287        < $t:ty >
1288    } $($args:tt)*}                                                                    =>   {$crate::derive::opt_other_typemagic!{@$cmd {$t}  $($args)* } };
1289    { @$cmd:ident {$( $($(::)? std::)? num:: )? NonZero $(::)? < $t:ty >}  $($args:tt)*} => { $crate::derive::nonzero_typemagic!{ @$cmd {$t}   $($args)* } };
1290    { @$cmd:ident {$( $($(::)? std::)? num:: )? NonZeroU8}                 $($args:tt)*} => { $crate::derive::nonzero_typemagic!{ @$cmd {u8}   $($args)* } };
1291    { @$cmd:ident {$( $($(::)? std::)? num:: )? NonZeroU16}                $($args:tt)*} => { $crate::derive::nonzero_typemagic!{ @$cmd {u16}  $($args)*  } };
1292    { @$cmd:ident {$( $($(::)? std::)? num:: )? NonZeroU32}                $($args:tt)*} => { $crate::derive::nonzero_typemagic!{ @$cmd {u32}  $($args)*  } };
1293    { @$cmd:ident {$( $($(::)? std::)? num:: )? NonZeroU64}                $($args:tt)*} => { $crate::derive::nonzero_typemagic!{ @$cmd {u64}  $($args)*  } };
1294    { @$cmd:ident {$( $($(::)? std::)? num:: )? NonZeroU128}               $($args:tt)*} => { $crate::derive::nonzero_typemagic!{ @$cmd {u128} $($args)*  } };
1295    { @$cmd:ident {$( $($(::)? std::)? string:: )? String}                 $($args:tt)*} => { $crate::derive::string_typemagic! { @$cmd $($args)* } };
1296    { @$cmd:ident {$($t:tt)+}                                              $($args:tt)*} => { $crate::derive::no_typemagic!     { @$cmd {$($t)+} $($args)* } };
1297    // HEY YOU! DON'T ADD OR REMOVE TYPES WITHOUT READING THIS COMMENT!
1298    //
1299    // 1. You need to make sure that every type handled by this macro implements
1300    //    `ShouldBeCaughtAsASpecialCase`.
1301    // 2. Make sure to document the behavior in `doc_magic_types` above.
1302}
1303pub use normalize_and_invoke;
1304
1305/// Implement type magic for types that aren't at all special.
1306///
1307/// See [`normalize_and_invoke`] for details.
1308#[doc(hidden)]
1309#[macro_export]
1310macro_rules! no_typemagic {
1311    { @build_type {$t:ty} } => { $t };
1312    { @setter_arg_type {$t:ty}} => { $t };
1313    { @setter_cvt {$t:ty} {$e:expr} } => { $e };
1314    { @build_field {$t:ty} {$e:expr} {$fname:expr}} => { $e.clone() };
1315    { @check_type {$t:ty} } => {
1316        $crate::derive::exports::assert_not_impl!(
1317            [type_was_not_correctly_identified_as_a_TorConfig_special_case]
1318            $t: $crate::derive::ShouldBeCaughtAsSpecialCase
1319        );
1320    };
1321    { @setter_docs {$t:ty} } => { "" };
1322}
1323pub use no_typemagic;
1324
1325/// Implement type magic for `String`.
1326///
1327/// See [`normalize_and_invoke`] for details.
1328#[doc(hidden)]
1329#[macro_export]
1330macro_rules! string_typemagic {
1331    { @build_type } => { String };
1332    { @setter_arg_type } => { impl $crate::setter_traits::StringOrStr };
1333    { @setter_cvt {$e:expr} } => { $e.to_string() };
1334    { @build_field {$e:expr} {$fname:expr}} => { $e.clone() };
1335    { @check_type } => {};
1336    { @setter_docs } => {
1337        "\nFor convenience, this function accepts both `String` and `&str`.\n"
1338    };
1339}
1340pub use string_typemagic;
1341
1342/// Implement type magic for `NonZero*`.
1343///
1344/// See [`normalize_and_invoke`] for details.
1345#[doc(hidden)]
1346#[macro_export]
1347macro_rules! nonzero_typemagic {
1348    { @build_type {$t:ty} } => { $t };
1349    { @setter_arg_type {$t:ty} } => { impl $crate::setter_traits::PossiblyBoundsChecked<$t> };
1350    { @setter_cvt {$t:ty} {$e:expr} } => { $e.to_unchecked() };
1351    { @build_field {$t:ty} {$e:expr} {$fname:expr}} => {
1352        $e.try_into().map_err(|_| $crate::ConfigBuildError::Invalid {
1353                field: $fname.to_string(),
1354                problem: "value not allowed to be zero".to_string()
1355        })?
1356    };
1357    { @check_type {$t:ty} } => {};
1358    { @setter_docs {$t:ty} } => {
1359        concat!("\nFor convenience, this function accepts both `",
1360            stringify!($t), "` and `NonZero<", stringify!($t), ">`.\n" )
1361    };
1362}
1363pub use nonzero_typemagic;
1364
1365/// Implement type magic for `Option<NonZero*>`
1366///
1367/// See [`normalize_and_invoke`] for details.
1368#[doc(hidden)]
1369#[macro_export]
1370macro_rules! opt_nz_typemagic {
1371    { @build_type {$t:ty} } => { Option<$t> };
1372    { @setter_arg_type {$t:ty} } => { impl $crate::setter_traits::OptionPossiblyBoundsChecked<$t> };
1373    { @setter_cvt {$t:ty} {$e:expr} } => { $e.to_option_unchecked() };
1374    { @build_field {$t:ty} {$e:expr} {$fname:expr}} => {
1375        match $e {
1376            Some(v) => match v.try_into() {
1377                Ok(n) => Some(n),
1378                Err(_) => return Err( $crate::ConfigBuildError::Invalid {
1379                    field: $fname.to_string(),
1380                    problem: "value not allowed to be zero".to_string()
1381                })
1382            }
1383            None => None,
1384        }
1385    };
1386    { @check_type {$t:ty} } => {};
1387    { @setter_docs {$t:ty} } => {
1388        concat!("\nFor convenience, this function accepts `",
1389            stringify!($t), "`, `NonZero<", stringify!($t), ">`, `Option<", stringify!($t),
1390            ">`, and `Option<NonZero<", stringify!($t), ">`.\n")
1391    };
1392}
1393pub use opt_nz_typemagic;
1394
1395/// Implement type magic for `Option<String>`
1396///
1397/// See [`normalize_and_invoke`] for details.
1398#[doc(hidden)]
1399#[macro_export]
1400macro_rules! opt_str_typemagic {
1401    { @build_type } => { Option<String> };
1402    { @setter_arg_type  } => { impl $crate::setter_traits::OptionStringOrStr };
1403    { @setter_cvt {$e:expr} } => { $e.to_option_string() };
1404    { @build_field {$e:expr} {$fname:expr}} => { $e.clone() };
1405    { @check_type } => {};
1406    { @setter_docs } => {
1407        "\nFor convenience, this function accepts `String`, `&str`, \
1408                 `Option<String>`, and `Option<&str>`.\n"
1409    };
1410}
1411pub use opt_str_typemagic;
1412
1413/// Implement type magic for `Option<T>`
1414///
1415/// See [`normalize_and_invoke`] for details.
1416#[doc(hidden)]
1417#[macro_export]
1418macro_rules! opt_other_typemagic {
1419    { @build_type {$t:ty} } => { Option<$t> };
1420    { @setter_arg_type {$t:ty} } => { impl $crate::setter_traits::PossiblyOption<$t> };
1421    { @setter_cvt {$t:ty} {$e:expr} } => { $e.to_option() };
1422    { @build_field {$t:ty} {$e:expr} {$fname:expr}} => { $e.clone() };
1423    { @check_type {$t:ty} } => {
1424        $crate::derive::exports::assert_not_impl!(
1425            [type_was_not_correctly_identified_as_a_TorConfig_Option_special_case]
1426            $t: $crate::derive::ShouldBeCaughtAsSpecialCase
1427        );
1428    };
1429    { @setter_docs {$t:ty} } => {
1430        concat!("\nFor convenience, this function accepts both `", stringify!($t),
1431              "` and `Option<", stringify!($T), ">`\n.")
1432    };
1433}
1434pub use opt_other_typemagic;
1435
1436/// Helper: Expand to the type `T` that a field of type `{$t}`
1437/// should have in the builder struct's Option<T>.
1438#[doc(hidden)]
1439#[macro_export]
1440macro_rules! bld_magic_type {
1441    { $($t:tt)+ } => { $crate::derive::normalize_and_invoke!{ @build_type {$($t)+} } };
1442}
1443pub use bld_magic_type;
1444
1445/// Helper: Expand to the type `T` that a setter should take for a field of type `{$t}`
1446#[doc(hidden)]
1447#[macro_export]
1448macro_rules! bld_magic_setter_arg_type {
1449    { $($t:tt)+ } => { $crate::derive::normalize_and_invoke!{ @setter_arg_type {$($t)+} } };
1450}
1451pub use bld_magic_setter_arg_type;
1452
1453/// Helper: Expand to the code that should be used to convert `{e}` into the type
1454/// `bld_magic_type!{$t}`.
1455#[doc(hidden)]
1456#[macro_export]
1457macro_rules! bld_magic_setter_cvt {
1458    { {$e:expr} {$($t:tt)+}} => { $crate::derive::normalize_and_invoke!{ @setter_cvt {$($t)+} {$e} } };
1459}
1460pub use bld_magic_setter_cvt;
1461
1462/// Helper: Expand to the code that should be used to convert `{e}` from type
1463/// `bld_magic_type!{$t}` into $t.  Uses the field name `{fname} to generate errors.
1464#[doc(hidden)]
1465#[macro_export]
1466macro_rules! bld_magic_cvt {
1467    { {$e:expr} {$fname:expr} {$($t:tt)+}} => { $crate::derive::normalize_and_invoke!{ @build_field {$($t)+} {$e} {$fname} } };
1468}
1469pub use bld_magic_cvt;
1470
1471/// Helper: Expand to the code that will make sure that the type `{t}`
1472/// can be handled correctly by these macros.
1473/// The code will cause a compile-time error on failure.
1474#[doc(hidden)]
1475#[macro_export]
1476macro_rules! bld_magic_check_type {
1477    { {$($t:tt)+}} => { $crate::derive::normalize_and_invoke!{ @check_type {$($t)+} } };
1478}
1479pub use bld_magic_check_type;
1480
1481/// Helper: Expand to a documentation string describing any type-based magic for
1482/// the setter for this type.
1483#[doc(hidden)]
1484#[macro_export]
1485macro_rules! bld_magic_setter_docs {
1486    { {$($t:tt)+} } => { $crate::derive::normalize_and_invoke!{ @setter_docs {$($t)+} } };
1487}
1488pub use bld_magic_setter_docs;
1489
1490/// Helper for sealing traits below.
1491mod seal {
1492    /// Used to seal ShouldBeCaughtAsSpecialCase.
1493    pub trait SealSpecialCase {}
1494    /// Used to seal ShouldBeCaughtAsSerdeSpecialCase.
1495    pub trait SealSerdeSpecialCase {}
1496    /// Used to seal ShouldUseListBuilder.
1497    pub trait SealUseListBuilder {}
1498    /// Used to seal ShouldUseMapBuilder
1499    pub trait SealUseMapBuilder {}
1500    /// Used to seal ShouldNotBeUsed
1501    pub trait SealShouldNotBeUsed {}
1502}
1503
1504/// Implement each `trait` for every comma-separated type in `types`, with an empty body.
1505macro_rules! impl_many {
1506    { $($ty:ty),+ : $trait:ty } =>
1507    {
1508        $( impl $trait for $ty {} )+
1509    };
1510    { $($ty:ty),+ : $trait:ty , $($more:tt)+} =>
1511    {
1512        impl_many!{ $($ty),+ : $trait }
1513        impl_many!{ $($ty),+ : $($more)+ }
1514    };
1515}
1516
1517/// A trait implemented by all the types that `normalize_and_invoke` does anything magic for.
1518///
1519/// We use this trait to detect cases that normalize_and_invoke should have handled, but didn't--
1520/// probably because the type was an alias.
1521pub trait ShouldBeCaughtAsSpecialCase: seal::SealSpecialCase {}
1522impl_many! {
1523    std::num::NonZero<u8>, std::num::NonZero<u16>,
1524    std::num::NonZero<u32>, std::num::NonZero<u64>,
1525    std::num::NonZero<u128>, String
1526    : seal::SealSpecialCase, ShouldBeCaughtAsSpecialCase
1527}
1528impl<T> seal::SealSpecialCase for Option<T> {}
1529impl<T> ShouldBeCaughtAsSpecialCase for Option<T> {}
1530
1531/// A trait implemented by all the types that should receive automatic serde magic handling.
1532///
1533/// We use this trait to detect cases that the tor_config derive macro should have caught,
1534/// but didn't-- probably because the type was an alias.
1535pub trait ShouldBeCaughtAsSerdeSpecialCase: seal::SealSerdeSpecialCase {}
1536impl_many! {
1537    std::time::Duration
1538    : seal::SealSerdeSpecialCase, ShouldBeCaughtAsSerdeSpecialCase
1539}
1540
1541/// A trait implemented by the types for which we should recommend the use of a
1542/// list builder.
1543pub trait ShouldUseListBuilder: seal::SealUseListBuilder {
1544    /// The element type of this list.
1545    type Element;
1546}
1547impl<T> seal::SealUseListBuilder for Vec<T> {}
1548impl<T> seal::SealUseListBuilder for std::collections::HashSet<T> {}
1549impl<T> seal::SealUseListBuilder for std::collections::BTreeSet<T> {}
1550impl<T> ShouldUseListBuilder for Vec<T> {
1551    type Element = T;
1552}
1553impl<T> ShouldUseListBuilder for std::collections::HashSet<T> {
1554    type Element = T;
1555}
1556impl<T> ShouldUseListBuilder for std::collections::BTreeSet<T> {
1557    type Element = T;
1558}
1559
1560/// Helper to implement `list_builder`: find the element type for a list-like object.
1561#[doc(hidden)]
1562#[macro_export]
1563macro_rules! list_element {
1564    { $($($(::)? std::)? vec::)? Vec $(::)? < $t:ty > } => { $t };
1565    { $($($(::)? std::)? collections::)? HashSet $(::)? < $t:ty > } => { $t };
1566    { $($($(::)? std::)? collections::)? BTreeSet $(::)? < $t:ty > } => { $t };
1567    { $t:ty } => { compile_error!{"'list_builder' only works on Vec, HashSet, or BTreeSet."} }
1568}
1569pub use list_element;
1570
1571/// A trait implemented by the types for which we should recommend the use of a
1572/// map builder.
1573pub trait ShouldUseMapBuilder: seal::SealUseMapBuilder {
1574    /// The corresponding type to use inside this map builder
1575    type BuilderMap;
1576}
1577impl<T> seal::SealUseMapBuilder for std::collections::HashMap<String, T> where
1578    T: crate::load::Buildable
1579{
1580}
1581impl<T> seal::SealUseMapBuilder for std::collections::BTreeMap<String, T> where
1582    T: crate::load::Buildable
1583{
1584}
1585impl<T> ShouldUseMapBuilder for std::collections::HashMap<String, T>
1586where
1587    T: crate::load::Buildable,
1588{
1589    type BuilderMap = std::collections::HashMap<String, T::Builder>;
1590}
1591impl<T> ShouldUseMapBuilder for std::collections::BTreeMap<String, T>
1592where
1593    T: crate::load::Buildable,
1594{
1595    type BuilderMap = std::collections::BTreeMap<String, T::Builder>;
1596}
1597
1598/// A trait implemented by types that we shouldn't actually use as fields in a configuration.
1599pub trait ShouldNotBeUsed: seal::SealShouldNotBeUsed {}
1600impl_many! {
1601    // This is unsuitable, since there is no actual way to set a value to `none` in Toml.
1602    // Use Duration with a default instead.
1603    Option<std::time::Duration>,
1604    Option<Option<std::time::Duration>>
1605    : seal::SealShouldNotBeUsed, ShouldNotBeUsed
1606}
1607/// Declare that types shouldn't be used in a collection (because they would want magic
1608/// serde handling, but that isn't implemented).
1609macro_rules! should_not_be_used_in_collection {
1610    { $($t:ty),* $(,)?} => {
1611        $(
1612        impl_many!{
1613            Vec<$t>,
1614            std::collections::BTreeSet<$t>,
1615            std::collections::HashSet<$t>
1616            : seal::SealShouldNotBeUsed, ShouldNotBeUsed
1617        }
1618        impl<K> seal::SealShouldNotBeUsed for std::collections::HashMap<K,$t> {}
1619        impl<K> ShouldNotBeUsed for std::collections::HashMap<K,$t> {}
1620        impl<K> seal::SealShouldNotBeUsed for std::collections::BTreeMap<K,$t> {}
1621        impl<K> ShouldNotBeUsed for std::collections::BTreeMap<K,$t> {}
1622        )*
1623    }
1624}
1625should_not_be_used_in_collection! {
1626    std::time::Duration,
1627}
1628
1629#[deprecated = "use as tor_basic_utils::assert_not_impl instead"]
1630pub use tor_basic_utils::assert_not_impl;
1631
1632define_derive_deftly! {
1633    /// Define a builder type for a given type, with settings appropriate to participate in the Arti
1634    /// build system.
1635    ///
1636    /// See [module documentation](crate::derive) for more information and usage instructions.
1637    //
1638    // `meta_quoted strip` means that
1639    //     #[deftly(tor_config(default = "something"))]
1640    // means to try to parse "something" as Rust code.  That means the syntax for specifying
1641    // a string literals for a default value is clumsy, but that's not a useful thing to do
1642    // since config fields don't have fields of type `&str`.
1643    //
1644    // All the other `as expr` want functions or something, so `strip` is right.
1645    //
1646    // `cfg_desc` is `as str`, which doesn't try to strip quotes and reparse.
1647    export TorConfig beta_deftly, for struct, meta_quoted strip:
1648
1649    #[allow(unused_imports)]
1650    use $crate::derive::exports as $<__tor_config_exports__ $tname>;
1651
1652    // -------------------
1653    // Common definitions and aliases.
1654
1655    // Location of exports for this macro.
1656    ${define E {$crate::derive::exports}}
1657
1658    // Location of exports for this macro, as a string.
1659    //
1660    // TODO $crate: I would prefer to use ${concat $crate "::derive::exports"} instead,
1661    // but that won't work, since $crate gets expanded at the wrong time.
1662    // See
1663    // https://gitlab.torproject.org/Diziet/rust-derive-deftly/-/issues/132#note_3288325
1664    // for discussion of the workaround used here.
1665    ${define EX ${concat "__tor_config_exports__" $tname}}
1666
1667    // Current field name as string.
1668    ${define FNAME { ${concat $fname} }}
1669
1670    // Name of the build method.
1671    ${define BLD_NAME {
1672        ${tmeta(tor_config(build_fn(name))) as ident, default build}
1673    } }
1674
1675    // -------------------
1676    // Definitions and aliases for defining the builder struct.
1677
1678    // True if the field type appears to be `std::time::Duration`
1679    //
1680    // (This can't be done with the regular "magic" macro system,
1681    // since it needs to be used in expansions that produce a field attribute.
1682    // macro_rules! macros can't appear in a field-attribute position.
1683    // There _are_ workarounds here, which I'll consider while
1684    // reafactoring the magic system.)
1685    ${defcond F_IS_DURATION
1686        any(approx_equal({$ftype}, {Duration}),
1687            approx_equal({$ftype}, {time::Duration}),
1688            approx_equal({$ftype}, {std::time::Duration}),
1689            approx_equal({$ftype}, {::std::time::Duration}))
1690    }
1691
1692    // True if the field type should receive magic handling with serde.
1693    ${defcond F_SERDE_MAGIC any(F_IS_DURATION)}
1694
1695    // Condition: True unless Serialize and Deserialize have both been disabled.
1696    ${defcond SERDE
1697        not(all(tmeta(tor_config(no_serialize_trait)),
1698                tmeta(tor_config(no_deserialize_trait))))
1699    }
1700
1701    // Expands to any attributes that should be applied to the current builder field
1702    // based on magic type behavior.
1703    ${define BLD_MAGIC_ATTRIBUTES
1704        ${if fmeta(tor_config(no_magic)) {
1705        } else if SERDE {
1706            ${select1
1707            F_IS_DURATION {
1708                ${if SERDE {
1709                    #[serde(with = ${concat $EX "::humantime_serde::option"})]
1710                }}
1711            }
1712            // HEY YOU! DON'T ADD ANY MORE MAGIC SERDE TYPES HERE WITHOUT READING THIS!
1713            // 1. You need to add the condition for your type to `F_SERDE_MAGIC`,
1714            //    and you need to make sure that your type implements
1715            //    `ShouldBeCaughtAsSerdeSpecialCase`.
1716            // 2. You need to document the behavior in `doc_magic_types`.
1717            else {
1718                ${if F_SERDE_MAGIC {
1719                    ${error "Type should receive magic handling with serde, but we failed to apply any."}
1720                }}
1721                // No magic needed.
1722            }}
1723        }}
1724    }
1725
1726    // For each list_builder field: the names of the list builder
1727    // type to define.
1728    ${define F_LST_BLD_TYPE {  $<
1729        ${fmeta(tor_config(list(listtype))) as ty,
1730            default ${paste $tname ${upper_camel_case $fname} List}
1731     } Builder>} }
1732
1733    // For each map_builder field: the names of the map builder
1734    // type to define.
1735    ${define F_MAP_TYPE { ${paste // See derive_deftly#138 for this $paste.
1736        ${fmeta(tor_config(map(maptype))) as ty,
1737            default ${paste $tname ${upper_camel_case $fname} Map}}
1738    }}}
1739    ${define F_MAP_BLD_TYPE { $< $F_MAP_TYPE Builder > }}
1740
1741    // Expands to $ftype of the current builder field, as modified by type magic.
1742    // (Most everybody should use $BLD_FTYPE instead.)
1743    ${define BLD_MAGIC_FTYPE {
1744        ${if fmeta(tor_config(no_magic)) {
1745            $ftype
1746        } else {
1747            $E::bld_magic_type!($ftype)
1748        }}
1749    }}
1750    // Expands to the type of the field within the builder.
1751    ${define BLD_FTYPE {
1752        ${if fmeta(tor_config(field(ty))) {
1753            ${fmeta(tor_config(field(ty))) as ty}
1754        } else if fmeta(tor_config(sub_builder)) {
1755            $< $ftype Builder >
1756        } else if fmeta(tor_config(list)) {
1757            $F_LST_BLD_TYPE
1758        } else if fmeta(tor_config(map)) {
1759            $F_MAP_BLD_TYPE
1760        } else {
1761            $E::Option<$BLD_MAGIC_FTYPE>
1762        }}
1763    }}
1764
1765    // Expands to the error type for this builder.
1766    ${define ERR
1767       ${tmeta(tor_config(build_fn(error))) as ty, default {$E::ConfigBuildError}}}
1768
1769    // If the current field is conditionally present, expands to the `cfg`
1770    // attribute we should apply to it.
1771    ${define IF_CFG {
1772        // TODO: Infelicity: It would be nice if this didn't have to take "cfg" as a string.
1773        // See https://gitlab.torproject.org/Diziet/rust-derive-deftly/-/issues/56
1774        ${if fmeta(tor_config(cfg)) {
1775            #[cfg( ${fmeta(tor_config(cfg)) as token_stream} )]
1776        }}
1777    }}
1778
1779    // Visibility for the builder type.
1780    ${define BLD_TVIS
1781        ${tmeta(tor_config(vis)) as vis, default $tvis}
1782    }
1783
1784    // Visibility for the current field in the builder type.
1785    ${define BLD_FVIS
1786        ${fmeta(tor_config(field(vis))) as vis, default {} }
1787    }
1788
1789    // True if we want to derive Flattenable for the builder type
1790    ${defcond DD_FLATTENABLE_ON_BUILDER
1791        all(not(tmeta(tor_config(no_deserialize_trait))),
1792            not(tmeta(tor_config(no_flattenable_trait)))
1793        )}
1794
1795    // Expands to the visibility for the current setter/accessor,
1796    // and for any types that we generate for it to expose.
1797    ${define SETTER_VIS {
1798        ${fmeta(tor_config(setter(vis))) as vis, default $BLD_TVIS}
1799    }}
1800
1801    // -------------------
1802    // Invoke checks for our type-handling macros.
1803
1804    $(
1805        ${if fmeta(tor_config(no_magic)) {
1806            // If we're disabling the magic, this is fine.
1807        } else {
1808            // Make sure that, for every other, it gets matched by the right case of
1809            // normalize_and_invoke.
1810            //
1811            // (We do this because our type checking in normalize_and_invoke is imperfect,
1812            // and can't detect aliases.)
1813            $E::bld_magic_check_type!({$ftype});
1814        }}
1815        ${if all(not(F_SERDE_MAGIC), not(fmeta(tor_config(no_magic))) ) {
1816            // If we don't get special handling from serde, make sure that the type doesn't actually
1817            // need it.
1818            //
1819            // (We do this because our type checking in F_IS_DURATION is imperfect and can't
1820            // detect)
1821            $E::assert_not_impl!(
1822                [type_was_not_correctly_identified_as_a_TorConfig_serde_special_case]
1823                $ftype: $E::ShouldBeCaughtAsSerdeSpecialCase
1824            );
1825        }}
1826    )
1827
1828    // -------------------
1829    // Check for types that don't make sense in a configuration.
1830    $(
1831        ${when not(fmeta(tor_config(no_magic)))}
1832
1833        $E::assert_not_impl!(
1834            [field_type_not_suitable_for_configuration]
1835            $ftype: $E::ShouldNotBeUsed
1836        );
1837    )
1838
1839    // -------------------
1840    // Check for missing invocations of sub_builder, list, or map.
1841    $(
1842        ${when not(any(
1843            fmeta(tor_config(sub_builder)),
1844            fmeta(tor_config(no_sub_builder)),
1845            fmeta(tor_config(no_magic)),
1846            fmeta(tor_config(build)),
1847            fmeta(tor_config(try_build)),
1848        ))}
1849        $E::assert_not_impl!(
1850            [missing_sub_builder_declaration_for_Buildable_field]
1851            $ftype: $E::BuildableTrait
1852        );
1853    )
1854
1855    $(
1856        ${when not(any(
1857            fmeta(tor_config(no_sub_builder)),
1858            fmeta(tor_config(no_magic)),
1859            fmeta(tor_config(list)),
1860        ))}
1861        $E::assert_not_impl!(
1862            [field_should_use_list_builder_or_opt_out]
1863            $ftype: $E::ShouldUseListBuilder
1864        );
1865    )
1866
1867    $(
1868        ${when not(any(
1869            fmeta(tor_config(no_sub_builder)),
1870            fmeta(tor_config(no_magic)),
1871            fmeta(tor_config(map)),
1872        ))}
1873        $E::assert_not_impl!(
1874            [field_should_use_map_builder_or_opt_out]
1875            $ftype: $E::ShouldUseMapBuilder
1876        );
1877    )
1878
1879    // -------------------
1880    // Define the builder type.
1881
1882    #[doc = ${concat "A builder to create an instance of [`" $tname "`].\n"}]
1883    #[derive($E::Default, $E::Clone, $E::Debug, $E::Deftly)]
1884    ${if not(tmeta(tor_config(no_deserialize_trait))) {
1885        #[derive($E::Deserialize)]
1886    }}
1887    ${if not(tmeta(tor_config(no_serialize_trait))) {
1888        #[derive($E::Serialize)]
1889    }}
1890    ${if DD_FLATTENABLE_ON_BUILDER {
1891        #[derive_deftly($E::Flattenable)]
1892    }}
1893    ${tmeta(tor_config(attr)) as attrs}
1894    #[allow(dead_code)]
1895    $BLD_TVIS struct $<$tname Builder><$tdefgens>
1896    where $twheres
1897    {
1898        $(
1899            ${when not(fmeta(tor_config(skip)))}
1900
1901            ${fmeta(tor_config(attr)) as attrs}
1902            ${if SERDE {
1903                #[serde(default)]
1904            }}
1905            // TODO tor_config(serde) deprecated, abolish (and remove from docs) around 2027-04
1906            ${ if fmeta(tor_config(serde)) {
1907                #[ serde( ${fmeta(tor_config(serde)) as token_stream} )]
1908            }}
1909            #[doc = ${concat "In-progress value for " $fname ".\n\n"
1910                             "See [`" $tname "." $fname "`]("$tname "#structfield." $fname ")"}]
1911            $BLD_MAGIC_ATTRIBUTES
1912            $IF_CFG
1913            $BLD_FVIS ${fdefine $fname} $BLD_FTYPE,
1914
1915            ${if all(SERDE, fmeta(tor_config(cfg))) {
1916                /// Placeholder to catch attempts to use this field when
1917                /// disabled by configuration.
1918                ///
1919                /// (This uses `serde_value` to make sure that Deserialize+Serialize is not
1920                /// needlessly lossy.)
1921                #[cfg(not(${fmeta(tor_config(cfg)) as token_stream} ))]
1922                #[serde(default)]
1923                ${fdefine $fname} $E::Option<$E::serde_value::Value>,
1924            }}
1925        )
1926    }
1927
1928    // -------------------
1929    // Define any list-builder or map-builder types.
1930
1931    ${define BUILD_LIST_ELEMENT {
1932        ${select1
1933        fmeta(tor_config(list(element(build)))) {
1934            |v| v.${fmeta(tor_config(list(element(build)))) as ident, default build}()
1935        }
1936        fmeta(tor_config(list(element(clone)))) {
1937            |v| Ok(v.clone())
1938        }
1939        else {
1940            ${error "With list, must specify list(element(clone)) or list(element(build))"}
1941        }}
1942    }}
1943    ${define APPLY_DEFAULTS_LIST_ELEMENT {
1944        ${select1
1945        fmeta(tor_config(list(element(build)))) {
1946            |v| $E::ConfigBuilder::apply_defaults(v)
1947        }
1948        fmeta(tor_config(list(element(clone)))) {
1949            |_v| Ok::<_ , $E::ConfigBuildError>(())
1950        }
1951        else {
1952            ${error "With list, must specify list(element(clone)) or list(element(build))"}
1953        }}
1954    }}
1955    ${define BLD_LIST_ELT_TYPE {
1956        ${select1
1957        fmeta(tor_config(list(element(build)))) {
1958            // TODO: Find a way to get the argument types for the setters be
1959            // nicer.
1960            //
1961            // It would be cool if we could paste "Builder" on to the end of the
1962            // output of $E::list_element, but that doesn't work.
1963            <<$ftype as $E::ShouldUseListBuilder>::Element as $E::BuildableTrait>::Builder
1964        }
1965        fmeta(tor_config(list(element(clone)))) {
1966            // We could use ShouldUseListBuilder::Element here, but the declared
1967            // argument types for the setters would be a bit nasty.
1968            $E::list_element!{ $ftype }
1969        }
1970        else {
1971            ${error "With list, must specify list(element(clone)) or list(element(build))"}
1972        }}
1973    }}
1974
1975    $(
1976        ${when fmeta(tor_config(list))}
1977
1978        $E::define_list_builder_helper! {
1979            #[doc = ${concat "Builder for the `" $ftype "` type.\n\n"}]
1980            $SETTER_VIS struct $F_LST_BLD_TYPE {
1981                $BLD_FVIS $fname: [
1982                    $BLD_LIST_ELT_TYPE
1983                ],
1984            }
1985            built: $ftype = $fname;
1986            default = ${fmeta(tor_config(default)) as expr};
1987            item_build: $BUILD_LIST_ELEMENT;
1988            item_apply_defaults: $APPLY_DEFAULTS_LIST_ELEMENT;
1989        }
1990    )
1991
1992    $(
1993        ${when fmeta(tor_config(map))}
1994
1995        $E::define_map_builder! {
1996            #[doc = ${concat "Builder for the `" $F_MAP_TYPE "` type.\n\n"}]
1997            $SETTER_VIS struct $F_MAP_BLD_TYPE =>
1998            $BLD_FVIS type $F_MAP_TYPE = {
1999                map: $ftype,
2000                builder_map: <$ftype as $E::ShouldUseMapBuilder>::BuilderMap,
2001            }
2002            defaults: ${fmeta(tor_config(default)) as expr};
2003        }
2004    )
2005
2006    // -------------------
2007    // Definitions to implement setter/accessor methods.
2008
2009    // Expands to the name of the setter/accessor for the current field.
2010    ${define SETTER_NAME { ${fmeta(tor_config(setter(name))) as ident, default $fname} }}
2011
2012    // Expands the declared type that the setter should take as its argument.
2013    ${define SETTER_INPUT_TYPE {
2014        ${select1
2015            fmeta(tor_config(setter(into))) {
2016                impl $E::Into<$ftype>
2017            }
2018            fmeta(tor_config(setter(try_into))) {
2019                SetterArg
2020            }
2021            fmeta(tor_config(setter(strip_option))) {
2022                $E::strip_option!{$ftype}
2023            }
2024            else {
2025                ${if fmeta(tor_config(no_magic)) {
2026                    $ftype
2027                } else {
2028                    $E::bld_magic_setter_arg_type!{$ftype}
2029                }
2030            }}
2031        }}}
2032
2033    // Expands to the generics (if any) that the setter should take.
2034    ${define SETTER_GENS {
2035        ${if fmeta(tor_config(setter(try_into))) {
2036            <SetterArg : $E::TryInto<$ftype>>
2037        } else {
2038        }}
2039    }}
2040
2041    // Expands to the expression that the setter should return.
2042    ${define SETTER_RETURN {
2043        ${if fmeta(tor_config(setter(try_into))) {
2044            Ok(self)
2045        } else {
2046            self
2047        }}
2048    }}
2049
2050    // Expands to the declared return type of the setter.
2051    ${define SETTER_RETURN_TYPE {
2052        ${if fmeta(tor_config(setter(try_into))) {
2053            $E::Result<&mut Self, SetterArg::Error>
2054        } else {
2055            &mut Self
2056        }}
2057    }}
2058
2059    // Expands to a string that we should add to the documentation
2060    // to explain the default value of the current field.
2061    ${define DFLT_DOC {
2062        ${select1
2063            fmeta(tor_config(sub_builder)) { "" }
2064            // TODO: perhaps we should document _something_ about build and try_build,
2065            // even though we can't document any default.
2066            fmeta(tor_config(build)) { "" }
2067            fmeta(tor_config(try_build)) { "" }
2068            fmeta(tor_config(default)) {
2069                ${concat "If no value is provided for `" $fname "`, "
2070                  "[`build`](Self::build) will use `"
2071                  ${fmeta(default) as str, default "Default::default()"}
2072                  "`."
2073            }}
2074            fmeta(tor_config(no_default)) {
2075                ${concat "If no value is provided for `" $fname "`, "
2076                  "[`build`](Self::build) will fail with an error."}
2077            }
2078            else {
2079                ${error "Every field must have default, no_default, try_build, build, or sub_builder."}
2080            }
2081        }
2082    }}
2083
2084    // Expands to a definition of the setter function for the current field.
2085    ${define SET_FN {
2086        #[doc = ${concat "Provide a value for `" $fname "`.\n\n"}]
2087        #[doc = $DFLT_DOC]
2088        ${if not(fmeta(tor_config(no_magic))) {
2089            #[doc = $E::bld_magic_setter_docs!{ { $ftype } } ]
2090        }}
2091        #[doc = ${concat "\n\n## " $fname "\n\n" }]
2092        ${fattrs doc}
2093        $IF_CFG
2094        $SETTER_VIS fn $SETTER_NAME $SETTER_GENS (&mut self, val: $SETTER_INPUT_TYPE) -> $SETTER_RETURN_TYPE {
2095            ${select1
2096                fmeta(tor_config(setter(into))) {
2097                    self.$fname = Some(val.into());
2098                }
2099                fmeta(tor_config(setter(try_into))) {
2100                    self.$fname = Some(val.try_into()?);
2101                }
2102                fmeta(tor_config(setter(strip_option))) {
2103                    self.$fname = Some(Some(val));
2104                }
2105                else {
2106                    ${if fmeta(tor_config(no_magic)) {
2107                        self.$fname = Some(val);
2108                    } else {
2109                        self.$fname = Some($E::bld_magic_setter_cvt!({val} {$ftype}));
2110                    }}
2111                }
2112            }
2113            $SETTER_RETURN
2114        }
2115    }}
2116
2117    ${define F_SUB_BUILDER_TYPE
2118        ${if fmeta(tor_config(map)) {
2119            $F_MAP_BLD_TYPE
2120        } else {
2121            $<$ftype Builder>
2122        }}
2123    }
2124
2125    // Expands to a declaration for the sub-builder accessor function for the current field.
2126    ${define ACCESS_SUBBUILDER_FN {
2127
2128        #[doc = ${concat "Return a mutable reference to the inner builder for `" $fname "`.\n\n"
2129                  "## " $fname "\n\n"
2130                }]
2131        ${fattrs doc}
2132        $IF_CFG
2133        $SETTER_VIS fn $fname(&mut self) -> &mut $F_SUB_BUILDER_TYPE {
2134            &mut self.$fname
2135        }
2136    }}
2137
2138    // -------------------
2139    // Define the setter/accessors methods.
2140
2141    #[allow(dead_code)]
2142    ${impl for $<$ttype Builder>} {
2143        $(
2144            ${if any(fmeta(tor_config(setter(skip))),
2145                     fmeta(tor_config(skip)),
2146                     fmeta(tor_config(list))) {
2147                // generate nothing.
2148            } else if any(fmeta(tor_config(sub_builder)),
2149                          fmeta(tor_config(map))) {
2150                $ACCESS_SUBBUILDER_FN
2151            } else {
2152                $SET_FN
2153            }}
2154        )
2155    }
2156
2157    $(
2158        ${when fmeta(tor_config(list))}
2159
2160        $E::define_list_builder_accessors!{
2161            struct $<$tname Builder> {
2162                $SETTER_VIS $fname : [
2163                    $BLD_LIST_ELT_TYPE
2164                 ],
2165            }
2166        }
2167    )
2168
2169    // -------------------
2170    // Definitions and helpers for the build method.
2171
2172    // Expands to the name of the function to use to build the sub-builder for the current field.
2173    ${define SUB_BUILDER_BUILD_FN {
2174        ${fmeta(tor_config(sub_builder(build_fn))) as path, default build}
2175    }}
2176
2177    // Expands to an expression of type Option<$ftype> for a field named "value",
2178    // taking type-based magic into account.
2179    ${define BLD_MAGIC_CVT {
2180        ${if fmeta(tor_config(no_magic)) {
2181            value.clone()
2182        } else {
2183            $E::bld_magic_cvt!({value} {${concat $fname}} {$ftype})
2184        }}
2185    }}
2186
2187    // Expands to the closure we run on a missing field to get the error type.
2188    ${define BLD_MISSING_FIELD {
2189        ${tmeta(tor_config(missing_field)) as expr, default {
2190            |name_of_missing_field: &str| $ERR::MissingField { field: name_of_missing_field.into() }
2191        }}
2192    }}
2193
2194    // Expands to an expression for building the current field,
2195    // and returning an appropriate error if there was a problem.
2196    ${define BUILD_FIELD {
2197         ${select1
2198            any(fmeta(tor_config(sub_builder)),
2199                fmeta(tor_config(list)),
2200                fmeta(tor_config(map))) {
2201                self.$fname.$SUB_BUILDER_BUILD_FN().map_err(|e| e.within($FNAME))?
2202            }
2203            all(fmeta(tor_config(default)), not(any(fmeta(tor_config(list)),
2204                                                    fmeta(tor_config(map))))) {
2205                {
2206                    let value = self.$fname.clone().unwrap_or_else(
2207                        || ${fmeta(tor_config(default)) as expr, default {Default::default()}});
2208                    $BLD_MAGIC_CVT
2209                }
2210            }
2211            fmeta(tor_config(build)) {
2212                (${fmeta(tor_config(build)) as expr})(self)
2213            }
2214            fmeta(tor_config(try_build)) {
2215                (${fmeta(tor_config(try_build)) as expr})(self)?
2216            }
2217            fmeta(tor_config(no_default)) {
2218                {
2219                    let value = self.$fname.clone().ok_or_else(
2220                        || { ($BLD_MISSING_FIELD)(stringify!($fname)) })?;
2221                    $BLD_MAGIC_CVT
2222                }
2223            }
2224            else {
2225                ${error "Every field must have default, no_default, try_build, build, or sub_builder."}
2226            }
2227        }
2228    }}
2229
2230    // Expands to the visibility of the build method.
2231    ${define BLD_FN_VIS {
2232        ${tmeta(tor_config(build_fn(vis))) as vis, default $BLD_TVIS}
2233    }}
2234
2235    // -------------------
2236    // Define the build method and the new() method.
2237
2238    #[allow(dead_code)]
2239    ${impl for $<$ttype Builder>} {
2240        /// Return a new builder object.
2241        $BLD_TVIS fn new() -> Self {
2242            Self::default()
2243        }
2244
2245        #[doc = ${concat
2246            "Try to construct a new [`" $tname "`] from the fields set in this builder.\n\n"
2247            "Return an error if any required field is missing, or is set to something invalid.\n"
2248        }]
2249        $BLD_FN_VIS fn $BLD_NAME(&self) -> $E::Result<$ttype, $ERR> {
2250            // Call pre_build as appropriate.
2251            ${if tmeta(tor_config(pre_build)) {
2252                let () = ${tmeta(tor_config(pre_build)) as path}(self)?;
2253            }}
2254
2255            // Warn if any configured-out option was provided.
2256            $(
2257                ${if fmeta(tor_config(cfg)) {
2258                    #[cfg(not( ${fmeta(tor_config(cfg)) as token_stream} ))]
2259                    if self.$fname.is_some() {
2260                        ${if fmeta(tor_config(cfg_reject)) {
2261                            return Err($E::ConfigBuildError::NoCompileTimeSupport {
2262                                field: stringify!($fname).to_string(),
2263                                problem: ${concat "The program was not built "
2264                                    ${fmeta(tor_config(cfg_desc)) as str}
2265                                }.to_string()
2266                            });
2267                        } else {
2268                            $E::tracing::warn!(
2269                                ${concat "Ignored configuration for '" $fname
2270                                "'. This option has no effect unless the program is built "
2271                                ${fmeta(tor_config(cfg_desc)) as str} "'"}
2272                            )
2273                        }}
2274                    }
2275                }}
2276            )
2277
2278            // TODO: It would be good to call apply_defaults here,
2279            // but if we make  change, we will hit extra redundancy:
2280            // If build() calls apply_defaults(),
2281            // our own apply_defaults will recurse to our sub-builders,
2282            // and then the build() functions of our sub-builders will
2283            // also invoke their apply_defaults methods.
2284
2285            // Construct the configuration struct.
2286            let result = $tname {
2287                $(
2288                    $IF_CFG
2289                    $fname: $BUILD_FIELD ,
2290
2291                    ${if fmeta(tor_config(cfg)) {
2292                        #[cfg(not( ${fmeta(tor_config(cfg)) as token_stream} ))]
2293                        $fname: $E::Default::default(),
2294                    }}
2295                )
2296            };
2297
2298            // Call the post_build function to transform the result.
2299            ${if tmeta(tor_config(post_build)) {
2300                let result = ${tmeta(tor_config(post_build)) as path}(result)?;
2301            }}
2302
2303            Ok(result)
2304        }
2305    }
2306
2307    // -------------------
2308    // Implement ConfigBuilder
2309
2310    ${impl $E::ConfigBuilder for $<$ttype Builder>} {
2311        fn apply_defaults(&mut self) -> Result<(), $E::ConfigBuildError> {
2312            #[allow(unused_imports)]
2313            use $E::ConfigBuilder as _;
2314            $(
2315                ${IF_CFG}
2316                ${if fmeta(tor_config(apply_field_default)) {
2317                    ${if any(fmeta(tor_config(default)),
2318                             fmeta(tor_config(no_default))) {
2319                        ${error "Cannot use apply_field_default with default or no_default."}
2320                    }}
2321                    {
2322                        let closure = ${fmeta(tor_config(apply_field_default)) as expr};
2323                        (closure)(self)?;
2324                    }
2325                } else if any(fmeta(tor_config(sub_builder)),
2326                        fmeta(tor_config(list)),
2327                        fmeta(tor_config(map))) {
2328                    self.$fname.apply_defaults()?;
2329                } else if fmeta(tor_config(default)) {
2330                    let _ = self.$fname.get_or_insert_with(
2331                        || ${fmeta(tor_config(default)) as expr, default {Default::default()}});
2332                }}
2333            )
2334            Ok(())
2335        }
2336    }
2337
2338    // -------------------
2339    // Add a builder() method to the configuration type.
2340    //
2341    // NOTE: This and some other code below is redundant with impl_standard_builder!().
2342    // I'm not using that trait here because complying with its input format is rather
2343    // baroque, and it's easier just to do it ourselves.
2344
2345    $impl {
2346        #[doc = ${concat "Return a new [`" $tname " Builder`] to construct an instance of this type."}]
2347        #[allow(dead_code)]
2348        $tvis fn builder() -> $<$ttype Builder> {
2349            $<$ttype Builder>::default()
2350        }
2351    }
2352
2353    // -------------------
2354    // Implement `$crate::load::Builder` for the Builder type.
2355
2356    ${if not(tmeta(tor_config(no_builder_trait))) {
2357        ${impl $E::BuilderTrait for $<$ttype Builder>} {
2358            type Built = $ttype;
2359            // We're writing it this way in case Builder::build() returns
2360            // a different Error type.
2361            #[allow(clippy::needless_question_mark)]
2362            fn build(&self) -> $E::Result<$ttype, $E::ConfigBuildError> {
2363                Ok($<$ttype Builder>::$BLD_NAME(self)?)
2364            }
2365        }
2366    }}
2367
2368    // -------------------
2369    // Implement $crate::extend_builder::ExtendBuiler on the builder type.
2370    // (We can't use derive_deftly_template_ExtendBuilder, since that macro was
2371    // written to apply to the configuration type and modify its builder. (!))
2372
2373    ${if not(tmeta(tor_config(no_extendbuilder_trait))) {
2374        ${impl $E::ExtendBuilder for $<$ttype Builder>} {
2375            #[allow(unused_variables)]
2376            fn extend_from(&mut self, other: Self, strategy: $E::ExtendStrategy) {
2377                ${for fields {
2378                    ${when not(fmeta(tor_config(skip)))}
2379
2380                    ${if fmeta(tor_config(cfg)) {
2381                        // For conditionally present features, it doesn't matter what we put
2382                        // in the field, so long as we make it set whenever _either_ config is set.
2383                        #[cfg(not( ${fmeta(tor_config(cfg)) as token_stream} ))]
2384                        if other.$fname.is_some() {
2385                            self.$fname = other.$fname;
2386                        }
2387
2388                        #[cfg( ${fmeta(tor_config(cfg)) as token_stream} )]
2389                    }}
2390                    {
2391                        ${if fmeta(tor_config(extend_with)) {
2392                            ${fmeta(tor_config(extend_with)) as expr}(&mut self.$fname, other.$fname, strategy);
2393                        } else if fmeta(tor_config(extend_with_replace)) {
2394                            if let Some(other_val) = other.$fname {
2395                                self.$fname = Some(other_val);
2396                            }
2397                        } else if any(fmeta(tor_config(sub_builder)),
2398                                fmeta(tor_config(list)),
2399                                fmeta(tor_config(map))) {
2400                            $E::ExtendBuilder::extend_from(&mut self.$fname, other.$fname, strategy);
2401                        } else {
2402                            if let Some(other_val) = other.$fname {
2403                                self.$fname = Some(other_val);
2404                            }
2405                        }}
2406                    }
2407                }}
2408            }
2409        }
2410    }}
2411
2412    // -------------------
2413    // Implement `$crate::load::Buildable` for the configuration type.
2414    ${if not(tmeta(tor_config(no_buildable_trait))) {
2415        ${impl $E::BuildableTrait} {
2416            type Builder = $<$ttype Builder>;
2417
2418            fn builder() -> $<$ttype Builder> {
2419                $<$ttype Builder>::default()
2420            }
2421        }
2422    }}
2423
2424
2425    // -------------------
2426    // Implement `Default` for the configuration type, in terms of the Builder.
2427    // (Unless the no_default_trait attribute was present.)
2428    ${if not(tmeta(tor_config(no_default_trait))) {
2429        ${impl $E::Default} {
2430            fn default() -> Self {
2431                // It's okay to use unwrap; one of the test cases verifies it.
2432                $<$ttype Builder>::default().$BLD_NAME().unwrap()
2433            }
2434        }
2435    }}
2436
2437    // ------------------
2438    // Test module for the builder.
2439    ${if not(any(
2440        tmeta(tor_config(no_default_trait)),
2441        tmeta(tor_config(no_deserialize_trait)),
2442        tmeta(tor_config(no_test_default))))
2443        {
2444        #[cfg(test)]
2445        mod $<test_ ${snake_case $tname} _builder> {
2446            #[test]
2447            // TODO: doesn't work on generics. Do we care?  If so, how should we fix?
2448            fn test_impl_default() {
2449                let def = super::$ttype::default();
2450                let empty_config = $E::figment::Figment::new();
2451                let builder: super::$<$ttype Builder> = empty_config.extract().unwrap();
2452                let from_empty = builder.$BLD_NAME().unwrap();
2453                assert_eq!(def, from_empty);
2454            }
2455        }
2456    }}
2457}
2458pub use derive_deftly_template_TorConfig;
2459
2460#[cfg(test)]
2461mod test {
2462    // @@ begin test lint list maintained by maint/add_warning @@
2463    #![allow(clippy::bool_assert_comparison)]
2464    #![allow(clippy::clone_on_copy)]
2465    #![allow(clippy::dbg_macro)]
2466    #![allow(clippy::mixed_attributes_style)]
2467    #![allow(clippy::print_stderr)]
2468    #![allow(clippy::print_stdout)]
2469    #![allow(clippy::single_char_pattern)]
2470    #![allow(clippy::unwrap_used)]
2471    #![allow(clippy::unchecked_time_subtraction)]
2472    #![allow(clippy::useless_vec)]
2473    #![allow(clippy::needless_pass_by_value)]
2474    #![allow(clippy::string_slice)] // See arti#2571
2475    //! <!-- @@ end test lint list maintained by maint/add_warning @@ -->
2476
2477    use crate::ConfigBuildError;
2478    use assert_matches::assert_matches;
2479    use tracing_test::traced_test;
2480
2481    /// Separate module to put config structs and their builders in, so that they aren't
2482    /// able to pick up anything we don't deliberately import.
2483    mod t {
2484        use std::{
2485            collections::{BTreeSet, HashMap},
2486            num::{NonZero, NonZeroU8},
2487            time::Duration,
2488        };
2489
2490        // use crate::derive::prelude::*;
2491        use derive_deftly::Deftly;
2492
2493        #[derive(Deftly, Clone, Debug, PartialEq)]
2494        #[derive_deftly(TorConfig)]
2495        pub(super) struct Simple {
2496            #[deftly(tor_config(default))]
2497            pub(super) xyz: u32,
2498
2499            #[deftly(tor_config(default = 3))]
2500            pub(super) abc: u16,
2501
2502            #[deftly(tor_config(build = |_self| 6 * 7))]
2503            pub(super) forty_two: u16,
2504
2505            #[deftly(tor_config(
2506                try_build = { |_self| Ok::<_,crate::ConfigBuildError>(6 * 7 + 1) }
2507            ))]
2508            pub(super) forty_three: u16,
2509        }
2510
2511        #[derive(Deftly, Clone, Debug, PartialEq)]
2512        #[derive_deftly(TorConfig)]
2513        #[deftly(tor_config(no_default_trait))]
2514        pub(super) struct FieldNoDefault {
2515            #[deftly(tor_config(default))]
2516            pub(super) has_default: u32,
2517            #[deftly(tor_config(no_default))]
2518            pub(super) has_no_default: u32,
2519        }
2520
2521        #[derive(Deftly, Clone, Debug, PartialEq)]
2522        #[derive_deftly(TorConfig)]
2523        #[deftly(tor_config(no_default_trait))]
2524        pub(super) struct Sub {
2525            #[deftly(tor_config(sub_builder))]
2526            pub(super) simple: Simple,
2527
2528            #[deftly(tor_config(sub_builder))]
2529            pub(super) fnd: FieldNoDefault,
2530
2531            #[deftly(tor_config(default))]
2532            pub(super) s: String,
2533        }
2534
2535        #[derive(Deftly, Clone, Debug, PartialEq)]
2536        #[derive_deftly(TorConfig)]
2537        pub(super) struct Magic {
2538            #[deftly(tor_config(default = 7))]
2539            pub(super) nzu8: NonZeroU8,
2540
2541            #[deftly(tor_config(default = 123))]
2542            pub(super) nzu8_2: NonZero<u8>,
2543
2544            #[deftly(tor_config(default))]
2545            pub(super) dur: Duration,
2546
2547            #[deftly(tor_config(default))]
2548            pub(super) s: String,
2549        }
2550
2551        #[derive(Deftly, Clone, Debug, PartialEq)]
2552        #[derive_deftly(TorConfig)]
2553        pub(super) struct CfgEnabled {
2554            #[deftly(tor_config(
2555                default,
2556                cfg = { true },
2557                cfg_desc = "with eschaton immenentization"
2558            ))]
2559            pub(super) flower_power: u32,
2560            #[deftly(tor_config(
2561                default,
2562                cfg = { true },
2563                cfg_reject,
2564                cfg_desc = "with eschaton immenentization"
2565            ))]
2566            pub(super) flower_power_err: u32,
2567        }
2568
2569        #[derive(Deftly, Clone, Debug, PartialEq)]
2570        #[derive_deftly(TorConfig)]
2571        pub(super) struct CfgDisabled {
2572            #[deftly(tor_config(
2573                default,
2574                cfg = { false },
2575                cfg_desc = "with resublimated thiotimoline"
2576            ))]
2577            pub(super) time_travel: u32,
2578            #[deftly(tor_config(
2579                default,
2580                cfg = "false",
2581                cfg_reject,
2582                cfg_desc = "with resublimated thiotimoline"
2583            ))]
2584            pub(super) time_travel_err: u32,
2585        }
2586
2587        #[derive(Deftly, Clone, Debug, PartialEq)]
2588        #[derive_deftly(TorConfig)]
2589        #[deftly(tor_config(
2590            pre_build = Self::check_odd,
2591            post_build = CfgValidating::check_even
2592        ))]
2593        pub(super) struct CfgValidating {
2594            #[deftly(tor_config(default = 1))]
2595            pub(super) odd: u32,
2596            #[deftly(tor_config(default))]
2597            pub(super) even: u32,
2598        }
2599        impl CfgValidatingBuilder {
2600            fn check_odd(&self) -> Result<(), crate::ConfigBuildError> {
2601                if let Some(v) = self.odd {
2602                    if v & 1 != 1 {
2603                        return Err(crate::ConfigBuildError::Invalid {
2604                            field: "odd".to_string(),
2605                            problem: "Not odd".to_string(),
2606                        });
2607                    }
2608                }
2609                Ok(())
2610            }
2611        }
2612        impl CfgValidating {
2613            fn check_even(self) -> Result<Self, crate::ConfigBuildError> {
2614                if self.even & 1 != 0 {
2615                    return Err(crate::ConfigBuildError::Invalid {
2616                        field: "even".to_string(),
2617                        problem: "Not even".to_string(),
2618                    });
2619                }
2620                Ok(self)
2621            }
2622        }
2623
2624        #[derive(Deftly, Clone, Debug, PartialEq)]
2625        #[derive_deftly(TorConfig)]
2626        #[deftly(tor_config(
2627            no_serialize_trait,
2628            no_test_default,
2629            no_extendbuilder_trait,
2630            no_flattenable_trait
2631        ))]
2632        pub(super) struct CfgGeneric<T, U>
2633        where
2634            T: Clone + std::fmt::Debug + PartialEq + Default,
2635            U: Clone + std::fmt::Debug + PartialEq + Default,
2636        {
2637            #[deftly(tor_config(default, no_magic))]
2638            pub(super) t: T,
2639            #[deftly(tor_config(default, no_magic))]
2640            pub(super) u: U,
2641        }
2642
2643        #[derive(Deftly, Clone, Debug, PartialEq)]
2644        #[derive_deftly(TorConfig)]
2645        pub(super) struct OptionsCfg {
2646            #[deftly(tor_config(default))]
2647            pub(super) a: Option<u32>,
2648            #[deftly(tor_config(default = Some(123)))]
2649            pub(super) b: Option<u32>,
2650            #[deftly(tor_config(default = Some(42)))]
2651            pub(super) nz: Option<NonZeroU8>,
2652            #[deftly(tor_config(default))]
2653            pub(super) s: Option<String>,
2654            #[deftly(tor_config(default))]
2655            pub(super) other: Option<(u32, u32)>,
2656        }
2657
2658        #[derive(Deftly, Clone, Debug, PartialEq)]
2659        #[derive_deftly(TorConfig)]
2660        #[deftly(tor_config(attr = #[derive(Eq,Ord,PartialOrd,PartialEq)]))]
2661        pub(super) struct AttribsCfg {
2662            #[deftly(tor_config(default))]
2663            #[deftly(tor_config(attr = { serde(alias = "fun_with_numbers") }))]
2664            #[deftly(tor_config(serde = r#"alias = "its_fun_to_count""#))]
2665            pub(super) a: u32,
2666        }
2667
2668        #[derive(Deftly, Clone, Debug, PartialEq)]
2669        #[derive_deftly(TorConfig)]
2670        pub(super) struct SettersCfg {
2671            #[deftly(tor_config(default, setter(skip)))]
2672            pub(super) a: u32,
2673
2674            #[deftly(tor_config(default, setter(into)))]
2675            pub(super) b: u32,
2676
2677            #[deftly(tor_config(default, setter(try_into)))]
2678            pub(super) c: u32,
2679            #[deftly(tor_config(default, setter(strip_option)))]
2680            pub(super) d: Option<u32>,
2681            #[deftly(tor_config(default, setter(name = set_the_e)))]
2682            pub(super) e: u32,
2683        }
2684        impl SettersCfgBuilder {
2685            // Custom setter.
2686            pub(super) fn a(&mut self, val: u32) {
2687                self.a = Some(val * 2);
2688            }
2689        }
2690
2691        #[derive(Deftly, Clone, Debug, PartialEq)]
2692        #[derive_deftly(TorConfig)]
2693        #[deftly(tor_config(no_serialize_trait, no_deserialize_trait))]
2694        pub(super) struct NoSerdeCfg {
2695            #[deftly(tor_config(default))]
2696            pub(super) ip: u128,
2697        }
2698
2699        #[derive(Deftly, Clone, Debug, PartialEq)]
2700        #[derive_deftly(TorConfig)]
2701        #[deftly(tor_config(build_fn(name = "build_this")))]
2702        pub(super) struct RenameBuild {
2703            #[deftly(tor_config(default))]
2704            pub(super) member: u16,
2705        }
2706
2707        #[derive(Deftly, Clone, Debug, PartialEq)]
2708        #[derive_deftly(TorConfig)]
2709        pub(super) struct RenameSubBuild {
2710            #[deftly(tor_config(sub_builder(build_fn = "build_this")))]
2711            pub(super) inner: RenameBuild,
2712        }
2713
2714        #[derive(Deftly, Clone, Debug, PartialEq)]
2715        #[derive_deftly(TorConfig)]
2716        pub(super) struct FullyCustom {
2717            #[deftly(tor_config(
2718                setter(skip),
2719                field(ty = (u32, u32), vis = "pub(super)"),
2720                build = { |this: &Self| format!("{} {}", this.value.0, this.value.1) },
2721                extend_with = { |mine: &mut (u32,u32), theirs: (u32,u32), _| *mine = theirs },
2722            ))]
2723            pub(super) value: String,
2724        }
2725        impl FullyCustomBuilder {
2726            pub(super) fn try_the_thing(&mut self, x: u64) {
2727                self.value = ((x >> 32) as u32, x as u32);
2728            }
2729        }
2730        #[derive(Deftly, Clone, Debug, PartialEq)]
2731        #[derive_deftly(TorConfig)]
2732        pub(super) struct FieldSkipCfg {
2733            #[deftly(tor_config(skip, build = { |_this: &Self| 25 }))]
2734            pub(super) value: u32,
2735        }
2736
2737        #[derive(Deftly, Clone, Debug, PartialEq)]
2738        #[derive_deftly(TorConfig)]
2739        pub(super) struct ListsCfg {
2740            #[deftly(tor_config(list(element(clone)), default = vec![7]))]
2741            pub(super) integers: Vec<u32>,
2742
2743            #[deftly(tor_config(
2744                list(listtype = StringSet, element(clone)),
2745                default = cats()
2746            ))]
2747            pub(super) cats: BTreeSet<String>,
2748
2749            #[deftly(tor_config(list(element(build)), default = vec![]))]
2750            pub(super) simple: Vec<Simple>,
2751        }
2752
2753        fn cats() -> Vec<String> {
2754            ["Damiano", "Moonbeam", "Checkers", "Enigma"]
2755                .iter()
2756                .map(|s| s.to_string())
2757                .collect()
2758        }
2759
2760        #[derive(Deftly, Clone, Debug, PartialEq)]
2761        #[derive_deftly(TorConfig)]
2762        pub(super) struct MapCfg {
2763            #[deftly(tor_config(map, default = default_map()))]
2764            pub(super) map: HashMap<String, Simple>,
2765        }
2766        fn default_map() -> HashMap<String, SimpleBuilder> {
2767            let mut b = SimpleBuilder::new();
2768            b.abc(32);
2769            b.xyz(123);
2770            let mut m = HashMap::new();
2771            m.insert("pangolin".to_string(), b);
2772            m
2773        }
2774    }
2775
2776    #[test]
2777    fn test_simple_defaults() {
2778        let b = t::SimpleBuilder::new();
2779        let x = b.build().unwrap();
2780        assert_eq!(x.xyz, 0);
2781        assert_eq!(x.abc, 3);
2782        assert_eq!(x.forty_two, 42);
2783        assert_eq!(x.forty_three, 43);
2784    }
2785
2786    #[test]
2787    fn test_simple_setters() {
2788        let mut b = t::SimpleBuilder::new();
2789        let x = b.abc(7).xyz(77).forty_two(777).build().unwrap();
2790        assert_eq!(x.xyz, 77);
2791        assert_eq!(x.abc, 7);
2792        assert_eq!(x.forty_two, 42);
2793        assert_eq!(x.forty_three, 43);
2794    }
2795
2796    #[test]
2797    fn test_simple_serde() {
2798        let v = r#"
2799        xyz = 7
2800        "#;
2801        let b: t::SimpleBuilder = toml::from_str(v).unwrap();
2802        let x = b.build().unwrap();
2803        assert_eq!(x.xyz, 7);
2804        assert_eq!(x.abc, 3);
2805        assert_eq!(x.forty_two, 42);
2806        assert_eq!(x.forty_three, 43);
2807    }
2808
2809    #[test]
2810    fn test_field_no_default() {
2811        let e = t::FieldNoDefaultBuilder::new().build().unwrap_err();
2812        assert_matches!(
2813            e,
2814            ConfigBuildError::MissingField {
2815                field
2816            } if field == "has_no_default"
2817        );
2818        let v = t::FieldNoDefaultBuilder::new()
2819            .has_no_default(42)
2820            .build()
2821            .unwrap();
2822        assert_eq!(v.has_default, 0);
2823        assert_eq!(v.has_no_default, 42);
2824    }
2825
2826    #[test]
2827    fn test_subbuilder() {
2828        let e = t::SubBuilder::new().build().unwrap_err();
2829        assert_matches!(
2830            e,
2831            ConfigBuildError::MissingField {
2832                field
2833            } if field == "fnd.has_no_default"
2834        );
2835
2836        let mut b = t::SubBuilder::new();
2837        b.fnd().has_no_default(5).has_default(66);
2838        b.simple().abc(123);
2839        b.s("Hello");
2840        let v = b.build().unwrap();
2841        assert_eq!(v.fnd.has_no_default, 5);
2842        assert_eq!(v.fnd.has_default, 66);
2843        assert_eq!(v.simple.abc, 123);
2844        assert_eq!(v.simple.xyz, 0);
2845        assert_eq!(v.s, "Hello");
2846    }
2847
2848    #[test]
2849    fn test_subbuilder_serde() {
2850        let v = r#"
2851        s = "hello world"
2852        [fnd]
2853        has_no_default = 1234
2854        "#;
2855        let b: t::SubBuilder = toml::from_str(v).unwrap();
2856        let x = b.build().unwrap();
2857        assert_eq!(x.fnd.has_no_default, 1234);
2858        assert_eq!(x.fnd.has_default, 0);
2859        assert_eq!(x.s, "hello world");
2860    }
2861
2862    #[test]
2863    fn test_magic_nz() {
2864        let mut b = t::Magic::builder();
2865        b.nzu8(123);
2866        b.nzu8_2(1);
2867        let v = b.build().unwrap();
2868        assert_eq!(v.nzu8.get(), 123);
2869        assert_eq!(v.nzu8_2.get(), 1);
2870
2871        let e = t::MagicBuilder::new().nzu8(0).build().unwrap_err();
2872        let ConfigBuildError::Invalid { field, problem } = e else {
2873            panic!("Error not as expected ({e:?})");
2874        };
2875        assert_eq!(field, "nzu8");
2876        assert_eq!(problem, "value not allowed to be zero");
2877
2878        let e = t::MagicBuilder::new().nzu8_2(0).build().unwrap_err();
2879        let ConfigBuildError::Invalid { field, problem } = e else {
2880            panic!("Error not as expected ({e:?})");
2881        };
2882        assert_eq!(field, "nzu8_2");
2883        assert_eq!(problem, "value not allowed to be zero");
2884    }
2885
2886    #[test]
2887    fn test_magic_string() {
2888        let mut b = t::Magic::builder();
2889        b.s("hello"); // <-- note that this is not a String.
2890        let v = b.build().unwrap();
2891        assert_eq!(v.s, "hello");
2892
2893        #[allow(clippy::unnecessary_to_owned)]
2894        b.s("world".to_string());
2895        let v = b.build().unwrap();
2896        assert_eq!(v.s, "world");
2897    }
2898
2899    #[test]
2900    fn test_magic_duration() {
2901        let v = r#"
2902        dur = "1 hour"
2903        "#;
2904        let b: t::MagicBuilder = toml::from_str(v).unwrap();
2905        let x = b.build().unwrap();
2906        assert_eq!(x.dur, std::time::Duration::new(60 * 60, 0));
2907    }
2908
2909    #[test]
2910    #[traced_test]
2911    fn test_cfg_enabled() {
2912        let s = r#"
2913        flower_power = 12
2914        flower_power_err = 14
2915        "#;
2916        let b: t::CfgEnabledBuilder = toml::from_str(s).unwrap();
2917        let v = b.build().unwrap();
2918        assert_eq!(v.flower_power, 12);
2919        assert_eq!(v.flower_power_err, 14);
2920        assert!(!logs_contain("no effect"));
2921    }
2922
2923    #[test]
2924    #[traced_test]
2925    fn test_cfg_disabled() {
2926        let s = r#"
2927        time_travel = "hello world"
2928        "#;
2929        let b: t::CfgDisabledBuilder = toml::from_str(s).unwrap();
2930        let v = b.build().unwrap();
2931        assert_eq!(v.time_travel, 0);
2932        assert!(logs_contain(
2933            "Ignored configuration for 'time_travel'. \
2934            This option has no effect unless the program is built with resublimated thiotimoline"
2935        ));
2936
2937        let s = r#"
2938        time_travel_err = "hello world"
2939        "#;
2940        let b: t::CfgDisabledBuilder = toml::from_str(s).unwrap();
2941        let e = b.build().unwrap_err();
2942        assert_matches!(e, ConfigBuildError::NoCompileTimeSupport { .. });
2943    }
2944
2945    #[test]
2946    fn test_validating() {
2947        let err_notodd = t::CfgValidating::builder().odd(6).build().unwrap_err();
2948        assert_eq!(
2949            err_notodd.to_string(),
2950            "Value of odd was incorrect: Not odd"
2951        );
2952        let err_noteven = t::CfgValidating::builder().even(5).build().unwrap_err();
2953        assert_eq!(
2954            err_noteven.to_string(),
2955            "Value of even was incorrect: Not even"
2956        );
2957        let v = t::CfgValidating::builder().odd(5).even(6).build().unwrap();
2958        assert_eq!(v.odd, 5);
2959        assert_eq!(v.even, 6);
2960    }
2961
2962    #[test]
2963    fn test_generic() {
2964        let mut b = t::CfgGeneric::<String, Vec<u32>>::builder();
2965        b.t("This is a test".to_string());
2966        b.u(vec![1, 2, 3]);
2967        let v = b.build().unwrap();
2968        assert_eq!(v.t, "This is a test");
2969        assert_eq!(&v.u, &[1, 2, 3]);
2970    }
2971
2972    #[test]
2973    fn test_options_setters() {
2974        let mut b = t::OptionsCfg::builder();
2975        // Try with no-option inputs.
2976        b.a(32);
2977        b.s("hello");
2978        b.other((1, 2));
2979        b.nz(12);
2980        let c = b.build().unwrap();
2981        assert_eq!(c.a, Some(32));
2982        assert_eq!(c.b, Some(123));
2983
2984        assert_eq!(c.s, Some("hello".to_string()));
2985        assert_eq!(c.other, Some((1, 2)));
2986        assert_eq!(c.nz, Some(12.try_into().unwrap()));
2987
2988        // Try with option inputs.
2989        b.a(Some(12));
2990        b.b(None);
2991        b.s(Some("world"));
2992        b.other(Some((11, 22)));
2993        b.nz(Some(std::num::NonZeroU8::new(15).unwrap()));
2994        let c = b.build().unwrap();
2995        assert_eq!(c.a, Some(12));
2996        assert_eq!(c.b, None);
2997        assert_eq!(c.s, Some("world".to_string()));
2998        assert_eq!(c.other, Some((11, 22)));
2999        assert_eq!(c.nz, Some(15.try_into().unwrap()));
3000    }
3001
3002    #[test]
3003    fn test_attributes() {
3004        let s1 = "fun_with_numbers = 1982374";
3005        let s2 = "its_fun_to_count = 1982375";
3006        let b1: t::AttribsCfgBuilder = toml::from_str(s1).unwrap();
3007        let b2: t::AttribsCfgBuilder = toml::from_str(s2).unwrap();
3008        // Make sure that derive(PartialEq, Ord) happened.
3009        assert_eq!(b1, b1);
3010        assert_ne!(b1, b2);
3011        assert!(b1 < b2);
3012    }
3013
3014    #[test]
3015    fn test_setter_meta() {
3016        let mut b = t::SettersCfgBuilder::new();
3017        b.a(7);
3018        b.b(5_u8);
3019        assert!(b.c(1_u64 << 40).is_err());
3020        b.c(100_u64).unwrap();
3021        b.d(19);
3022        b.set_the_e(22);
3023        let v = b.build().unwrap();
3024        assert_eq!(v.a, 7 * 2);
3025        assert_eq!(v.b, 5_u32);
3026        assert_eq!(v.c, 100_u32);
3027        assert_eq!(v.d, Some(19));
3028        assert_eq!(v.e, 22);
3029    }
3030
3031    #[test]
3032    fn test_build_fn_rename() {
3033        let mut b = t::RenameBuild::builder();
3034        let v = b.member(6).build_this().unwrap();
3035        assert_eq!(v.member, 6);
3036
3037        let mut b = t::RenameSubBuild::builder();
3038        b.inner().member(5);
3039        let v = b.build().unwrap();
3040        assert_eq!(v.inner.member, 5);
3041    }
3042
3043    #[test]
3044    fn test_custom() {
3045        let mut b = t::FullyCustomBuilder::new();
3046        b.try_the_thing(0xF00B00B512345678);
3047        assert_eq!(b.value, (0xF00B00B5, 0x12345678));
3048        let v = b.build().unwrap();
3049
3050        assert_eq!(v.value, "4027252917 305419896");
3051    }
3052
3053    #[test]
3054    fn test_field_skip() {
3055        let c = t::FieldSkipCfg::builder().build().unwrap();
3056        assert_eq!(c.value, 25);
3057    }
3058
3059    #[test]
3060    fn test_list_builder() {
3061        let mut b = t::ListsCfgBuilder::new();
3062        b.set_integers(vec![12, 6, 3]);
3063        let c = b.build().unwrap();
3064        assert_eq!(&c.integers[..], &[12, 6, 3]);
3065        assert!(c.cats.contains("Moonbeam"));
3066        assert!(c.cats.contains("Damiano"));
3067        assert!(c.simple.is_empty());
3068
3069        let b = t::ListsCfgBuilder::new();
3070        let c = b.build().unwrap();
3071        assert_eq!(&c.integers[..], &[7]);
3072
3073        let mut b = t::ListsCfgBuilder::new();
3074        b.integers().push(22);
3075        b.cats().remove(0);
3076        b.cats().push("Frida".to_string());
3077        b.simple().push(t::SimpleBuilder::new());
3078        let c = b.build().unwrap();
3079        assert_eq!(&c.integers[..], &[7, 22]);
3080        assert!(c.cats.contains("Frida"));
3081        assert!(!c.cats.contains("Damiano"));
3082        assert_eq!(c.simple.len(), 1);
3083    }
3084
3085    #[test]
3086    fn test_list_builder_serde() {
3087        let s1 = r#"
3088            integers = [ 1,2,3 ]
3089        "#;
3090        let s2 = r#"
3091            cats = [ "Prof. Jiggly", "Jorts" ]
3092        "#;
3093        let s3 = r#"
3094            cats = [ "Jenny" ]
3095            [[simple]]
3096            xyz = 9
3097            abc = 12
3098            [[simple]]
3099            xyz = 16
3100        "#;
3101        let b1: t::ListsCfgBuilder = toml::from_str(s1).unwrap();
3102        let b2: t::ListsCfgBuilder = toml::from_str(s2).unwrap();
3103        let b3: t::ListsCfgBuilder = toml::from_str(s3).unwrap();
3104        let c1 = b1.build().unwrap();
3105        let c2 = b2.build().unwrap();
3106        let c3 = b3.build().unwrap();
3107
3108        assert_eq!(&c1.integers[..], &[1, 2, 3]);
3109        assert!(c1.cats.contains("Checkers"));
3110        assert!(!c1.cats.contains("Jorts"));
3111
3112        assert_eq!(&c2.integers[..], &[7]);
3113        assert_eq!(c2.cats.len(), 2);
3114        assert!(c2.cats.contains("Jorts"));
3115        assert!(!c2.cats.contains("Checkers"));
3116
3117        assert_eq!(c3.cats.len(), 1);
3118        assert_eq!(c3.simple.len(), 2);
3119        assert_eq!(c3.simple[0].xyz, 9);
3120        assert_eq!(c3.simple[0].abc, 12);
3121        assert_eq!(c3.simple[1].xyz, 16);
3122        assert_eq!(c3.simple[1].abc, 3);
3123    }
3124
3125    #[test]
3126    fn test_map_builder() {
3127        let mut b = t::MapCfg::builder();
3128        {
3129            let mut sb = t::Simple::builder();
3130            sb.xyz(11);
3131            b.map().insert("Hello".to_string(), sb);
3132        }
3133        {
3134            let mut sb = t::Simple::builder();
3135            sb.abc(33);
3136            b.map().insert("World".to_string(), sb);
3137        }
3138        let c = b.build().unwrap();
3139
3140        assert_eq!(c.map.len(), 3);
3141        assert_eq!(c.map.get("Hello").unwrap().xyz, 11);
3142        assert_eq!(c.map.get("Hello").unwrap().abc, 3);
3143        assert_eq!(c.map.get("World").unwrap().xyz, 0);
3144        assert_eq!(c.map.get("World").unwrap().abc, 33);
3145        assert_eq!(c.map.get("pangolin").unwrap().xyz, 123);
3146        assert_eq!(c.map.get("pangolin").unwrap().abc, 32);
3147    }
3148}