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
use std::borrow::Cow;
use std::collections::HashMap;
use std::error::Error as StdError;
use std::fmt;
use crate::kinds::{tag_check, error_name};
use crate::traits::ErrorKind;
#[derive(Debug)]
pub struct Error(pub(crate) Box<Inner>);
pub struct Tag { pub(crate) bit: u32 }
#[derive(Debug)]
pub(crate) struct Inner {
pub code: u32,
pub messages: Vec<Cow<'static, str>>,
pub error: Option<Box<dyn StdError + Send + Sync + 'static>>,
pub headers: HashMap<u16, bytes::Bytes>,
}
impl Error {
pub fn is<T: ErrorKind>(&self) -> bool {
T::is_superclass_of(self.0.code)
}
pub fn has_tag(&self, tag: Tag) -> bool {
tag_check(self.0.code, tag.bit)
}
pub fn context<S: Into<Cow<'static, str>>>(mut self, msg: S) -> Error {
self.0.messages.push(msg.into());
self
}
pub fn headers(&self) -> &HashMap<u16, bytes::Bytes> {
&self.0.headers
}
pub fn with_headers(mut self, headers: HashMap<u16, bytes::Bytes>)
-> Error
{
self.0.headers = headers;
self
}
pub fn kind_name(&self) -> &str {
error_name(self.0.code)
}
pub fn kind_debug(&self) -> impl fmt::Display {
format!("{} [0x{:08X}]", error_name(self.0.code), self.0.code)
}
pub fn initial_message(&self) -> Option<&str> {
self.0.messages.first().map(|m| &m[..])
}
pub fn from_code(code: u32) -> Error {
Error(Box::new(Inner {
code,
messages: Vec::new(),
error: None,
headers: HashMap::new(),
}))
}
pub fn refine_kind<T: ErrorKind>(mut self) -> Error {
self.0.code = T::CODE;
self
}
}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let kind = self.kind_name();
if f.alternate() {
write!(f, "{}", kind)?;
for msg in self.0.messages.iter().rev() {
write!(f, ": {}", msg)?;
}
if let Some(mut src) = self.source() {
write!(f, ": {}", src)?;
while let Some(next) = src.source() {
write!(f, ": {}", next)?;
src = next;
}
}
} else {
if let Some(last) = self.0.messages.last() {
write!(f, "{}: {}", kind, last)?;
} else {
write!(f, "{}", kind)?;
}
}
Ok(())
}
}
impl StdError for Error {
fn source(&self) -> Option<&(dyn StdError + 'static)> {
self.0.error.as_ref().map(|b| b.as_ref() as &dyn std::error::Error)
}
}