bookkeeper_client/
error.rs1use std::fmt::{self, Debug, Display, Formatter};
2use std::sync::Arc;
3
4#[derive(Clone, Debug)]
5enum Message {
6 None,
7 Static(&'static &'static str),
8 Dynamic(Box<str>),
9}
10
11#[derive(Clone, Debug)]
13pub struct Error<T: Clone + Debug + Display> {
14 kind: T,
15 message: Message,
16 cause: Option<Arc<dyn std::error::Error + Send + Sync + 'static>>,
17}
18
19impl<K> Error<K>
20where
21 K: Clone + Debug + Display,
22{
23 pub(crate) fn new(kind: K) -> Error<K> {
24 Error { kind, message: Message::None, cause: None }
25 }
26
27 pub(crate) fn with_description(kind: K, description: &'static &'static str) -> Error<K> {
28 Error { kind, message: Message::Static(description), cause: None }
29 }
30
31 pub(crate) fn with_message<S: Into<Box<str>>>(kind: K, message: S) -> Error<K> {
32 Error { kind, message: Message::Dynamic(message.into()), cause: None }
33 }
34
35 pub(crate) fn cause_by<E: std::error::Error + Send + Sync + 'static>(self, e: E) -> Self {
36 let cause = Arc::new(e);
37 Error { cause: Some(cause), ..self }
38 }
39
40 pub fn kind(&self) -> K {
42 self.kind.clone()
43 }
44}
45
46impl<K> Display for Error<K>
47where
48 K: Clone + Debug + Display,
49{
50 fn fmt(&self, f: &mut Formatter<'_>) -> std::result::Result<(), fmt::Error> {
51 match &self.message {
52 Message::None => write!(f, "{}", self.kind),
53 Message::Static(message) => write!(f, "{}: {}", self.kind, message),
54 Message::Dynamic(message) => write!(f, "{}: {}", self.kind, &message),
55 }
56 }
57}
58
59impl<K> std::error::Error for Error<K>
60where
61 K: Clone + Debug + Display,
62{
63 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
64 match &self.cause {
65 None => None,
66 Some(arced) => Some(arced.as_ref()),
67 }
68 }
69}