1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
//! Error types

use anomaly::{BoxError, Context};
use std::{
    fmt::{self, Display},
    ops::Deref,
};
use thiserror::Error;

/// Kinds of errors
#[derive(Copy, Clone, Debug, Error, Eq, PartialEq)]
pub enum ErrorKind {
    /// Malformed account or validator address
    #[error("address error")]
    Address,

    /// Invalid decimal value
    #[error("invalid decimal value")]
    Decimal,

    /// Input/output errors
    #[error("I/O error")]
    Io,

    /// Invalid field name
    #[error("unknown field name")]
    FieldName,

    /// Parse error
    #[error("parse error")]
    Parse,

    /// Signature error
    #[error("signature error")]
    Signature,

    /// Invalid type
    #[error("type error")]
    Type,
}

impl ErrorKind {
    /// Add context to an [`ErrorKind`]
    pub fn context(self, source: impl Into<BoxError>) -> Context<ErrorKind> {
        Context::new(self, Some(source.into()))
    }
}

/// Error type
#[derive(Debug)]
pub struct Error(Box<Context<ErrorKind>>);

impl Deref for Error {
    type Target = Context<ErrorKind>;

    fn deref(&self) -> &Context<ErrorKind> {
        &self.0
    }
}

impl Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "{}", self.0)
    }
}

impl std::error::Error for Error {
    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
        self.0.source()
    }
}

impl From<ErrorKind> for Error {
    fn from(kind: ErrorKind) -> Self {
        Context::new(kind, None).into()
    }
}

impl From<Context<ErrorKind>> for Error {
    fn from(context: Context<ErrorKind>) -> Self {
        Error(Box::new(context))
    }
}

impl From<ecdsa::signature::Error> for Error {
    fn from(err: ecdsa::signature::Error) -> Error {
        Context::new(ErrorKind::Signature, Some(err.into())).into()
    }
}

impl From<rust_decimal::Error> for Error {
    fn from(err: rust_decimal::Error) -> Error {
        Context::new(ErrorKind::Decimal, Some(err.into())).into()
    }
}

impl From<subtle_encoding::Error> for Error {
    fn from(err: subtle_encoding::Error) -> Error {
        Context::new(ErrorKind::Parse, Some(err.into())).into()
    }
}

impl From<toml::de::Error> for Error {
    fn from(err: toml::de::Error) -> Error {
        Context::new(ErrorKind::Parse, Some(err.into())).into()
    }
}