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