config/
memory.rs

1use crate::{
2    util::accumulate_child_keys, ConfigurationBuilder, ConfigurationProvider, ConfigurationSource, Value,
3};
4use std::collections::HashMap;
5
6/// Represents a [`ConfigurationProvider`](crate::ConfigurationProvider) that
7/// provides in-memory configuration values.
8pub struct MemoryConfigurationProvider {
9    data: HashMap<String, (String, Value)>,
10}
11
12impl MemoryConfigurationProvider {
13    /// Initializes a new in-memory configuration provider.
14    ///
15    /// # Arguments
16    ///
17    /// * `data` - The in-memory data associated with the provider
18    ///
19    /// # Remarks
20    ///
21    /// The data key is normalized to uppercase. The value is a tuple where the
22    /// first item is the originally-cased key and the second item is value.
23    pub fn new(data: HashMap<String, (String, Value)>) -> Self {
24        Self { data }
25    }
26}
27
28impl ConfigurationProvider for MemoryConfigurationProvider {
29    fn get(&self, key: &str) -> Option<Value> {
30        self.data
31            .get(&key.to_uppercase())
32            .map(|t| t.1.clone())
33    }
34
35    fn child_keys(&self, earlier_keys: &mut Vec<String>, parent_path: Option<&str>) {
36        accumulate_child_keys(&self.data, earlier_keys, parent_path)
37    }
38}
39
40/// Represents a [`ConfigurationSource`](crate::ConfigurationSource) for in-memory data.
41#[derive(Default)]
42pub struct MemoryConfigurationSource {
43    /// Gets a list of key/value pairs representing the initial data.
44    pub initial_data: Vec<(String, Value)>,
45}
46
47impl MemoryConfigurationSource {
48    /// Initializes a new in-memory configuration source.
49    ///
50    /// # Arguments
51    ///
52    /// * `initial_data` - The list of key/value pairs representing the initial data
53    pub fn new<S: AsRef<str>>(initial_data: &[(S, S)]) -> Self {
54        Self {
55            initial_data: initial_data
56                .iter()
57                .map(|t| (t.0.as_ref().to_owned(), t.1.as_ref().to_owned().into()))
58                .collect(),
59        }
60    }
61}
62
63impl ConfigurationSource for MemoryConfigurationSource {
64    fn build(&self, _builder: &dyn ConfigurationBuilder) -> Box<dyn ConfigurationProvider> {
65        let data: HashMap<_, _> = self
66            .initial_data
67            .iter()
68            .map(|t| (t.0.to_uppercase(), (t.0.clone(), t.1.clone())))
69            .collect();
70        Box::new(MemoryConfigurationProvider::new(data))
71    }
72}
73
74pub mod ext {
75
76    use super::*;
77
78    /// Defines extension methods for [`ConfigurationBuilder`](crate::ConfigurationBuilder).
79    pub trait MemoryConfigurationBuilderExtensions {
80        /// Adds the in-memory configuration source using the specified data.
81        ///
82        /// # Arguments
83        ///
84        /// * `data` - The data to add to memory configuration provider
85        fn add_in_memory<S: AsRef<str>>(&mut self, data: &[(S, S)]) -> &mut Self;
86    }
87
88    impl MemoryConfigurationBuilderExtensions for dyn ConfigurationBuilder + '_ {
89        fn add_in_memory<S: AsRef<str>>(&mut self, data: &[(S, S)]) -> &mut Self {
90            self.add(Box::new(MemoryConfigurationSource::new(data)));
91            self
92        }
93    }
94
95    impl<T: ConfigurationBuilder> MemoryConfigurationBuilderExtensions for T {
96        fn add_in_memory<S: AsRef<str>>(&mut self, data: &[(S, S)]) -> &mut Self {
97            self.add(Box::new(MemoryConfigurationSource::new(data)));
98            self
99        }
100    }
101}