1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
//! 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.
//!
//! ```no_run
//! # use std::path::PathBuf;
//! # use serde::{Deserialize, Serialize};
//! 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();
//! }
//! ```
// so that the derive macro can name this crate even from inside it
extern crate self as statime_config;
pub use ConfigError;
pub use ;
// the traits and the derives that implement them share their names, so that
// one import brings both, as serde does
pub use ;
// `Setting` and `Section` are what `Configurable::Node` resolves to, so they
// are part of the interface whether or not anyone names them directly
pub use ;
/// The machinery the derive macro's generated code reaches for, which is
/// everything it needs that is not already public. Not a stable interface.