ledvar-diff 0.1.0

Optional companion standard for the Ledvar protocol: representing the comparison (diff) of two snapshots.
Documentation
//! The five exhaustive comparison outcomes (DIFF.md §2).

use serde::{Deserialize, Serialize};

/// The relationship of a node to its prior state. Exhaustive and mutually
/// exclusive: every node is exactly one, and there is no sixth case.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum StateStatus {
    /// No previous snapshot (cold start).
    Baseline,
    /// Present in current, not in previous.
    Added,
    /// Present in previous, not in current.
    Removed,
    /// Present in both, same `content_hash`.
    Unchanged,
    /// Present in both, different `content_hash`.
    Modified,
}

impl StateStatus {
    /// A real change relative to the previous state (`Added`, `Removed`, `Modified`).
    /// `Baseline` and `Unchanged` are not drift.
    pub fn is_drift(self) -> bool {
        matches!(
            self,
            StateStatus::Added | StateStatus::Removed | StateStatus::Modified
        )
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn drift_classification() {
        assert!(StateStatus::Added.is_drift());
        assert!(StateStatus::Removed.is_drift());
        assert!(StateStatus::Modified.is_drift());
        assert!(!StateStatus::Unchanged.is_drift());
        assert!(!StateStatus::Baseline.is_drift());
    }

    #[test]
    fn every_status_serializes_to_its_name() {
        // The five names are the companion standard's vocabulary (DIFF.md §2) — pin the wire form.
        for (status, name) in [
            (StateStatus::Baseline, "\"Baseline\""),
            (StateStatus::Added, "\"Added\""),
            (StateStatus::Removed, "\"Removed\""),
            (StateStatus::Unchanged, "\"Unchanged\""),
            (StateStatus::Modified, "\"Modified\""),
        ] {
            assert_eq!(serde_json::to_string(&status).unwrap(), name);
        }
    }
}