#[derive(Config)]
{
// Attributes available to this derive:
#[config]
}
Expand description
Derives (automatically implements) Config
for a struct.
This only works for structs with named fields, but not for tuple structs, unit structs, enums, or unions.
Quick example
use confique::Config;
use std::net::IpAddr;
#[derive(Config)]
struct Conf {
color: Option<String>,
#[config(nested)]
http: HttpConf,
}
#[derive(Config)]
struct HttpConf {
#[config(env = "APP_PORT")]
port: u16,
#[config(default = "127.0.0.1")]
bind: IpAddr,
}
This derives Config
for the two structs.
HttpConf::port
can be loaded from the environment variableAPP_PORT
.HttpConf::bind
has a default value of127.0.0.1
(the string is turned into theIpAddr
via itsDeserialize
impl). Thus a value for this field does not need to be present when loading configuration.Conf::color
is optional and does not need to be present when loading the configuration.
How to use
There are two types of fields distinguished by this macro: nested and leaf fields.
-
Nested fields: they have to be annotated with
#[config(nested)]
and contain a nested configuration object. The type of this field must implementConfig
. As implied by the previous statement,Option<_>
as type for nested fields is not allowed. -
Leaf fields: all fields not annotated with
#[config (nested)]
, these contain your actual values. The type of such a field has to implementserde::Deserialize
.
Doc comments on the struct and the individual fields are interpreted and
stored in Meta
. They are used in the formatting functions
(e.g. toml::format
).
Attributes
This macro currently recognizes the following attributes for leaf fields:
-
#[config(default = ...)]
: sets a default value for this field. This is returned byPartial::default_values
and, in most circumstances, used as a last “layer” to pull values from that have not been set in a layer of higher-priority. Currently, Boolean, float, integer and string values are allowed. -
#[config(env = "KEY")]
: assigns an environment variable to this field. InPartial::from_env
, the variable is checked and deserialized into the field if present.
Special types for leaf fields
These types give a different meaning/semantic to the field. Please note that due to the limitations of derive macros, the type is checked literally. So it won’t work if you rename symbols or used full paths.
Option<T>
: this marks the field as an optional field. All other fields are non-optional and will raise an error if while loading the configuration, no value has been set for them. Optional fields cannot have a#[config(default = ...)]
attribute as that would not make sense.
What the macro generates
This macro emits one impl confique::Config for … { … }
block. But in order
to implement that trait, a partial type of your struct is also generated.
That partial type lives in its own module and derives
serde::Deserialize
.
The example in the “Quick example” section above would expand to something like this:
impl confique::Config for Conf {
type Partial = confique_partial_conf::PartialConf;
...
}
mod confique_partial_conf {
#[derive(serde::Deserialize)]
pub(super) struct PartialConf {
pub(super) color: Option<String>,
#[serde(default = "confique::Partial::empty")]
pub(super) http: <HttpConf as confique::Config>::Partial,
}
impl confique::Partial for PartialConf { ... }
}
impl confique::Config for HttpConf {
type Partial = confique_partial_http_conf::PartialHttpConf;
...
}
mod confique_partial_http_conf {
#[derive(serde::Deserialize)]
pub(super) struct PartialHttpConf {
pub(super) port: Option<u16>,
pub(super) bind: Option<IpAddr>,
}
impl confique::Partial for PartialHttpConf { ... }
}