Skip to main content

Crate statime_config

Crate statime_config 

Source
Expand description

Configuration parsing

This crate provides a configuration parsing library and associated derive macros for parsing configuration from multiple TOML files.

As a user of this crate, you will typically define a set of structs, enums and ‘atomic’ values that represent individual configuration settings. To these you then apply the Configurable and ConfigurableAtomic derives.

The root of the configuration tree is represented by the RootConfig type, which is a Configurable struct that holds the configuration for the entire application, but has an additional RootConfig::load method that loads the configuration from TOML files.

use statime_config::{Configurable, ConfigurableAtomic, RootConfig, SystemConfigSetting};

/// The root configuration needs to be a [`Configurable`] struct with [`RootConfig`]
/// implemented, which is used to load the configuration from TOML files.
/// It also needs to contain information which can identify whether and which
/// system configuration is to be used when loading the configuration.
#[derive(Debug, Clone, PartialEq, Eq, Configurable)]
pub struct Config {
    /// Whether to use the system configuration files, note the default
    /// attribute calls Default::default()
    #[config(default)]
    pub use_system_config: UseSystemConfig,

    /// This section has no default value, if any value within it is not
    /// specified and has no default, that will be an error.
    pub observability: ObservabilityConfig,
}

impl RootConfig for Config {
    fn use_system_config(partial: &Self::Partial) -> SystemConfigSetting {
        match partial.use_system_config.clone().into_option() {
            Some(UseSystemConfig::Enabled(false)) => SystemConfigSetting::None,
            Some(UseSystemConfig::Enabled(true)) => SystemConfigSetting::DefaultPath(UseSystemConfig::DEFAULT_SYSTEM_CONFIG.into()),
            Some(UseSystemConfig::Directory(path)) => SystemConfigSetting::UserSpecifiedPath(path),
            None => SystemConfigSetting::Unset,
        }
    }
}

/// Only the Configurable derive is needed here, as this is not the root struct.
#[derive(Debug, Clone, PartialEq, Eq, Configurable)]
pub struct ObservabilityConfig {
    /// Example of using a custom enum as an atomic value, note how the
    /// default can also be any expression that evaluates to the type of
    /// the field.
    #[config(default = LogLevel::Info)]
    pub level: LogLevel,
}

/// Example of a custom enum that is used as an atomic value, by deriving
/// the ConfigurableAtomic trait.
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, ConfigurableAtomic)]
#[serde(rename_all = "kebab-case")]
pub enum LogLevel {
    Debug,
    Info,
    Warn,
    Error,
}


/// Which system configuration to layer underneath the main configuration, if
/// any.
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, ConfigurableAtomic)]
#[serde(untagged)]
pub enum UseSystemConfig {
    /// `true` reads the fragments supplied by the distribution, `false` uses no
    /// system configuration at all.
    Enabled(bool),

    /// A directory to read the fragments from, instead of the default one.
    Directory(PathBuf),
}

impl UseSystemConfig {
    pub const DEFAULT_SYSTEM_CONFIG: &str = "/usr/lib/ntpd-rs/system-config";
}

impl Default for UseSystemConfig {
    fn default() -> Self {
        Self::Enabled(false)
    }
}

fn main() {
    let config = Config::load("/path/to/config.toml").unwrap();
}

Modules§

serde_util

Structs§

ConfigPath
A path in the tree, such as observability.log-level or sources[2].address.
MergeContext
The context within the current merge operation. Generated code only ever walks it with MergeContext::at; the rest is the loader’s business.
NonNegative
OriginId
A unique identifier that represents an origin.
Positive

Enums§

ConfigError
Everything that can go wrong while loading a configuration.
EnumSection
EnumSections are merge-able partial values within a configuration tree that have no default partial value. This is the case for enums, which may not have a default variant.
InfiniteOr
MergePolicy
Whether to merge by overriding values, or by rejecting any overlapping values.
Origin
Where a configuration file/value is coming from.
Section
Sections are merge-able partial values within a configuration tree.
Setting
An atomic merge boundary in the configuration tree.
SystemConfigSetting

Traits§

Configurable
Relates a configuration type to how it is represented while a configuration is still being loaded.
ConfigurableAtomic
Marks a type as a value the tree does not look inside.
IsNonNegative
IsPositive
Merge
Allows the merging of two values following the merge policy in the merge context.
PartialTree
Everything the loader needs of a partial configuration tree
PartialValue
A value in a partial configuration tree.
RootConfig
A configuration that a document can be loaded into.

Derive Macros§

Configurable
Generate the partial counterpart of a configuration struct.
ConfigurableAtomic
Mark a type as a configuration value the tree does not look inside.