translatable 1.0.0

A robust internationalization solution for Rust featuring compile-time validation, ISO 639-1 compliance, and TOML-based translation management.
Documentation
//! Runtime error module.
//!
//! This module contains all the runtime
//! errors that could be generated by
//! macro calls or user-facing helper
//! method invocations.

use thiserror::Error;
use translatable_shared::misc::language::Language;
use translatable_shared::translations::node::TranslationNodeError;

/// Macro runtime error handling.
///
/// Used in [`translation`] invocations for non
/// compile-time validations and errors.
///
/// Use the [`Display`] implementation to obtain the
/// error message, [`Self::cause`] is available as
/// a helper method for such purpose. Read it's
/// documentation before using.
///
/// [`translation`]: crate::translation
/// [`Display`]: std::fmt::Display
#[derive(Error, Debug)]
pub enum RuntimeError {
    /// Translation node error derivations.
    ///
    /// [`TranslationNode`] construction
    /// failure, usually nesting missmatch, invalid
    /// template validation...
    ///
    /// [`Display`] directly forwards the inner
    /// error [`Display`] value.
    ///
    /// The enum implements
    /// [`From<TranslationNodeError>`] to allow
    /// conversion from
    /// [`TranslationNodeError`].
    ///
    /// **Parameters**
    /// * `0` - The [`TranslationNodeError`] derivation.
    ///
    /// [`TranslationNode`]: crate::shared::translations::node::TranslationNode
    /// [`TranslationNodeError`]: crate::shared::translations::node::TranslationNodeError
    /// [`Display`]: std::fmt::Display
    #[error("{0:#}")]
    TranslationNode(#[from] TranslationNodeError),

    /// Dynamic path resolve error.
    ///
    /// The specified path may not be found
    /// in any of the translation files.
    ///
    /// This is not related to runtime language
    /// validity, check [`LanguageNotAvailable`]
    /// for that purpose.
    ///
    /// **Parameters**
    /// * `0` - The path that could not be found
    /// appended with it's separator.
    ///
    /// [`LanguageNotAvailable`]: crate::Error::LanguageNotAvailable
    #[error("The path '{0}' could not be found")]
    PathNotFound(String),

    /// Dynamic language obtention error.
    ///
    /// This specifically happens when a language
    /// is not available for a specific translation.
    ///
    /// Language parsing is delegated to the user,
    /// the language parameter must be a [`Language`],
    /// if it's a &[`str`] the validation is made in compile
    /// time. In that case we don't reach runtime.
    ///
    /// **Parameters**
    /// * `0` - The language that is not available.
    /// * `1` - The path for which the language is not available
    /// appended with it's separator.
    #[error("The language '{0:?}' ('{0:#}') is not available for the path '{1}'")]
    LanguageNotAvailable(Language, String),
}

impl RuntimeError {
    /// Runtime error display helper.
    ///
    /// This method is marked as `#[cold]`
    /// so it should be called lazily with
    /// monads such as [`ok_or_else`] or any
    /// other `or_else` method.
    ///
    /// **Returns**
    /// A heap allocated [`String`] containing
    /// the cause of the error.
    ///
    /// [`ok_or_else`]: std::option::Option::ok_or_else
    #[cold]
    #[inline]
    pub fn cause(&self) -> String {
        format!("{self:#}")
    }
}