1use error_stack::{Context, Report};
2use std::error::Error;
3use std::fmt::{Debug, Display, Formatter};
4
5pub struct HyperlitError(pub Report<HyperlitErrorContext>);
6
7pub struct HyperlitErrorContext {
8 pub context: Box<dyn Context>,
9}
10
11impl Debug for HyperlitError {
12 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
13 std::fmt::Debug::fmt(&self.0, f)
14 }
15}
16
17impl HyperlitErrorContext {
18 #[track_caller]
19 pub fn new<T: Context>(context: T) -> HyperlitErrorContext {
20 HyperlitErrorContext {
21 context: Box::new(context),
22 }
23 }
24
25 #[track_caller]
26 pub fn from_string<T: Into<String>>(message: T) -> HyperlitErrorContext {
27 HyperlitErrorContext {
28 context: Box::new(GeneralError {
29 message: message.into(),
30 }),
31 }
32 }
33}
34
35pub struct BoxedErrorContext {
36 pub error: BoxedError,
37}
38
39pub type BoxedError = Box<dyn Error + Send + Sync + 'static>;
40
41impl BoxedErrorContext {
42 #[track_caller]
43 pub fn new(error: BoxedError) -> BoxedErrorContext {
44 BoxedErrorContext { error }
45 }
46}
47
48impl Display for BoxedErrorContext {
49 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
50 std::fmt::Display::fmt(&self.error, f)
51 }
52}
53
54impl Debug for BoxedErrorContext {
55 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
56 std::fmt::Debug::fmt(&self.error, f)
57 }
58}
59
60impl Error for BoxedErrorContext {}
61
62impl HyperlitErrorContext {
63 pub fn from_context<T: Context>(context: T) -> HyperlitErrorContext {
64 HyperlitErrorContext {
65 context: Box::new(context),
66 }
67 }
68}
69
70impl Display for HyperlitErrorContext {
71 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
72 std::fmt::Display::fmt(&self.context, f)
73 }
74}
75
76impl Debug for HyperlitErrorContext {
77 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
78 std::fmt::Debug::fmt(&self.context, f)
79 }
80}
81
82impl Error for HyperlitErrorContext {}
83
84pub struct GeneralError {
85 pub message: String,
86}
87
88impl Display for GeneralError {
89 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
90 std::fmt::Display::fmt(&self.message, f)
91 }
92}
93
94impl Debug for GeneralError {
95 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
96 std::fmt::Debug::fmt(&self.message, f)
97 }
98}
99
100impl Error for GeneralError {}
101
102impl Display for HyperlitError {
103 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
104 std::fmt::Display::fmt(&self.0, f)
105 }
106}
107
108impl HyperlitError {
109 #[track_caller]
110 pub fn change_context<S: Into<String>>(self, message: S) -> Self {
111 Self(
112 self.0
113 .change_context(HyperlitErrorContext::from_string(message.into())),
114 )
115 }
116}
117
118impl HyperlitError {
119 #[track_caller]
120 pub fn new<T: Context>(error: T) -> HyperlitError {
121 HyperlitError(Report::new(HyperlitErrorContext::from_context(error)))
122 }
123
124 #[track_caller]
125 pub fn from_string<T: Into<String>>(message: T) -> HyperlitError {
126 HyperlitError(Report::new(HyperlitErrorContext::from_string(message)))
127 }
128
129 #[track_caller]
130 pub fn from_boxed(error: BoxedError) -> HyperlitErrorContext {
131 HyperlitErrorContext {
132 context: Box::new(BoxedErrorContext::new(error)),
133 }
134 }
135}
136
137impl<T: Context> From<T> for HyperlitError {
138 #[track_caller]
139 fn from(error: T) -> Self {
140 Self::new(error)
141 }
142}
143
144#[macro_export]
145macro_rules! bail {
146 ($($args:tt)+) => {
147 return Err($crate::err!($($args)+))
148 }
149}
150
151#[macro_export]
152macro_rules! err {
153 ($($args:tt)+) => {
154 $crate::error::HyperlitError::from_string(format!($($args)+))
155 };
156}