1use std::{error::Error, fmt, rc::Rc};
2
3use ntex_bytes::ByteString;
4
5pub fn fmt_err_string(e: &dyn Error) -> String {
6 let mut buf = String::new();
7 _ = fmt_err(&mut buf, e);
8 buf
9}
10
11pub fn fmt_err(f: &mut dyn fmt::Write, e: &dyn Error) -> fmt::Result {
12 let mut current = Some(e);
13 while let Some(std_err) = current {
14 writeln!(f, "{std_err}")?;
15 current = std_err.source();
16 }
17 Ok(())
18}
19
20#[derive(Debug, Clone, thiserror::Error, PartialEq, Eq)]
21pub struct ErrorMessage(ByteString);
22
23#[derive(Debug, Clone, thiserror::Error)]
24#[error("{msg}")]
25pub struct ErrorMessageChained {
26 msg: ByteString,
27 #[source]
28 source: Option<Rc<dyn Error>>,
29}
30
31impl ErrorMessageChained {
32 pub fn new<M, E>(ctx: M, source: E) -> Self
33 where
34 M: Into<ErrorMessage>,
35 E: Error + 'static,
36 {
37 ErrorMessageChained {
38 msg: ctx.into().into_string(),
39 source: Some(Rc::new(source)),
40 }
41 }
42
43 pub fn msg(&self) -> &ByteString {
44 &self.msg
45 }
46
47 pub fn source(&self) -> &Option<Rc<dyn Error>> {
48 &self.source
49 }
50}
51
52impl ErrorMessage {
53 pub const fn empty() -> Self {
54 Self(ByteString::from_static(""))
55 }
56
57 pub fn is_empty(&self) -> bool {
58 self.0.is_empty()
59 }
60
61 pub fn as_str(&self) -> &str {
62 &self.0
63 }
64
65 pub fn as_bstr(&self) -> &ByteString {
66 &self.0
67 }
68
69 pub fn into_string(self) -> ByteString {
70 self.0
71 }
72
73 pub fn with_source<E: Error + 'static>(self, source: E) -> ErrorMessageChained {
74 ErrorMessageChained::new(self, source)
75 }
76}
77
78impl From<String> for ErrorMessage {
79 fn from(value: String) -> Self {
80 Self(ByteString::from(value))
81 }
82}
83
84impl From<ByteString> for ErrorMessage {
85 fn from(value: ByteString) -> Self {
86 Self(value)
87 }
88}
89
90impl From<&'static str> for ErrorMessage {
91 fn from(value: &'static str) -> Self {
92 Self(ByteString::from_static(value))
93 }
94}
95
96impl fmt::Display for ErrorMessage {
97 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
98 self.0.fmt(f)
99 }
100}
101
102impl From<ErrorMessage> for ByteString {
103 fn from(msg: ErrorMessage) -> Self {
104 msg.0
105 }
106}
107
108impl<'a> From<&'a ErrorMessage> for ByteString {
109 fn from(msg: &'a ErrorMessage) -> Self {
110 msg.0.clone()
111 }
112}
113
114impl<M: Into<ErrorMessage>> From<M> for ErrorMessageChained {
115 fn from(value: M) -> Self {
116 ErrorMessageChained {
117 msg: value.into().0,
118 source: None,
119 }
120 }
121}