1use std::{
2 borrow::Cow,
3 fmt::{self, Display, Formatter},
4};
5
6#[derive(Debug)]
8pub struct Error {
9 msg: Cow<'static, str>,
10 cause: Option<Box<dyn std::error::Error + Send + Sync>>,
11}
12
13impl Error {
14 pub fn from_msg<T>(msg: T) -> Self
16 where
17 T: Into<String>,
18 {
19 Self {
20 msg: Cow::Owned(msg.into()),
21 cause: None,
22 }
23 }
24
25 #[inline]
27 pub const fn from_static_msg(msg: &'static str) -> Self {
28 Self {
29 msg: Cow::Borrowed(msg),
30 cause: None,
31 }
32 }
33
34 pub fn from_msg_and_cause<T, E>(msg: T, err: E) -> Self
36 where
37 T: Into<String>,
38 E: Into<Box<dyn std::error::Error + Send + Sync>>,
39 {
40 Self {
41 msg: Cow::Owned(msg.into()),
42 cause: Some(err.into()),
43 }
44 }
45
46 pub fn from_static_msg_and_cause<E>(msg: &'static str, err: E) -> Self
48 where
49 E: Into<Box<dyn std::error::Error + Send + Sync>>,
50 {
51 Self {
52 msg: Cow::Borrowed(msg),
53 cause: Some(err.into()),
54 }
55 }
56
57 pub fn from_cause<E>(err: E) -> Self
59 where
60 E: Into<Box<dyn std::error::Error + Send + Sync>>,
61 {
62 Self {
63 msg: Cow::Borrowed(""),
64 cause: Some(err.into()),
65 }
66 }
67}
68
69impl std::error::Error for Error {
70 #[inline]
71 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
72 self.cause.as_ref().map(|err| &**err as _)
73 }
74}
75
76impl Display for Error {
77 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
78 if let Some(cause) = self.cause.as_ref() {
79 if self.msg.is_empty() {
80 Display::fmt(cause, f)
81 } else {
82 write!(f, "{}: {}", self.msg, cause)
83 }
84 } else if self.msg.is_empty() {
85 f.write_str("unknown error")
86 } else {
87 f.write_str(&self.msg)
88 }
89 }
90}