[][src]Crate justconfig

The just-config crate supplies a methods for reading, transforming and validating configuration information from multiple sources.

Before you read any further let's answer a simple question: Is this configuration library for you?

  • If you want to read a configuration file created by your user: yes
  • If you want to flexibly process the information read from a configuration file: yes
  • If you want to add environment variables or constants (command line parameters) to the mix: yes
  • If you want an easy way to merge multiple ocnfiguration sources: yes
  • If you want to add defaults or environment variables: yes
  • If you want to read and write a configuration file: no
  • If you want your configuration file to specify data types: no
  • If you want your configuration file to have significant whitespace or be a mess of brackets: no

Configuration paths

Configuration information in just-config is represented as a set of nodes. Each node can have sub nodes forming a configuration tree. To not limit the developer to a specific choice of separator character the node tree is represented as an instance of the ConfPath struct.

Configuration pipeline

Configuration information in just-config is processed using a configuration pipeline. You retrieve a configuration value from the configuration source by calling get. Then the configuration information is passed though processors and validators.

Configuration source

A configuration source is any struct that implements the Source trait. This make the configuration system very flexible. You can read configuration information from text files, the network or from environment variables. All these configuration sources can be mixed and matched.

There are some configuration sources already included in just-config.

Multiple configuration sources can be registered. They are tried in order of their registration. The first configuration source that returns a value for a configuration key is used. That way configuration sources can be layered. See add_source for more information and an example.

Processors

The processors allow you to pre-process the value read from the configuration source. Processors always operate on the string representation of the value. Their purpose is to transform the string (trim, unquote, unescape, etc.) and prepare it for conversion into the target data type.

Validators

As soon as the first validator is called the string value is converted into the target data type. All validation takes place after the conversion. That way the properties of the target data type can be used to validate the information. The first validation step is always present, its the call to the FromStr method of the target date type. If this conversion fails, the configuration value is returned as invalid.

As you might have guessed, all types implementing the FromStr trait are able to be used as target data types for the configuration. In most cases type inference does a very good job to provide the necessary type information for just-config. Simply assign the configuration value to the target data type and it will use the FromStr trait to convert the string value from the configuration source into that type.

Examples

Basic example

use justconfig::Config;
use justconfig::ConfPath;
use justconfig::sources::text::ConfigText;
use justconfig::sources::env::Env;
use justconfig::sources::defaults::Defaults;
use justconfig::processors::Explode;
use justconfig::validators::Range;
use justconfig::item::ValueExtractor;
use std::ffi::OsStr;
use std::fs::File;

let mut conf = Config::default();

// Allow some environment variables to override configuration values read
// from the configuration file.
let config_env = Env::new(&[
  (ConfPath::from(&["searchPath"]), OsStr::new("SEARCH_PATH")),
]);

// Open the configuration file
let config_file = File::open("myconfig.conf").expect("Could not open config file.");
conf.add_source(ConfigText::new(config_file, "myconfig.conf").expect("Loading configuration file failed."));

// Read the value `num_frobs` from the configuration file.
// Do not allow to use more than 10 frobs.
let num_frobs: i32 = conf.get(conf.root().push("num_frobs")).max(10).value()?;

// Read a list of tags from the configuration file.
let tag_list: Vec<String> = conf.get(conf.root().push("tags")).values(..)?;

// Read the paths from the config file and allow it to be overriden by
// the environment variable. We split everything at `:` to allow passing
// multiple paths using an environment variable. When read from the config
// file, multiple values can be set without using the `:` delimiter.
// Passing 1.. to values() makes sure at least one search path is set.
let search_paths: Vec<String> = conf.get(conf.root().push("searchPath")).explode(':').values(1..)?;

Supplying defaults

Often you want to supply default values for configuration items. This can be done in two ways:

  • Use try_value() and supply the default by using or.
  • Add a Defaults source as the last configuration source to supply a default value.

The second option shortens the pipeline length and allows the defaults to be set at one central location.

use justconfig::Config;
use justconfig::ConfPath;
use justconfig::sources::text::ConfigText;
use justconfig::sources::defaults::Defaults;
use justconfig::item::ValueExtractor;
use std::fs::File;

let mut conf = Config::default();

let config_file = File::open("myconfig.conf").expect("Could not open config file.");
conf.add_source(ConfigText::new(config_file, "myconfig.conf").expect("Loading configuration file failed."));

// Add defaults for `key1` and `key2` as a fallback if they are not set via
// the configuration file.
let mut defaults = Defaults::default();
defaults.set(conf.root().push_all(&["key1"]), "default value 1", "default");
defaults.set(conf.root().push_all(&["key2"]), "default value 2", "default");
conf.add_source(defaults);

Enumerating keys

Every ConfPath keeps track of all items that where created using it. That way configuration sources can create a list of configuration items that can be enumerated. The ConfigText source offers the with_path method that allows you to pass a ConfPath into the parser. This ConfPath is used to create the ConfPath instances for every configuration node. This way the configuration can be enumerated using the passed instance.

use justconfig::Config;
use justconfig::ConfPath;
use justconfig::sources::text::ConfigText;
use justconfig::sources::defaults::Defaults;
use justconfig::item::ValueExtractor;
use std::fs::File;

let mut conf = Config::default();

let config_file = File::open("myconfig.conf").expect("Could not open config file.");
let config_file_path = ConfPath::default();
conf.add_source(ConfigText::with_path(config_file, "myconfig.conf", &config_file_path).expect("Loading configuration file failed."));

for config_node in config_file_path.children() {
    print!("{}", config_node.tail_component_name().unwrap())
}

Modules

error

General error enums.

item

Structures for representing configuration items and values.

processors

Processors trim, split, unescape or otherwise process the configuration items before they get parsed into typed values.

source

Contains the Source trait that must be implemented by configuration sources.

sources

Rust module containing some included configuration sources.

validators

Validators, in contrast to processors do not modify the value on any way.

Structs

ConfPath

An owned, immutable configuration path.

Config

Main struct representing a loaded configuration.