config/
config.rs

1use std::fmt::Debug;
2
3use serde::de::Deserialize;
4use serde::ser::Serialize;
5
6use crate::builder::{ConfigBuilder, DefaultState};
7use crate::error::{ConfigError, Result};
8use crate::map::Map;
9use crate::path;
10use crate::ser::ConfigSerializer;
11use crate::source::Source;
12use crate::value::{Table, Value};
13
14/// A prioritized configuration repository.
15///
16/// It maintains a set of configuration sources, fetches values to populate those, and provides
17/// them according to the source's priority.
18#[derive(Clone, Debug)]
19pub struct Config {
20    defaults: Map<path::Expression, Value>,
21    overrides: Map<path::Expression, Value>,
22    sources: Vec<Box<dyn Source + Send + Sync>>,
23
24    /// Root of the cached configuration.
25    pub cache: Value,
26}
27
28impl Default for Config {
29    fn default() -> Self {
30        Self {
31            defaults: Default::default(),
32            overrides: Default::default(),
33            sources: Default::default(),
34            cache: Value::new(None, Table::new()),
35        }
36    }
37}
38
39impl Config {
40    pub(crate) fn new(value: Value) -> Self {
41        Self {
42            cache: value,
43            ..Self::default()
44        }
45    }
46
47    /// Creates new [`ConfigBuilder`] instance
48    pub fn builder() -> ConfigBuilder<DefaultState> {
49        ConfigBuilder::<DefaultState>::default()
50    }
51
52    /// Refresh the configuration cache with fresh
53    /// data from added sources.
54    ///
55    /// Configuration is automatically refreshed after a mutation
56    /// operation (`set`, `merge`, `set_default`, etc.).
57    fn refresh(&mut self) -> Result<&mut Self> {
58        self.cache = {
59            let mut cache: Value = Map::<String, Value>::new().into();
60
61            // Add defaults
62            for (key, val) in &self.defaults {
63                key.set(&mut cache, val.clone());
64            }
65
66            // Add sources
67            self.sources.collect_to(&mut cache)?;
68
69            // Add overrides
70            for (key, val) in &self.overrides {
71                key.set(&mut cache, val.clone());
72            }
73
74            cache
75        };
76
77        Ok(self)
78    }
79
80    /// Set an overwrite
81    ///
82    /// This function sets an overwrite value.
83    /// The overwrite `value` is written to the `key` location on every `refresh()`
84    ///
85    /// # Warning
86    ///
87    /// Errors if config is frozen
88    pub(crate) fn set<T>(&mut self, key: &str, value: T) -> Result<&mut Self>
89    where
90        T: Into<Value>,
91    {
92        self.overrides.insert(key.parse()?, value.into());
93
94        self.refresh()
95    }
96
97    fn get_value(&self, key: &str) -> Result<Value> {
98        // Parse the key into a path expression
99        let expr: path::Expression = key.parse()?;
100
101        // Traverse the cache using the path to (possibly) retrieve a value
102        let value = expr.get(&self.cache).cloned();
103
104        value.ok_or_else(|| ConfigError::NotFound(key.into()))
105    }
106
107    pub fn get<'de, T: Deserialize<'de>>(&self, key: &str) -> Result<T> {
108        self.get_value(key).and_then(|value| {
109            // Deserialize the received value into the requested type
110            T::deserialize(value).map_err(|e| e.extend_with_key(key))
111        })
112    }
113
114    pub fn get_string(&self, key: &str) -> Result<String> {
115        self.get_value(key)
116            .and_then(|value| value.into_string().map_err(|e| e.extend_with_key(key)))
117    }
118
119    pub fn get_int(&self, key: &str) -> Result<i64> {
120        self.get_value(key)
121            .and_then(|value| value.into_int().map_err(|e| e.extend_with_key(key)))
122    }
123
124    pub fn get_float(&self, key: &str) -> Result<f64> {
125        self.get_value(key)
126            .and_then(|value| value.into_float().map_err(|e| e.extend_with_key(key)))
127    }
128
129    pub fn get_bool(&self, key: &str) -> Result<bool> {
130        self.get_value(key)
131            .and_then(|value| value.into_bool().map_err(|e| e.extend_with_key(key)))
132    }
133
134    pub fn get_table(&self, key: &str) -> Result<Map<String, Value>> {
135        self.get_value(key)
136            .and_then(|value| value.into_table().map_err(|e| e.extend_with_key(key)))
137    }
138
139    pub fn get_array(&self, key: &str) -> Result<Vec<Value>> {
140        self.get_value(key)
141            .and_then(|value| value.into_array().map_err(|e| e.extend_with_key(key)))
142    }
143
144    /// Attempt to deserialize the entire configuration into the requested type.
145    pub fn try_deserialize<'de, T: Deserialize<'de>>(self) -> Result<T> {
146        T::deserialize(self)
147    }
148
149    /// Attempt to serialize the entire configuration from the given type.
150    pub fn try_from<T: Serialize>(from: &T) -> Result<Self> {
151        let mut serializer = ConfigSerializer::default();
152        from.serialize(&mut serializer)?;
153        Ok(serializer.output)
154    }
155}
156
157impl Source for Config {
158    fn clone_into_box(&self) -> Box<dyn Source + Send + Sync> {
159        Box::new((*self).clone())
160    }
161
162    fn collect(&self) -> Result<Map<String, Value>> {
163        self.cache.clone().into_table()
164    }
165}