alma 0.1.1

A Bevy-native modal text editor with Vim-style navigation.
Documentation
//! Error taxonomy for application configuration loading and projection.

use crate::{
    fs_utils::{EscapedDisplayText, FilesystemConfigError},
    plugin::PluginRegistryError,
};
use std::{io, path::PathBuf};

/// Errors returned while loading external application configuration.
#[derive(Debug, thiserror::Error)]
#[non_exhaustive]
pub enum ConfigLoadError {
    /// The current process directory could not be read.
    #[error("failed to read current directory: {source}")]
    CurrentDir {
        /// Underlying I/O error.
        #[source]
        source: io::Error,
    },
    /// Reading an explicit config file failed.
    #[error("failed to read config {}: {source}", display_path(path))]
    Read {
        /// Config file path.
        path: PathBuf,
        /// Underlying I/O error.
        #[source]
        source: io::Error,
    },
    /// Config JSON could not be parsed.
    #[error("failed to parse config {}: {source}", display_path(path))]
    Parse {
        /// Config file path.
        path: PathBuf,
        /// Underlying parse error.
        #[source]
        source: serde_json::Error,
    },
    /// Config JSON did not satisfy Alma's schema.
    #[error("config {} failed schema validation: {message}", display_path(path))]
    Schema {
        /// Config file path.
        path: PathBuf,
        /// Stable validation failure text.
        message: String,
    },
    /// Schema construction failed.
    #[error("failed to compile config schema: {message}")]
    SchemaCompile {
        /// Underlying schema error.
        message: String,
    },
    /// Schema-valid config could not be deserialized into typed config.
    #[error("failed to deserialize config {}: {source}", display_path(path))]
    Deserialize {
        /// Config file path.
        path: PathBuf,
        /// Underlying deserialization error.
        #[source]
        source: serde_json::Error,
    },
    /// Plugin registry invariants failed after schema validation.
    #[error("config {} has invalid plugin registry: {source}", display_path(path))]
    PluginRegistry {
        /// Config file path.
        path: PathBuf,
        /// Underlying registry validation error.
        #[source]
        source: PluginRegistryError,
    },
}

/// Errors returned while projecting app config into runtime subsystem config.
#[derive(Debug, thiserror::Error)]
#[non_exhaustive]
pub enum ConfigProjectionError {
    /// Filesystem runtime config could not be built.
    #[error("{0}")]
    Filesystem(#[from] FilesystemConfigError),
}

/// Escapes a path for user-facing diagnostics.
fn display_path(path: &std::path::Path) -> String {
    EscapedDisplayText::from_path(path).as_str().to_owned()
}