Skip to main content

configbuilder_pattern_loader/
default_loader.rs

1use crate::{ConfigError, FeatureLoader, FeatureState, LoadedFeature, Loader, LoaderOps};
2
3/// Reference `Loader`/`FeatureLoader` implementation: a generic dispatch shell over
4/// any real [`LoaderOps`] implementor.
5///
6/// Doesn't care what's boxed inside — the real, filesystem/TOML-backed implementor
7/// (`configbuilder-svc-loader-spi`) is constructed by
8/// `configbuilder-svc-saf` and boxed here.
9pub struct DefaultLoader {
10    /// The real `LoaderOps` implementor this loader dispatches to.
11    pub ops: Box<dyn LoaderOps>,
12}
13
14impl DefaultLoader {
15    /// Load and deserialize a named section.
16    pub(crate) fn load_section<T>(&self, key: &str) -> Result<T, ConfigError>
17    where
18        T: serde::de::DeserializeOwned + Default,
19    {
20        let val = self.ops.load_section_value(key)?;
21        if val.as_table().is_some_and(|t| t.is_empty()) {
22            return Ok(T::default());
23        }
24        val.try_into()
25            .map_err(|e: toml::de::Error| ConfigError::Parse(e.to_string()))
26    }
27
28    /// Validate the loader's configured directories.
29    pub(crate) fn validate(&self) -> Result<(), ConfigError> {
30        self.ops.validate_dirs()
31    }
32
33    /// Load a named feature and return its state plus record metadata.
34    pub(crate) fn load_feature<T>(&self, key: &str) -> Result<LoadedFeature<T>, ConfigError>
35    where
36        T: serde::de::DeserializeOwned,
37    {
38        let raw = self.ops.load_feature_raw(key)?;
39        let state = match raw.value {
40            None => FeatureState::Disabled,
41            Some(val) => FeatureState::Enabled(
42                val.try_into()
43                    .map_err(|e: toml::de::Error| ConfigError::Parse(e.to_string()))?,
44            ),
45        };
46        Ok(LoadedFeature {
47            state,
48            record: raw.record,
49        })
50    }
51
52    /// Load a named section and return only its enabled/disabled state.
53    pub(crate) fn load_optional_section<T>(&self, key: &str) -> Result<FeatureState<T>, ConfigError>
54    where
55        T: serde::de::DeserializeOwned,
56    {
57        self.load_feature(key).map(|loaded| loaded.state)
58    }
59}
60
61impl Loader for DefaultLoader {
62    fn load_section<T>(&self, key: &str) -> Result<T, ConfigError>
63    where
64        T: serde::de::DeserializeOwned + Default,
65    {
66        self.load_section(key)
67    }
68
69    fn validate(&self) -> Result<(), ConfigError> {
70        self.validate()
71    }
72}
73
74impl FeatureLoader for DefaultLoader {
75    fn load_feature<T>(&self, key: &str) -> Result<LoadedFeature<T>, ConfigError>
76    where
77        T: serde::de::DeserializeOwned,
78    {
79        self.load_feature(key)
80    }
81}