figen 0.2.0

Strongly typed configuration bindings and registries generated from a declarative schema
Documentation
#[cfg(feature = "std")]
mod std {
    #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
    pub struct ConfigRegistry {
        pub version: u32,
        pub entries: Vec<RegistryEntry>,
    }

    #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
    pub struct RegistryEntry {
        pub key: String,
        pub default_value: Option<Value>,
        pub value_kind: ValueKind,
    }

    #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
    #[derive(Eq, PartialEq, Debug)]
    pub enum Value {
        String(String),
        Number(i32),
        Boolean(bool),
    }

    #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
    #[derive(Eq, PartialEq, Debug, Copy, Clone)]
    pub enum ValueKind {
        String,
        Number,
        Boolean,
        Custom,
    }
}

#[cfg(not(feature = "std"))]
mod nostd {
    #[cfg_attr(feature = "serde", derive(serde::Serialize))]
    pub struct ConfigRegistry {
        pub version: u32,
        pub entries: &'static [RegistryEntry],
    }

    #[cfg_attr(feature = "serde", derive(serde::Serialize))]
    pub struct RegistryEntry {
        pub key: &'static str,
        pub default_value: Option<Value>,
        pub value_kind: ValueKind,
    }

    #[cfg_attr(feature = "serde", derive(serde::Serialize))]
    #[derive(Eq, PartialEq, Debug)]
    pub enum Value {
        String(&'static str),
        Number(i32),
        Boolean(bool),
    }

    #[cfg_attr(feature = "serde", derive(serde::Serialize))]
    #[derive(Eq, PartialEq, Debug, Copy, Clone)]
    pub enum ValueKind {
        String,
        Number,
        Boolean,
        Custom,
    }
}

#[cfg(not(feature = "std"))]
pub use nostd::*;

#[cfg(feature = "std")]
pub use std::*;

impl ConfigRegistry {
    #[cfg(not(feature = "std"))]
    pub const fn new(version: u32, entries: &'static [RegistryEntry]) -> Self {
        Self { version, entries }
    }
    #[cfg(feature = "std")]
    pub const fn new(version: u32, entries: Vec<RegistryEntry>) -> Self {
        Self { version, entries }
    }

    pub fn get_version(&self) -> u32 {
        self.version
    }

    pub fn has_entry(&self, key: &str) -> bool {
        self.entries.iter().any(|entry| entry.key == key)
    }

    pub fn get_entry(&self, key: &str) -> Option<&RegistryEntry> {
        self.entries.iter().find(|entry| entry.key == key)
    }

    pub fn get_default_value(&self, key: &str) -> Option<&Value> {
        let entry = self.get_entry(key);
        if let Some(entry) = entry {
            entry.default_value.as_ref()
        } else {
            None
        }
    }

    pub fn iter_entries(&self) -> impl Iterator<Item = &RegistryEntry> {
        self.entries.iter()
    }
}

impl RegistryEntry {
    #[cfg(not(feature = "std"))]
    pub const fn new(
        key: &'static str,
        value_kind: ValueKind,
        default_value: Option<Value>,
    ) -> Self {
        Self {
            key,
            default_value,
            value_kind,
        }
    }
    #[cfg(feature = "std")]
    pub fn new(key: &'static str, value_kind: ValueKind, default_value: Option<Value>) -> Self {
        Self {
            key: key.into(),
            default_value,
            value_kind,
        }
    }
}