alma 0.1.1

A Bevy-native modal text editor with Vim-style navigation.
Documentation
//! Error taxonomy for buffer-owner ECS boundaries.

use crate::{
    ecs::events::{
        command::CommandFailureDiagnostic,
        operation::{OperationFailureClass, OperationFailureSource, OperationRetryAdvice},
    },
    fs_utils::FileWriteError,
    vim::VimError,
};

/// Structured command failure retained at the owner boundary.
#[derive(Debug)]
pub(super) enum BufferCommandError {
    /// A command failed with native Vim semantics.
    Vim(VimError),
    /// A write command failed after filesystem policy or persistence validation.
    Write(FileWriteError),
    /// Filesystem policy was not installed for a command that requires persistence.
    FilesystemUnavailable,
}

impl BufferCommandError {
    /// Returns the boundary class that determines disclosure and recovery.
    pub(super) const fn class(&self) -> OperationFailureClass {
        match self {
            Self::Vim(_) => OperationFailureClass::UserVisible,
            Self::Write(_) => OperationFailureClass::Persistence,
            Self::FilesystemUnavailable => OperationFailureClass::RuntimeConfig,
        }
    }

    /// Returns the safe Vim-facing status error.
    pub(super) const fn status_error(&self) -> VimError {
        match self {
            Self::Vim(error) => *error,
            Self::Write(_) | Self::FilesystemUnavailable => VimError::CantOpenFileForWriting,
        }
    }

    /// Returns the redacted diagnostic shape for production telemetry.
    pub(super) fn diagnostic(&self) -> CommandFailureDiagnostic {
        CommandFailureDiagnostic {
            class: self.class(),
            status_error: self.status_error(),
            source: self.source_shape(),
            retry: self.retry_advice(),
        }
    }

    /// Returns a redacted lower-boundary source shape.
    fn source_shape(&self) -> Option<OperationFailureSource> {
        match self {
            Self::Write(error) => Some(OperationFailureSource::from_file_write_error(error)),
            Self::Vim(_) | Self::FilesystemUnavailable => None,
        }
    }

    /// Returns the typed persistence failure, if one exists.
    pub(super) const fn write_error(&self) -> Option<&FileWriteError> {
        match self {
            Self::Write(error) => Some(error),
            Self::Vim(_) | Self::FilesystemUnavailable => None,
        }
    }

    /// Returns retry guidance for the same command request.
    pub(super) fn retry_advice(&self) -> OperationRetryAdvice {
        match self {
            Self::Write(error) => {
                OperationFailureSource::from_file_write_error(error).retry_advice()
            }
            Self::Vim(_) | Self::FilesystemUnavailable => OperationRetryAdvice::RetryAfterChange,
        }
    }
}