tier 0.1.17

Rust configuration library for layered TOML, env, and CLI settings
Documentation
use std::fmt::{self, Display, Formatter};

#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
/// Policy applied when unknown configuration paths are discovered.
pub enum UnknownFieldPolicy {
    /// Accept unknown fields silently.
    Allow,
    /// Accept unknown fields but emit warnings.
    Warn,
    #[default]
    /// Reject unknown fields with an error.
    Deny,
}

impl Display for UnknownFieldPolicy {
    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
        match self {
            Self::Allow => write!(f, "allow"),
            Self::Warn => write!(f, "warn"),
            Self::Deny => write!(f, "deny"),
        }
    }
}

#[derive(Debug, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
/// Migration action applied when upgrading older configuration payloads.
pub enum ConfigMigrationKind {
    /// Renames one configuration path to another.
    Rename {
        /// Original path used by older configs.
        from: String,
        /// Replacement path used by newer configs.
        to: String,
    },
    /// Removes a configuration path that is no longer supported.
    Remove {
        /// Path removed from newer configs.
        path: String,
    },
}

#[derive(Debug, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
/// Declarative migration rule applied to loaded configuration values.
pub struct ConfigMigration {
    /// Version introduced by this migration rule.
    pub since_version: u32,
    /// Concrete migration action.
    pub kind: ConfigMigrationKind,
    /// Optional operator-facing migration note.
    pub note: Option<String>,
}

impl ConfigMigration {
    /// Creates a rename migration from `from` to `to`.
    #[must_use]
    pub fn rename(from: impl Into<String>, to: impl Into<String>, since_version: u32) -> Self {
        Self {
            since_version,
            kind: ConfigMigrationKind::Rename {
                from: from.into(),
                to: to.into(),
            },
            note: None,
        }
    }

    /// Creates a removal migration for `path`.
    #[must_use]
    pub fn remove(path: impl Into<String>, since_version: u32) -> Self {
        Self {
            since_version,
            kind: ConfigMigrationKind::Remove { path: path.into() },
            note: None,
        }
    }

    /// Attaches an operator-facing migration note.
    #[must_use]
    pub fn with_note(mut self, note: impl Into<String>) -> Self {
        self.note = Some(note.into());
        self
    }
}