Expand description
Reference: Attributes supported by the tor_config macro
§Top-level attributes
These attributes can be provided at the top-level, right after
derive_deftly(TorConfig) and before pub struct FooConfig.
§deftly(tor_config(no_serialize_trait)) — Don’t derive Serialize for the builder struct
By default, the generated Builder will derive serde::Serialize.
This attribute suppresses that behavior.
§deftly(tor_config(no_deserialize_trait)) — Don’t derive Deserialize for the builder struct
By default, the generated Builder will implement serde::Deserialize.
This attribute suppresses that behavior.
Using this option will prevent your type from participating directly in the Arti configuration system.
§deftly(tor_config(no_flattenable_trait)) — Don’t derive Flattenable for the builder struct
By default, the generated Builder will derive Flattenable.
This attribute suppresses that behavior.
§deftly(tor_config(no_extendbuilder_trait)) — Don’t derive ExtendBuilder for the builder struct
By default, the generated Builder will derive ExtendBuilder.
This attribute suppresses that behavior.
§deftly(tor_config(no_default_trait)) — Don’t derive Default for the config struct
By default, the macro will derive Default on the configuration type
by creating a default builder, and constructing the configuration type with it.
§deftly(tor_config(no_test_default)) — Don’t test Default for the config struct
By default, the macro will implement a test to make sure that its generated Default
implementation produces the same result as deserializing an empty configuration builder,
and building it.
This attribute prevents that test from being generated.
The test is also omitted when no_default_trait or no_deserialize_trait is given.
Note: You must specify this option if the configuration type has any generic parameters. Otherwise, it’s best to avoid this attribute.
TODO: We should remove this limitation if we can.
§deftly(tor_config(no_builder_trait)) — Don’t derive Builder for the builder struct
By default, the builder will implement tor_config::load::Builder.
This attribute suppresses that behavior.
This attribute’s name ends with
_traitto remind the caller that the Builder struct itself will still be implemented.
§deftly(tor_config(no_buildable_trait)) — Don’t derive Buildable for the config struct
By default, the configuration struct will implement
tor_config::load::Buildable.
This attribute suppresses that behavior.
§deftly(tor_config(attr = "..")) — Apply an attribute to the builder struct
This attribute passes its contents through to a new attribute on the derived builder struct.
For example, you can make the builder derive PartialOrd by saying
#[deftly(tor_config(attr= "derive(PartialOrd)"))](See also attr for fields.)
§deftly(tor_config(pre_build = "..")) — Call a function before building
This attribute makes the generated build() method call a validation function on itself
before it builds the configuration. The function must take &FooBuilder
as an argument, and return Result<(),ConfigBuildError>. If the function
returns an error, then the build method fails with that error.
Example:
#[derive(Clone,Debug,PartialEq,Deftly)]
#[derive_deftly(TorConfig)]
#[deftly(tor_config(pre_build="Self::must_be_odd"))]
pub struct FavoriteOddNumber {
#[deftly(tor_config(default="23"))]
my_favorite: u32,
}
impl FavoriteOddNumberBuilder {
fn must_be_odd(&self) -> Result<(), ConfigBuildError> {
let Some(fav) = self.my_favorite else { return Ok(()); };
if fav % 2 != 1 {
return Err(ConfigBuildError::Invalid {
field: "my_favorite".to_string(),
problem: format!("{fav} was not an odd number")
})
}
Ok(())
}
}See also post_build.
§deftly(tor_config(post_build = "..")) — Call a function after building
This attribute makes the generated build() method call a validation function
on the configuration after it is built.
The function must take the configuration
by value as an argument,
and Result<(the configuration),ConfigBuildError>. If the function
returns an error, then the build method fails with that error.
Example:
#[derive(Clone,Debug,PartialEq,Deftly)]
#[derive_deftly(TorConfig)]
#[deftly(tor_config(post_build="FavoriteEvenNumber::must_be_even"))]
pub struct FavoriteEvenNumber {
#[deftly(tor_config(default="86"))]
my_favorite: u32,
}
impl FavoriteEvenNumber {
fn must_be_even(self) -> Result<Self, ConfigBuildError> {
if self.my_favorite % 2 != 0 {
return Err(ConfigBuildError::Invalid {
field: "my_favorite".to_string(),
problem: format!("{} was not an even number", self.my_favorite)
})
}
Ok(self)
}
}Note: You can also use this attribute to clean up or normalize the configuration object.
§deftly(tor_config(vis = "..")) — Change visibility of the builder
By default, the builder struct is generated with the same visibility as the configuration struct. You can use this attribute to change its visibility.
§deftly(tor_config(build_fn(name = ".."))) — Change name of the build method
By default, the generated build method is called build.
You can use this attribute to change its name.
§deftly(tor_config(build_fn(vis = ".."))) — Change visibility of the build method
By default, the build() method has the same visibility as the builder struct.
You can use this attribute to change its visibility.
See also:
§deftly(tor_config(build_fn(error = ".."))) — Change return error type of the build method.
By default, the build() method returns [ConfigBuildError
on failure. You can change the error type with this attribute.
You will probably need to use this attribute along with build_fn(missing_field),
if any of your fields are mandatory.
§deftly(tor_config(build_fn(missing_field = ".."))) — Code to generate a missing field error.
By default, when a required field is not set, the build() method returns
Err(E::MissingField { field: "field_name".to_string() }),
where E is ConfigBuildError or the type configured with build_fn(error).
You can use this attribute to override this behavior.
Its value should be an expression evaluating to a closure of type
FnOnce(&str) -> E.
For compatibility with
derive_builder’s version of `build_fn(error)``, you can say:#[build_fn(error="SomeError", missing_field= r#"|fname| derive_builder::UninitializedFieldError( fname.to_string() ).into()" )]
§Field-level attributes
§deftly(tor_config(default))) — Use Default::default() when no value is provided
When this attribute is provided, if the given field is absent in the builder,
the build() method will set its value to Default::default().
For each field, you must specify exactly one of
default, default =, no_default, build, try_build, or sub_builder.
§deftly(tor_config(default = ".."))) — Use a given value when no value is provided
When this attribute is provided, if the given field is absent in the builder,
the build() method will set its value to the value of the provided expression.
The expression may invoke a function, but cannot use self.
For each field, you must specify exactly one of
default, default =, no_default, build, try_build, or sub_builder.
§deftly(tor_config(no_default)) — Do not provide a default for this field.
When this attribute is provided, if the given field is absent in the builder,
the build() method will fail with an error.
For each field, you must specify exactly one of
default, default =, no_default, build, try_build, or sub_builder.
When you set this attribute on a field, you must also set the top-level
no_default_traitattribute, since there will not be a meaningful value for the configuration struct.Don’t use this option on any config struct that’s always present with a multiplicity of one, or else the empty configuration will become invalid.
§deftly(tor_config(build = "..")) — Call a function to build this field.
When this attribute is provided, you can completely override the way that this field is constructed.
The expression must evaluate to a function taking &Builder as an argument,
and returning the type of the field.
For each field, you must specify exactly one of
default, default =, no_default, build, try_build, or sub_builder.
Be careful with this attribute: it can lead to counterintuitive behavior for the end user.
Example:
#[derive(Clone,Debug,PartialEq,Deftly)]
#[derive_deftly(TorConfig)]
pub struct LowercaseExample {
#[deftly(tor_config(build="Self::build_lc"))]
lc: String,
}
impl LowercaseExampleBuilder {
fn build_lc(&self) -> String {
let s = self.lc.as_ref().map(String::as_str).unwrap_or("");
s.to_lowercase()
}
}§deftly(tor_config(try_build = "..")) — Call a fallible function to build this field.
When this attribute is provided, you can completely override the way that this field is constructed.
The expression must evaluate to a function taking &Builder as an argument,
and returning Result<T, ConfigBuildError>, where T is the type of the field.
For each field, you must specify exactly one of
default, default =, no_default, build, try_build, or sub_builder.
Be careful with this attribute: it can lead to counterintuitive behavior for the end user.
Example:
#[derive(Clone,Debug,PartialEq,Deftly)]
#[derive_deftly(TorConfig)]
pub struct SqrtExample {
#[deftly(tor_config(try_build="Self::build_sqrt"))]
val: f64,
}
impl SqrtExampleBuilder {
fn build_sqrt(&self) -> Result<f64, ConfigBuildError> {
let v = self.val.unwrap_or(0.0).sqrt();
if v.is_nan() {
return Err(ConfigBuildError::Invalid {
field: "val".to_string(),
problem: format!("{v} was negative")
})
}
Ok(v)
}
}§deftly(tor_config(sub_builder)) — Declare a field to contain a nested configuration
This attribute is what allows configuration structures to nest.
When you set this attribute on a field of type InnerCfg,
the builder structure will contain a field of type InnerCfgBuilder.
In order to construct the field, the build() method will call
InnerCfgBuilder::build().
For each field, you must specify exactly one of
default, default =, no_default, build, try_build, or sub_builder.
§deftly(tor_config(sub_builder(build_fn = "..."))) — Call a different function on this sub-builder
By default, when sub_builder is in use,
the build() method is used to generate the inner configuration object.
This attribute changes the name of the function that is called on the inner builder.
§deftly(tor_config(no_sub_builder)) — Allow a Buildable field without a sub_builder.
By default, the TorConfig macro inserts code to checks whether each field
implements Buildable, and causes a compile-time error if any such field
does not have an explicit sub_builder, build, try_build,
or no_magic declaration.
This attribute overrides this check, and allows you to have a field
implementing Buildable without using the sub_builder pattern.
§deftly(tor_config(list)) — Declare a field to contain a nested list of items.
This attribute should be used on every field containing a Vec,
BTreeSet, HashSet, or similar.
It causes the an appropriate list-builder
and set of accessors to be generated.
When using this attribute, you must also provide a default = producing a Vec
of the builder type, and either list(element(build)) or list(element(clone)).
Examples:
// The builder and the constructed list will both contain u32.
#[deftly(tor_config(list(element(clone)), default = "vec![7]"))]
integers: Vec<u32>,
// The builder will contain a Vec<MyTypeBuilder>;.
#[deftly(tor_config(list(), (element(build)), default = "vec![]"))]
objects: Vec<MyType>§deftly(tor_config(list(listtype = ...)))
Usually, the name of the list type alias and builder object based on the struct and the field name.
You can provide a different name for the list type alias using this attribute, as in
listtype = "TypeName".
The list builder will then be constructed with the list type name, suffixed with Builder.
§deftly(tor_config(list(element(build))) — Declare that the list builder contains sub-builders.
Used along with list,
and indicates the elements of the built list should be constructed via
builders themselves. When this attribute is used, the builder structure
will contain a Vec of builders for the list’s elements.
If this attribute is given a value, it will be used as the name of the “build” method for the list elements.
§deftly(tor_config(list(element(clone))) — Declare that the list builder objects should be cloned directly.
Used along with list,
and indicates the elements of the built list should be cloned directly
from those in the builder. When this attribute is used, the builder structure
will contain a Vec whose elements are the same type as those of the genated list.
§deftly(tor_config(map)) — Use a map-builder pattern.
This attribute should be used on every field containing a HashMap or BTreeMap
whose key is a String, and whose value type is a Buildable.
It causes the template to generate a map builder type and corresponding accessor functions.
The map builder behaves like a map from String to the builder type.
If a value is provided for this attribute, it is used as the name of the
map type alias, and suffixed with Builder to get the name for the builder type.
Otherwise, the map type alias is derived from the name of the struct and the field.
The default = attribute is mandatory with this attribute.
For more information on the generated code, see
define_map_builder.
§deftly(tor_config(list(maptype = ...)))
Usually, the name of the map type alias and builder object based on the struct and the field name.
You can provide a different name for the map type alias using this attribute, as in
maptype = "TypeName".
The map builder will then be constructed with the map type name, suffixed with Builder.
§deftly(tor_config(setter(name = ".."))) — Change the name of the setter function
By default, the setter function for a field has the same name as its field. You can provide a different name in this attribute.
§deftly(tor_config(setter(vis = ".."))) — Change the visibility of the setter function
By default, the setter function for a field has the same visibility as the builder type. You can provide a different visibility in this attribute.
§deftly(tor_config(setter(skip))) — Do not generate a setter function
By default, the builder generates a setter function for every field. You can tell it not to do so for a single field by providing this attribute.
§deftly(tor_config(setter(into))) — Have the setter function accept impl Into<T>
By default, the setter function expects an argument of type T,
where T is the same type of the field.
When this option is provided, the setter instead expects an argument of type impl Into<T>,
and calls Into::into on it to set the field.
§deftly(tor_config(setter(try_into))) — Have the setter function accept impl TryInto<T>
By default, the setter function expects an argument of type T,
where T is the same type of the field.
When this option is provided, the setter instead expects an argument of type impl TryInto<T>,
and calls TryInto::try_into on it to set the field.
If try_into returns an error, the setter function returns that error.
§deftly(tor_config(setter(strip_option))) — Have the setter for Option<T> accept T
This attribute requires that the field itself have type Option<T> for some T.
Instead of taking Option<T> as an argument, the setter now accepts T.
§deftly(tor_config(field(ty = ".."))) — Change the type of a field in the builder
By default, for every field of type T in the configuration,
the builder has a field of type Option<T>.
This attribute changes the type of the field in the builder to the provided type.
This attribute has no effect on the generated setter or builder code. Therefore, you will typically need to use it along with the
setter(skip),build, andextend_withfield attributes.
Example:
#[derive(Clone,Debug,PartialEq)]
pub struct ParsedValue {
// ...
}
impl std::str::FromStr for ParsedValue {
type Err = String;
fn from_str(s: &str) -> Result<Self, Self::Err> {
// ...
}
}
#[derive(Clone,Debug,PartialEq,Deftly)]
#[derive_deftly(TorConfig)]
pub struct MyConfig {
#[deftly(tor_config(
try_build = r#"Self::try_build_behavior"#,
field(ty = "Option<String>"),
setter(skip)
))]
behavior: ParsedValue,
}
impl MyConfigBuilder {
pub fn behavior(&mut self, s: impl AsRef<str>) -> &mut Self {
self.behavior = Some(s.as_ref().to_string());
self
}
fn try_build_behavior(&self) -> Result<ParsedValue, ConfigBuildError> {
self.behavior
.as_ref()
.map(String::as_str)
.unwrap_or("Leave the macro processor. Take the cannoli.")
.parse()
.map_err(|problem| ConfigBuildError::Invalid {
field: "behavior".to_string(),
problem,
})
}
}§deftly(tor_config(field(vis = ".."))) — Change the visibility of a field in the builder
By default, fields in the builder are private. This attribute changes their visibility to the one provided.
§deftly(tor_config(skip)) — Do not generate the field in the builder
If this attribute is present, no field is generated in the builder for this field.
Implies setter(skip). Requires build.
§deftly(tor_config(attr = ".."))) — Apply an attribute to the field in the builder
Any attribute provided here is applied to the declared field in the builder.
Example:
#[deftly(tor_config(attr = "allow(deprecated)"))]
x: SomeDeprecatedType,See also the cfg and serde attributes.
§deftly(tor_config(serde = ".."))) — Apply a serde attribute to the field in the builder
Any serde attribute provided here is applied to the declared field in the builder.
Example:
#[deftly(tor_config(serde = r#"alias = "old_name_of_field" "#))]
current_name_of_field: String,Attributes applied with serde apply after any specified with
attr instead.
This is a convenience attribute; you could just use
attrinstead.
§deftly(tor_config(extend_with = "")) — Change the ExtendBuilder behavior for a field.
Unless you specify no_extendbuilder_trait, the builder type will
implement ExtendBuilder,
and will need a way to replace or extend every field in the builder with
the value from another builder.
This attribute lets you override the default behavior for a single field.
It expects an expression that evaluates to type
FnOnce(&mut T, T, ExtendStrategy),
where T is the type of the field in the builder.
§deftly(tor_config(cfg = ".."))) — Mark a field as conditionally present
This option causes a field in the builder to be conditionally present or absent at compile time,
similar to the ordinary cfg attribute.
However, unlike with the ordinary cfg attribute,
if the user provides any configuration values for this field when it is disabled,
the generated build() code will emit a warning via tracing at runtime telling them
what feature they would need to turn on.
If an error is more appropriate than a warning, additionally use
cfg_reject.
Note that you cannot use this along with a regular
cfgattribute, since a regularcfgattribute would suppress the field altogether. Therefore, the field will still be present in the configuration struct even when thecfgcondition is false. To work around this limitation, it’s conventional to arrange for the type of the field to be()when thecfgcondition is false.
The tor_config(cfg_desc) attribute is mandatory to use along with cfg.
It should contain a short prepositional phrase
describing how the program needs to be built with
in order to make this feature present.
Examples might be “with RPC support” or “for Windows”.
Example:
#[cfg(feature = "rpc")]
pub type RpcOptionType = String;
#[cfg(not(feature = "rpc"))]
type RpcOptionType = ();
#[derive(Clone,Debug,PartialEq,Deftly)]
#[derive_deftly(TorConfig)]
pub struct OnionSoupConfig {
#[deftly(tor_config(cfg = r#" feature="rpc" "#, cfg_desc = "with RPC support"))]
#[deftly(tor_config(default))]
rpc_option: RpcOptionType,
}§deftly(tor_config(cfg_reject)) — Reject the configuration when a feature is missing.
Used alongside tor_config(cfg); see also that attribute’s documentation.
Usually, tor_config(cfg) causes a warning if values are provided
for a compiled-out configuration option.
When this attribute is present, then tor_config(cfg) causes an error instead.
§deftly(tor_config(cfg_desc = ".."))) — Description of when a field is present.
Used along with tor_config(cfg); see that attribute’s documentation.
§deftly(tor_config(no_magic))) — Disable magic handling based on a field’s type
This attribute disables type-based magic behavior for the current field.