Skip to main content

config/
memory.rs

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