ex3-canister-error 0.17.3

Underlying error types used over ex3 core canisters.
Documentation
use derive_more::Display;
use ex3_common_error_info::ErrorInfo;
use std::fmt;
use thiserror::Error;

use crate::{def_error_base_on_kind, ErrorCode, ErrorKind, SECOND_LEVEL_ERROR_CODE_INTERVAL};

/// An error with no reason.
#[derive(Error, Debug, Clone, Copy)]
#[error("no reason is provided")]
pub struct SilentError;

/// An error with only a string as the reason.
#[derive(Error, Debug, Clone)]
#[error("{0}")]
pub struct OtherError(String);

#[derive(Debug, PartialEq, Eq, Clone, Copy, Display)]
pub enum CommonErrorKind {
    Pager,
    Authorize,
    /// Other system error
    Other,
}

impl ErrorCode for CommonErrorKind {
    fn error_code(&self) -> u32 {
        let parent_code = ErrorKind::error_code(&ErrorKind::Common);
        match self {
            CommonErrorKind::Pager => parent_code + SECOND_LEVEL_ERROR_CODE_INTERVAL * 1,
            CommonErrorKind::Authorize => parent_code + SECOND_LEVEL_ERROR_CODE_INTERVAL * 2,
            CommonErrorKind::Other => parent_code + SECOND_LEVEL_ERROR_CODE_INTERVAL * 3,
        }
    }
}

def_error_base_on_kind!(CommonError, CommonErrorKind, "Common error.");

impl OtherError {
    /// Creates an error with only a string as the reason.
    pub fn new<T>(reason: T) -> Self
    where
        T: fmt::Display,
    {
        Self(reason.to_string())
    }
}

impl From<OtherError> for ErrorInfo {
    fn from(value: OtherError) -> Self {
        ErrorInfo {
            code: CommonErrorKind::error_code(&CommonErrorKind::Other),
            message: value.0,
        }
    }
}

impl From<OtherError> for CommonError {
    fn from(error: OtherError) -> Self {
        let error_info: ErrorInfo = error.into();
        CommonErrorKind::Other.because(error_info)
    }
}