1use std::fmt;
2
3use crate::{AnyError, StackError, StackErrorExt, meta, stack_error};
4
5pub trait StackResultExt<T, E> {
7 #[track_caller]
9 fn context(self, context: impl fmt::Display) -> Result<T, AnyError>;
10
11 #[track_caller]
15 fn with_context<F, C>(self, context: F) -> Result<T, AnyError>
16 where
17 F: FnOnce(&E) -> C,
18 C: fmt::Display;
19}
20
21impl<T, E: StackError + 'static> StackResultExt<T, E> for Result<T, E> {
22 fn context(self, context: impl fmt::Display) -> Result<T, AnyError> {
23 match self {
24 Ok(v) => Ok(v),
25 Err(e) => Err(e.into_any().context(context)),
26 }
27 }
28
29 fn with_context<F, C>(self, context: F) -> Result<T, AnyError>
30 where
31 F: FnOnce(&E) -> C,
32 C: fmt::Display,
33 {
34 match self {
35 Ok(v) => Ok(v),
36 Err(e) => {
37 let context = context(&e);
38 Err(e.into_any().context(context))
39 }
40 }
41 }
42}
43
44pub trait StdResultExt<T, E> {
51 #[track_caller]
53 fn std_context(self, context: impl fmt::Display) -> Result<T, AnyError>;
54
55 #[track_caller]
59 fn with_std_context<F, C>(self, context: F) -> Result<T, AnyError>
60 where
61 F: FnOnce(&E) -> C,
62 C: fmt::Display;
63
64 #[track_caller]
71 fn anyerr(self) -> Result<T, AnyError>;
72}
73
74impl<T, E: std::error::Error + Send + Sync + 'static> StdResultExt<T, E> for Result<T, E> {
75 fn std_context(self, context: impl fmt::Display) -> Result<T, AnyError> {
76 match self {
77 Ok(v) => Ok(v),
78 Err(e) => Err(AnyError::from_std(e).context(context)),
79 }
80 }
81
82 fn with_std_context<F, C>(self, context: F) -> Result<T, AnyError>
83 where
84 F: FnOnce(&E) -> C,
85 C: fmt::Display,
86 {
87 match self {
88 Ok(v) => Ok(v),
89 Err(e) => {
90 let context = context(&e);
91 Err(AnyError::from_std(e).context(context))
92 }
93 }
94 }
95
96 fn anyerr(self) -> Result<T, AnyError> {
97 match self {
98 Ok(v) => Ok(v),
99 Err(err) => Err(AnyError::from_std(err)),
100 }
101 }
102}
103
104impl<T> StdResultExt<T, NoneError> for Option<T> {
105 fn std_context(self, context: impl fmt::Display) -> Result<T, AnyError> {
106 match self {
107 Some(v) => Ok(v),
108 None => Err(NoneError { meta: meta() }.into_any().context(context)),
109 }
110 }
111
112 fn with_std_context<F, C>(self, context: F) -> Result<T, AnyError>
113 where
114 F: FnOnce(&NoneError) -> C,
115 C: fmt::Display,
116 {
117 match self {
118 Some(v) => Ok(v),
119 None => {
120 let err = NoneError { meta: meta() };
121 let context = context(&err);
122 Err(err.into_any().context(context))
123 }
124 }
125 }
126
127 fn anyerr(self) -> Result<T, AnyError> {
128 match self {
129 Some(v) => Ok(v),
130 None => Err(NoneError { meta: meta() }.into_any()),
131 }
132 }
133}
134
135impl<T> StackResultExt<T, NoneError> for Option<T> {
136 fn context(self, context: impl fmt::Display) -> Result<T, AnyError> {
137 match self {
138 Some(v) => Ok(v),
139 None => Err(NoneError { meta: meta() }.into_any().context(context)),
140 }
141 }
142
143 fn with_context<F, C>(self, context: F) -> Result<T, AnyError>
144 where
145 F: FnOnce(&NoneError) -> C,
146 C: fmt::Display,
147 {
148 match self {
149 Some(v) => Ok(v),
150 None => {
151 let err = NoneError { meta: meta() };
152 let context = context(&err);
153 Err(err.into_any().context(context))
154 }
155 }
156 }
157}
158
159#[stack_error(derive, add_meta)]
161#[error("Expected some, found none")]
162pub struct NoneError {}
163
164#[stack_error(derive, add_meta)]
166pub(crate) enum FromString {
167 #[error("{message}")]
168 WithSource { message: String, source: AnyError },
169 #[error("{message}")]
170 WithoutSource { message: String },
171}