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