ledvar-core 0.1.0

Reference implementation of the Ledvar protocol: data model, canonical content-addressed hashing, and well-formedness.
Documentation
//! Error type for the core. Hand-rolled (no `thiserror`) to keep the dependency
//! surface minimal — this crate is embedded by every higher layer.

use std::fmt;

/// Why a snapshot is not well-formed, or a version cannot be parsed.
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Error {
    /// `protocol_version` is not a parseable `MAJOR.MINOR.PATCH`.
    BadVersion(String),
    /// The snapshot's MAJOR differs from [`crate::SUPPORTED_PROTOCOL_MAJOR`].
    UnsupportedMajor(u64),
    /// The snapshot's MINOR differs from [`crate::SUPPORTED_PROTOCOL_MINOR`]. Only
    /// enforced while MAJOR is 0, where a MINOR bump may move the canonical form (SPEC §10).
    UnsupportedMinor(u64),
    /// A node at the given index has an empty `path`.
    EmptyPath(usize),
    /// A node at the given index has an empty segment in its `path` (`[""]`).
    EmptyPathSegment(usize),
    /// A node at the given index has an empty attribute name (`{"":[…]}`).
    EmptyAttrName(usize),
    /// A node (index) has an attribute (name) that maps to an empty value set (`{"a":[]}`).
    EmptyValueSet(usize, String),
    /// Two nodes share the same identity (path) within one snapshot.
    DuplicatePath(Vec<String>),
}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            Error::BadVersion(v) => write!(f, "protocol_version is not MAJOR.MINOR.PATCH: {v:?}"),
            Error::UnsupportedMajor(m) => write!(
                f,
                "unsupported protocol MAJOR {m} (this implementation supports {})",
                crate::SUPPORTED_PROTOCOL_MAJOR
            ),
            Error::UnsupportedMinor(m) => write!(
                f,
                "unsupported protocol MINOR {m} while MAJOR is 0 (this implementation supports 0.{})",
                crate::SUPPORTED_PROTOCOL_MINOR
            ),
            Error::EmptyPath(i) => write!(f, "node at index {i} has an empty path"),
            Error::EmptyPathSegment(i) => write!(f, "node at index {i} has an empty path segment"),
            Error::EmptyAttrName(i) => write!(f, "node at index {i} has an empty attribute name"),
            Error::EmptyValueSet(i, name) => {
                write!(f, "node at index {i}: attribute {name:?} has an empty value set")
            }
            Error::DuplicatePath(p) => write!(f, "duplicate node path within snapshot: {p:?}"),
        }
    }
}

impl std::error::Error for Error {}