1use std::error::Error;
2
3use crate::StringError;
4use crate::{ErrorAttachment, ErrorReport, ErrorSensitivityLabel};
5
6pub trait ResultExt {
27 type Ok;
29
30 #[track_caller]
33 fn change_context<E: Error + Sized + Send + Sync + 'static>(
34 self,
35 error: E,
36 ) -> core::result::Result<Self::Ok, ErrorReport>;
37
38 #[track_caller]
40 fn error_attach<S: Into<String>>(
41 self,
42 key_name: S,
43 attachment: ErrorSensitivityLabel<ErrorAttachment>,
44 ) -> Result<Self::Ok, ErrorReport>;
45
46 #[track_caller]
48 fn error_attach_public_string<S: Into<String>>(
49 self,
50 key_name: S,
51 attachment: String,
52 ) -> Result<Self::Ok, ErrorReport>;
53
54 #[track_caller]
56 fn unwrap_error(self) -> Self::Ok;
57
58 #[track_caller]
60 fn expect_error(self, msg: &str) -> Self::Ok;
61}
62
63impl<T, E> ResultExt for core::result::Result<T, E>
64where
65 E: Error + Sized + Send + Sync + 'static,
66{
67 type Ok = T;
68
69 #[track_caller]
70 fn change_context<R: Error + Sized + Send + Sync + 'static>(
71 self,
72 error: R,
73 ) -> Result<T, ErrorReport> {
74 match self {
76 Ok(ok) => Ok(ok),
77 Err(err) => Err(ErrorReport::from_error(err).push_error(error)),
78 }
79 }
80
81 #[track_caller]
82 fn error_attach<S: Into<String>>(
83 self,
84 key_name: S,
85 attachment: ErrorSensitivityLabel<ErrorAttachment>,
86 ) -> Result<T, ErrorReport> {
87 match self {
89 Ok(ok) => Ok(ok),
90 Err(err) => Err(ErrorReport::from_error(err).attach(key_name, attachment)),
91 }
92 }
93
94 #[track_caller]
95 fn error_attach_public_string<S: Into<String>>(
96 self,
97 key_name: S,
98 attachment: String,
99 ) -> Result<T, ErrorReport> {
100 match self {
102 Ok(ok) => Ok(ok),
103 Err(err) => {
104 Err(ErrorReport::from_error(err).attach_public_string(key_name, attachment))
105 }
106 }
107 }
108
109 #[track_caller]
110 fn unwrap_error(self) -> T {
111 match self {
112 Ok(t) => t,
113 Err(e) => std::panic::panic_any(ErrorReport::from_error(e).push_error(
114 StringError::new("Called `ResultExt::unwrap_error()` on an `Err` value"),
115 )),
116 }
117 }
118
119 #[track_caller]
120 fn expect_error(self, msg: &str) -> T {
121 match self {
122 Ok(t) => t,
123 Err(e) => std::panic::panic_any(
124 ErrorReport::from_error(e)
125 .push_error(StringError::new(msg))
126 .attach(
127 "function_call",
128 ErrorSensitivityLabel::Public(ErrorAttachment::String(
129 "ResultExt::expect_error".to_owned(),
130 )),
131 ),
132 ),
133 }
134 }
135}
136
137impl<T> ResultExt for core::result::Result<T, ErrorReport> {
138 type Ok = T;
139
140 #[track_caller]
141 fn change_context<R: Error + Sized + Send + Sync + 'static>(
142 self,
143 error: R,
144 ) -> Result<T, ErrorReport> {
145 match self {
147 Ok(ok) => Ok(ok),
148 Err(err) => Err(err.push_error(error)),
149 }
150 }
151
152 #[track_caller]
153 fn error_attach<S: Into<String>>(
154 self,
155 key_name: S,
156 attachment: ErrorSensitivityLabel<ErrorAttachment>,
157 ) -> Result<T, ErrorReport> {
158 match self {
160 Ok(ok) => Ok(ok),
161 Err(err) => Err(err.attach(key_name, attachment)),
162 }
163 }
164
165 #[track_caller]
166 fn error_attach_public_string<S: Into<String>>(
167 self,
168 key_name: S,
169 attachment: String,
170 ) -> Result<T, ErrorReport> {
171 match self {
173 Ok(ok) => Ok(ok),
174 Err(err) => Err(err.attach(
175 key_name,
176 ErrorSensitivityLabel::Public(ErrorAttachment::String(attachment)),
177 )),
178 }
179 }
180
181 #[track_caller]
182 fn unwrap_error(self) -> T {
183 match self {
184 Ok(t) => t,
185 Err(e) => std::panic::panic_any(e.push_error(StringError::new(
186 "Called `ResultExt::unwrap_error()` on an `Err` value",
187 ))),
188 }
189 }
190
191 #[track_caller]
192 fn expect_error(self, msg: &str) -> T {
193 match self {
194 Ok(t) => t,
195 Err(e) => std::panic::panic_any(e.push_error(StringError::new(msg)).attach(
196 "function_call",
197 ErrorSensitivityLabel::Public(ErrorAttachment::String(
198 "ResultExt::expect_error".to_owned(),
199 )),
200 )),
201 }
202 }
203}
204
205impl<T> ResultExt for std::option::Option<T> {
206 type Ok = T;
207
208 #[track_caller]
209 fn change_context<R: Error + Sized + Send + Sync + 'static>(
210 self,
211 error: R,
212 ) -> Result<T, ErrorReport> {
213 match self {
215 Some(ok) => Ok(ok),
216 None => Err(ErrorReport::from_error(StringError::new(
217 "Called `Option::change_context()` (Part of trait: `ResultExt`) on a `None` value",
218 ))
219 .push_error(error)),
220 }
221 }
222
223 #[track_caller]
224 fn error_attach<S: Into<String>>(
225 self,
226 key_name: S,
227 attachment: ErrorSensitivityLabel<ErrorAttachment>,
228 ) -> Result<T, ErrorReport> {
229 match self {
231 Some(ok) => Ok(ok),
232 None => Err(ErrorReport::from_error(StringError::new(
233 "Called `Option::error_attach()` (Part of trait: `ResultExt`) on a `None` value",
234 ))
235 .attach(key_name, attachment)),
236 }
237 }
238
239 #[track_caller]
240 fn error_attach_public_string<S: Into<String>>(
241 self,
242 key_name: S,
243 attachment: String,
244 ) -> Result<T, ErrorReport> {
245 match self {
247 Some(ok) => Ok(ok),
248 None => Err(ErrorReport::from_error(StringError::new(
249 "Called `Option::error_attach_public_string()` (Part of trait: `ResultExt`) on a `None` value",
250 ))
251 .attach(
252 key_name,
253 ErrorSensitivityLabel::Public(ErrorAttachment::String(attachment)),
254 )),
255 }
256 }
257
258 #[track_caller]
259 fn unwrap_error(self) -> T {
260 match self {
261 Some(t) => t,
262 None => std::panic::panic_any(ErrorReport::from_error(StringError::new(
263 "Called `Option::unwrap_error()` (Part of trait: `ResultExt`) on a `None` value",
264 ))),
265 }
266 }
267
268 #[track_caller]
269 fn expect_error(self, msg: &str) -> T {
270 match self {
271 Some(t) => t,
272 None => std::panic::panic_any(ErrorReport::from_error(StringError::new(msg)).attach(
273 "function_call",
274 ErrorSensitivityLabel::Public(ErrorAttachment::String(
275 "ResultExt::expect_error".to_owned(),
276 )),
277 )),
278 }
279 }
280}