1use std::{error::Error, fmt};
2
3use crate::{Error2, ErrorWrap, Location};
4
5#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
6pub struct NoneError;
7
8impl fmt::Display for NoneError {
9 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10 write!(f, "NoneError")
11 }
12}
13
14impl Error for NoneError {}
15
16pub trait OptionExt<T>: Sized {
17 #[track_caller]
18 fn context<C, E>(self, context: C) -> Result<T, E>
19 where
20 C: ErrorWrap<NoneError, E>,
21 E: Error2,
22 {
23 self.context_and_location(context, Location::caller())
24 }
25
26 fn context_and_location<C, E>(self, context: C, location: Location) -> Result<T, E>
27 where
28 C: ErrorWrap<NoneError, E>,
29 E: Error2;
30
31 #[track_caller]
32 fn with_context<F, C, E>(self, f: F) -> Result<T, E>
33 where
34 F: FnOnce() -> C,
35 C: ErrorWrap<NoneError, E>,
36 E: Error2,
37 {
38 self.with_context_and_location(f, Location::caller())
39 }
40
41 fn with_context_and_location<F, C, E>(self, f: F, location: Location) -> Result<T, E>
42 where
43 F: FnOnce() -> C,
44 C: ErrorWrap<NoneError, E>,
45 E: Error2;
46}
47
48impl<T> OptionExt<T> for Option<T> {
49 fn context_and_location<C, E>(self, context: C, location: Location) -> Result<T, E>
50 where
51 C: ErrorWrap<NoneError, E>,
52 E: Error2,
53 {
54 match self {
55 Some(t) => Ok(t),
56 None => Err(context.wrap(NoneError, location)),
57 }
58 }
59
60 fn with_context_and_location<F, C, E>(self, f: F, location: Location) -> Result<T, E>
61 where
62 F: FnOnce() -> C,
63 C: ErrorWrap<NoneError, E>,
64 E: Error2,
65 {
66 match self {
67 Some(t) => Ok(t),
68 None => {
69 let context = f();
70 Err(context.wrap(NoneError, location))
71 }
72 }
73 }
74}