Crate confique[][src]

Expand description

Confique is a type-safe, layered, light-weight, serde-based configuration library.

The core of the library is the Config trait and its derive-macro. You define your configuration value as one or more structs, each of which has to #[derive(Config)]. Then you can use different ways of loading an instancce of your root configuration struct.

How to use

Defining your configuration with structs

First, define some structs that describe all your configuration values. Use the types you want to use in your code. For example, if you have a port config and your code needs that value, it should be of type u16, and not Option<u16> or String. That way, the code using that value is cleanest.

Small example:

use confique::Config;

#[derive(Config)]
struct Conf {
    // A required value. Since it's not `Option<_>`, it has to be specified when
    // loading the configuration, or else loading returns an error.
    username: String,

    // An optional value.
    welcome_message: Option<String>,

    // A required value with default value. If no other value is specified
    // (e.g. in a config file), the default value is used.
    #[config(default = 8080)]
    port: u16,
}

As your application grows, oftentimes you want to split the configuration into multiple structs. This has the added benefit that your config files are somewhat structured or have sections. You can do that by including other types that implement Config with #[config(nested)].

use std::path::PathBuf;
use confique::Config;

#[derive(Config)]
struct Conf {
    username: String,

    #[config(nested)]
    log: LogConf,

    #[config(nested)]
    db: DbConf,
}

#[derive(Config)]
struct LogConf {
    #[config(default = true)]
    stdout: bool,

    file: Option<PathBuf>,
}

#[derive(Config)]
struct DbConf {
    // ...
}

You can also attach some other attributes to fields. For example, with #[config(env = "KEY")], you can load a value from an environment variable. For more information, see the docs for the derive macro.

Loading the configuration

Here, you have multiple options. Most of the time, you can probably use the provided high-level methods of Config, like Config::from_file and Config::builder.

use confique::Config;

// Load from a single file only.
let config = Conf::from_file("config.toml")?;

// Or load from multiple sources (higher priority sources are listed first).
let config = Conf::builder()
    .env()
    .file("config.toml")
    .file("/etc/myapp/config.toml")
    .load()?;

But you can also assemble your configuration yourself. That’s what the partial types are for (i.e. Config::Partial). These implement serde::Deserialize and can thus be loaded from a vast number of sources. One of those sources is the built-in File which gives you a bit more control when loading configuration from files. And you can always simply create an instance of the partial type by writing all values in Rust code with struct initializer syntax!

Once you have all your layers (partial types) collected, you have to combine them via Partial::with_fallback and convert them to the actual config type via Config::from_partial. And you probably also want to use Partial::default_values as the last layer.

use confique::{Config, File, FileFormat, Partial};

#[derive(Config)]
struct Conf {
    foo: f32,
}

type PartialConf = <Conf as Config>::Partial;
let from_file: PartialConf = File::with_format("/etc/foo/config", FileFormat::Toml)
    .required()
    .load()?;
let from_file: PartialConf = todo!();
let manual = PartialConf {
    // Remember: all fields in the partial types are `Option`s!
    foo: Some(3.14),
};
let defaults = PartialConf::default_values();

let merged = from_file.with_fallback(manual).with_fallback(defaults);
let config = Conf::from_partial(merged)?;

Using your configuration

Well, this is the simple part: the loaded configuration is just an instance of your struct. And you already know how to access fields of structs!

Cargo features

This crate has a Cargo feature for each supported file format which are all enabled by default.

  • toml: enables TOML support and adds the toml dependency.
  • yaml: enables YAML support and adds the serde_yaml dependency.

Re-exports

pub use serde;

Modules

Types for Config::META. Represent information about a configuration type.

TOML specific features. This module only exists if the Cargo feature toml is enabled.

YAML specific features. This module only exists if the Cargo feature yaml is enabled.

Structs

Convenience builder to configure, load and merge multiple configuration sources.

Type describing all errors that can occur in this library.

A file as source for configuration.

Enums

All file formats supported by confique.

Traits

A configuration object that can be deserialized in layers via serde.

A potentially partial configuration object that can be directly deserialized via serde.

Derive Macros

Derives (automatically implements) Config for a struct.