1#![allow(unused_macros)]
9
10use core::fmt;
11use signatory::signature;
12
13use std::{
14 error::Error as StdError,
15 string::{String, ToString},
16};
17
18#[derive(Debug)]
20pub struct Error {
21 kind: ErrorKind,
22
23 description: Option<String>,
24}
25
26#[derive(Debug, Copy, Clone, PartialEq)]
28pub enum ErrorKind {
29 InvalidPrefix,
31 InvalidKeyLength,
33 VerifyError,
35 SignatureError,
37 ChecksumFailure,
39 CodecFailure,
41 IncorrectKeyType,
43 InvalidPayload,
45 InvalidSignatureLength,
47}
48
49#[macro_export]
52macro_rules! err {
53 ($variant:ident, $msg:expr) => {
54 $crate::error::Error::new(
55 $crate::error::ErrorKind::$variant,
56 Some($msg)
57 )
58 };
59 ($variant:ident, $fmt:expr, $($arg:tt)+) => {
60 err!($variant, &format!($fmt, $($arg)+))
61 };
62}
63
64impl ErrorKind {
65 pub fn as_str(self) -> &'static str {
66 match self {
67 ErrorKind::InvalidPrefix => "Invalid byte prefix",
68 ErrorKind::InvalidKeyLength => "Invalid key length",
69 ErrorKind::InvalidSignatureLength => "Invalid signature length",
70 ErrorKind::VerifyError => "Signature verification failure",
71 ErrorKind::ChecksumFailure => "Checksum match failure",
72 ErrorKind::CodecFailure => "Codec failure",
73 ErrorKind::SignatureError => "Signature failure",
74 ErrorKind::IncorrectKeyType => "Incorrect key type",
75 ErrorKind::InvalidPayload => "Invalid payload",
76 }
77 }
78}
79
80impl fmt::Display for ErrorKind {
81 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
82 write!(f, "{}", self.as_str())
83 }
84}
85
86impl Error {
87 pub fn new(kind: ErrorKind, description: Option<&str>) -> Self {
89 Error {
90 kind,
91 description: description.map(|desc| desc.to_string()),
92 }
93 }
94
95 pub fn kind(&self) -> ErrorKind {
99 self.kind
100 }
101}
102
103impl From<signature::Error> for Error {
105 fn from(source: signature::Error) -> Error {
106 err!(SignatureError, &format!("Signature error: {}", source))
107 }
108}
109
110impl From<data_encoding::DecodeError> for Error {
112 fn from(source: data_encoding::DecodeError) -> Error {
113 err!(CodecFailure, "Data encoding failure: {}", source)
114 }
115}
116
117impl StdError for Error {
118 fn description(&self) -> &str {
119 if let Some(ref desc) = self.description {
120 desc
121 } else {
122 self.kind.as_str()
123 }
124 }
125}
126
127impl fmt::Display for Error {
128 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
129 match self.description {
130 Some(ref desc) => write!(f, "{}: {}", self.kind.as_str(), desc),
131 None => write!(f, "{}", self.kind.as_str()),
132 }
133 }
134}
135
136#[cfg(test)]
137mod tests {
138 #[test]
139 fn test_error_to_string() {
140 assert_eq!(
141 err!(InvalidKeyLength, "Testing").to_string(),
142 "Invalid key length: Testing"
143 );
144 assert_eq!(
145 err!(InvalidKeyLength, "Testing {}", 1).to_string(),
146 "Invalid key length: Testing 1"
147 );
148 }
149}