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