preftool/
lib.rs

1extern crate caseless;
2extern crate slog;
3#[macro_use]
4extern crate lazy_static;
5#[macro_use]
6extern crate error_chain;
7
8use std::collections::HashSet;
9use std::ops::Deref;
10
11pub use bind::Error as ValidationError;
12pub use bind::Result as ValidationResult;
13pub use bind::{ConfigProxy, FromConfig, Options, ValidateOptions};
14pub use config::ConfigBuilder;
15pub use provider::{ConfigurationProviderBuilder, DefaultConfigurationProvider};
16pub use strings::ConfigKey;
17pub use values::Settings;
18
19/// Common trait used by several objects throughout preftool that owns a slog::Logger instance.
20pub trait LogOwner {
21  fn logger(&self) -> &slog::Logger;
22}
23
24/// Configuration trait. Configuration is thread safe, and cloneable.
25/// Clones *should* be cheap (default config object consits of cloning an
26/// Arc and 3 String instances).
27pub trait Configuration: Sized + Send + Sync + Clone {
28  /// Type used for configuration sections.
29  type Section: Configuration;
30
31  /// Iterator type used to get child sections.
32  type Sections: IntoIterator<Item = Self::Section>;
33
34  /// Get a value from the configuration, if it exists.
35  fn get<K: Into<ConfigKey>>(&self, key: K) -> Option<&str>;
36
37  /// Get a sub-section from the configuration. This always returns a section,
38  /// even if it is empty.
39  fn section<K: Into<ConfigKey>>(&self, key: K) -> Self::Section;
40
41  /// Get all child sections of this configuration, as an iterator.
42  fn sections(&self) -> Self::Sections;
43
44  /// Get the current section key.
45  fn key(&self) -> &ConfigKey;
46
47  /// Get the current section path.
48  fn path(&self) -> &ConfigKey;
49
50  /// Get the current section value (if any).
51  fn value(&self) -> Option<&str>;
52}
53
54/// A configuration provider.
55pub trait ConfigurationProvider: Send + Sync {
56  /// Try to get a value for a given key.
57  fn try_get(&self, key: &ConfigKey) -> Option<&str>;
58
59  /// Get all child keys of a given key.
60  fn get_child_keys(&self, key: &ConfigKey, keys: &mut HashSet<ConfigKey>);
61}
62
63impl<P: ConfigurationProvider> ConfigurationProvider for Box<P> {
64  fn try_get(&self, key: &ConfigKey) -> Option<&str> {
65    self.deref().try_get(key)
66  }
67
68  fn get_child_keys(&self, key: &ConfigKey, keys: &mut HashSet<ConfigKey>) {
69    self.deref().get_child_keys(key, keys)
70  }
71}
72
73impl ConfigurationProvider for Box<dyn ConfigurationProvider> {
74  fn try_get(&self, key: &ConfigKey) -> Option<&str> {
75    self.deref().try_get(key)
76  }
77
78  fn get_child_keys(&self, key: &ConfigKey, keys: &mut HashSet<ConfigKey>) {
79    self.deref().get_child_keys(key, keys)
80  }
81}
82
83/// A configuration source. Produces one or more configuration providers.
84pub trait ConfigurationSource {
85  fn build<B: ConfigurationBuilder>(self, builder: B) -> std::io::Result<B>;
86}
87
88/// A configuration builder.
89pub trait ConfigurationBuilder: Sized {
90  /// Resulting configuration type.
91  type Config: Configuration;
92
93  // TODO: IntoConfigurationProvider trait?
94  /// Add a configuration provider to the builder.
95  fn push_provider<P: ConfigurationProvider + 'static>(self, source: P) -> Self;
96
97  /// Add a configuration source to the builder.
98  fn add<S: ConfigurationSource>(self, source: S) -> std::io::Result<Self> {
99    source.build(self)
100  }
101
102  /// Build the configuration.
103  fn build(self) -> std::io::Result<Self::Config>;
104}
105
106pub mod bind;
107mod config;
108mod macros;
109mod provider;
110mod strings;
111mod values;