katra-core 0.1.0

Katra3D core: shared vocabulary, error model, event model, IDs, and policy types.
Documentation
//! The Katra error model.
//!
//! Errors are **categories**, not strings. Every failure mode maps to one
//! category so that policy code (fallback, promotion gates, budgets) can
//! switch on the category without parsing messages.
//!
//! See `docs/standards/error-model.md` for the full policy.

use std::fmt;

/// Result alias used across Katra3D.
pub type Result<T, E = KatraError> = core::result::Result<T, E>;

/// Coarse error category. Policy decisions must only depend on this, never
/// on the human-readable message.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum ErrorCategory {
    /// A caller passed an invalid argument.
    InvalidArgument,
    /// The requested operation is not supported in this build/backend.
    NotSupported,
    /// A budget (memory, bandwidth, ring depth, ...) was exceeded.
    OutOfBudget,
    /// An I/O operation failed.
    Io,
    /// A protocol/serialization violation (trace format, message framing).
    Protocol,
    /// A resource was not found.
    NotFound,
    /// A resource already exists.
    AlreadyExists,
    /// Data is corrupt (cache index, trace, archive).
    Corrupt,
    /// An operation timed out.
    Timeout,
    /// A synchronization invariant was violated.
    Sync,
    /// A fallback implementation was requested but is unavailable.
    FallbackUnavailable,
    /// An internal invariant was violated (a Katra bug).
    Internal,
}

/// The unified Katra error type.
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum KatraError {
    /// Invalid argument; the `&'static str` names the argument.
    InvalidArgument(&'static str),
    /// Operation not supported; the message names the capability.
    NotSupported(String),
    /// A budget was exceeded.
    OutOfBudget {
        /// Budget name, e.g. `"staging_bytes"`.
        resource: &'static str,
        /// Amount requested.
        requested: u64,
        /// Amount available.
        available: u64,
    },
    /// I/O failure.
    Io(std::io::ErrorKind, String),
    /// Protocol violation (trace format, ABI framing).
    Protocol(String),
    /// Resource not found.
    NotFound(String),
    /// Resource already exists.
    AlreadyExists(String),
    /// Corrupt data.
    Corrupt(String),
    /// Timeout.
    Timeout {
        /// What timed out.
        what: &'static str,
        /// Timeout in nanoseconds.
        timeout_ns: u64,
    },
    /// Synchronization invariant violation.
    Sync(String),
    /// Fallback unavailable.
    FallbackUnavailable(&'static str),
    /// Internal invariant violation.
    Internal(&'static str),
}

impl KatraError {
    /// The coarse category of this error.
    pub fn category(&self) -> ErrorCategory {
        match self {
            KatraError::InvalidArgument(_) => ErrorCategory::InvalidArgument,
            KatraError::NotSupported(_) => ErrorCategory::NotSupported,
            KatraError::OutOfBudget { .. } => ErrorCategory::OutOfBudget,
            KatraError::Io(..) => ErrorCategory::Io,
            KatraError::Protocol(_) => ErrorCategory::Protocol,
            KatraError::NotFound(_) => ErrorCategory::NotFound,
            KatraError::AlreadyExists(_) => ErrorCategory::AlreadyExists,
            KatraError::Corrupt(_) => ErrorCategory::Corrupt,
            KatraError::Timeout { .. } => ErrorCategory::Timeout,
            KatraError::Sync(_) => ErrorCategory::Sync,
            KatraError::FallbackUnavailable(_) => ErrorCategory::FallbackUnavailable,
            KatraError::Internal(_) => ErrorCategory::Internal,
        }
    }
}

impl fmt::Display for KatraError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            KatraError::InvalidArgument(a) => write!(f, "invalid argument: {a}"),
            KatraError::NotSupported(c) => write!(f, "not supported: {c}"),
            KatraError::OutOfBudget { resource, requested, available } => write!(
                f,
                "budget exceeded for {resource}: requested {requested}, available {available}"
            ),
            KatraError::Io(kind, msg) => write!(f, "io error ({kind}): {msg}"),
            KatraError::Protocol(msg) => write!(f, "protocol violation: {msg}"),
            KatraError::NotFound(msg) => write!(f, "not found: {msg}"),
            KatraError::AlreadyExists(msg) => write!(f, "already exists: {msg}"),
            KatraError::Corrupt(msg) => write!(f, "corrupt data: {msg}"),
            KatraError::Timeout { what, timeout_ns } => {
                write!(f, "timeout on {what} after {timeout_ns} ns")
            }
            KatraError::Sync(msg) => write!(f, "synchronization violation: {msg}"),
            KatraError::FallbackUnavailable(s) => write!(f, "fallback unavailable: {s}"),
            KatraError::Internal(msg) => write!(f, "internal error: {msg}"),
        }
    }
}

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

impl From<std::io::Error> for KatraError {
    fn from(e: std::io::Error) -> Self {
        KatraError::Io(e.kind(), e.to_string())
    }
}