configbuilder-pattern-loader 0.1.0

configbuilder-pattern: loader domain, trait contract + tech-agnostic reference implementation.
Documentation
//! Canonical usage of the `Loader` trait against a minimal local implementor.
//!
//! `configbuilder-svc-loader-spi`'s `TomlLoaderOps` is the real,
//! filesystem-backed implementor; this example shows the trait shape without a
//! real backend.

use configbuilder_pattern_loader::{ConfigError, Loader};

#[derive(Debug, Default, serde::Deserialize)]
#[serde(default)]
struct AuthConfig {
    token_ttl_secs: u64,
}

struct InMemoryLoader {
    raw: toml::Value,
}

impl Loader for InMemoryLoader {
    fn load_section<T>(&self, key: &str) -> Result<T, ConfigError>
    where
        T: serde::de::DeserializeOwned + Default,
    {
        match self.raw.get(key) {
            Some(value) => value
                .clone()
                .try_into()
                .map_err(|e: toml::de::Error| ConfigError::Parse(e.to_string())),
            None => Ok(T::default()),
        }
    }

    fn validate(&self) -> Result<(), ConfigError> {
        Ok(())
    }
}

fn main() {
    let raw = match toml::from_str("[auth]\ntoken_ttl_secs = 3600") {
        Ok(raw) => raw,
        Err(e) => {
            eprintln!("failed to parse toml: {e}");
            return;
        }
    };
    let loader = InMemoryLoader { raw };
    match loader.load_section::<AuthConfig>("auth") {
        Ok(auth) => println!("token_ttl_secs = {}", auth.token_ttl_secs),
        Err(e) => eprintln!("failed to load auth section: {e}"),
    }
}