1use std::{
2 collections::HashMap,
3};
4use crate::{
5 entry::{
6 err,
7 err_with,
8 },
9 types::{
10 Error,
11 Error_,
12 },
13 Level,
14 Log,
15};
16
17pub trait ErrContext {
19 fn context(self, message: impl ToString) -> Error;
22
23 fn context_with(self, message: impl ToString, attrs: impl Fn(&mut HashMap<&'static str, String>) -> ()) -> Error;
26
27 fn stack_context(self, log: &Log, message: impl ToString) -> Error;
30
31 fn stack_context_with(
34 self,
35 log: &Log,
36 message: impl ToString,
37 attrs: impl Fn(&mut HashMap<&'static str, String>) -> (),
38 ) -> Error;
39}
40
41impl<T: Into<Error>> ErrContext for T {
42 fn context(self, message: impl ToString) -> Error {
43 return Error(Box::new(Error_ {
44 message: message.to_string(),
45 attrs: HashMap::new(),
46 context: vec![],
47 causes: vec![self.into()],
48 incidental: vec![],
49 }));
50 }
51
52 fn context_with(
53 self,
54 message: impl ToString,
55 attrs: impl Fn(&mut HashMap<&'static str, String>) -> (),
56 ) -> Error {
57 let mut new_attrs = HashMap::new();
58 attrs(&mut new_attrs);
59 return Error(Box::new(Error_ {
60 message: message.to_string(),
61 attrs: new_attrs,
62 context: vec![],
63 causes: vec![self.into()],
64 incidental: vec![],
65 }));
66 }
67
68 fn stack_context(self, log: &Log, message: impl ToString) -> Error {
69 return Error(Box::new(Error_ {
70 message: message.to_string(),
71 attrs: HashMap::new(),
72 context: vec![log.clone()],
73 causes: vec![self.into()],
74 incidental: vec![],
75 }));
76 }
77
78 fn stack_context_with(
79 self,
80 log: &Log,
81 message: impl ToString,
82 attrs: impl Fn(&mut HashMap<&'static str, String>) -> (),
83 ) -> Error {
84 let mut new_attrs = HashMap::new();
85 attrs(&mut new_attrs);
86 return Error(Box::new(Error_ {
87 message: message.to_string(),
88 attrs: new_attrs,
89 context: vec![log.clone()],
90 causes: vec![self.into()],
91 incidental: vec![],
92 }));
93 }
94}
95
96pub trait ResultContext<O> {
99 fn context(self, message: impl ToString) -> Result<O, Error>;
102
103 fn context_with(
106 self,
107 message: impl ToString,
108 attrs: impl Fn(&mut HashMap<&'static str, String>) -> (),
109 ) -> Result<O, Error>;
110
111 fn stack_context(self, log: &Log, message: impl ToString) -> Result<O, Error>;
114
115 fn stack_context_with(
119 self,
120 log: &Log,
121 message: impl ToString,
122 attrs: impl Fn(&mut HashMap<&'static str, String>) -> (),
123 ) -> Result<O, Error>;
124
125 fn also<O2, E: Into<Error>>(self, r: Result<O2, E>) -> Result<O, Error>;
129
130 fn log(self, log: &Log, level: Level, message: impl ToString);
133
134 fn log_with(
137 self,
138 log: &Log,
139 level: Level,
140 message: impl ToString,
141 attrs: impl Fn(&mut HashMap<&'static str, String>) -> (),
142 );
143}
144
145impl<O, E: Into<Error>> ResultContext<O> for Result<O, E> {
146 fn context(self, message: impl ToString) -> Result<O, Error> {
147 match self {
148 Ok(x) => Ok(x),
149 Err(e) => Err(e.context(message)),
150 }
151 }
152
153 fn context_with(
154 self,
155 message: impl ToString,
156 attrs: impl Fn(&mut HashMap<&'static str, String>) -> (),
157 ) -> Result<O, Error> {
158 match self {
159 Ok(x) => Ok(x),
160 Err(e) => Err(e.context_with(message, attrs)),
161 }
162 }
163
164 fn stack_context(self, log: &Log, message: impl ToString) -> Result<O, Error> {
165 match self {
166 Ok(x) => Ok(x),
167 Err(e) => Err(e.stack_context(log, message)),
168 }
169 }
170
171 fn stack_context_with(
172 self,
173 log: &Log,
174 message: impl ToString,
175 attrs: impl Fn(&mut HashMap<&'static str, String>) -> (),
176 ) -> Result<O, Error> {
177 match self {
178 Ok(x) => Ok(x),
179 Err(e) => Err(e.stack_context_with(log, message, attrs)),
180 }
181 }
182
183 fn also<O2, E2: Into<Error>>(self, r: Result<O2, E2>) -> Result<O, Error> {
184 match self {
185 Ok(o) => match r {
186 Ok(_) => {
187 return Ok(o);
188 },
189 Err(e2) => {
190 return Err(e2.into());
191 },
192 },
193 Err(e) => match r {
194 Ok(_) => return Err(e.into()),
195 Err(e2) => return Err(e.into().also(e2.into())),
196 },
197 }
198 }
199
200 fn log(self, log: &Log, level: Level, message: impl ToString) {
201 if let Err(e) = self.context(message) {
202 log.log_err(level, e);
203 }
204 }
205
206 fn log_with(
207 self,
208 log: &Log,
209 level: Level,
210 message: impl ToString,
211 attrs: impl Fn(&mut HashMap<&'static str, String>) -> (),
212 ) {
213 if let Err(e) = self.context_with(message, attrs) {
214 log.log_err(level, e);
215 }
216 }
217}
218
219impl<O> ResultContext<O> for Option<O> {
220 fn context(self, message: impl ToString) -> Result<O, Error> {
221 match self {
222 Some(x) => Ok(x),
223 None => Err(err(message)),
224 }
225 }
226
227 fn context_with(
228 self,
229 message: impl ToString,
230 attrs: impl Fn(&mut HashMap<&'static str, String>) -> (),
231 ) -> Result<O, Error> {
232 match self {
233 Some(x) => Ok(x),
234 None => Err(err_with(message, attrs)),
235 }
236 }
237
238 fn stack_context(self, log: &Log, message: impl ToString) -> Result<O, Error> {
239 match self {
240 Some(x) => Ok(x),
241 None => Err(log.err(message)),
242 }
243 }
244
245 fn stack_context_with(
246 self,
247 log: &Log,
248 message: impl ToString,
249 attrs: impl Fn(&mut HashMap<&'static str, String>) -> (),
250 ) -> Result<O, Error> {
251 match self {
252 Some(x) => Ok(x),
253 None => Err(log.err_with(message, attrs)),
254 }
255 }
256
257 fn also<O2, E2: Into<Error>>(self, r: Result<O2, E2>) -> Result<O, Error> {
258 match self {
259 Some(o) => match r {
260 Ok(_) => {
261 return Ok(o);
262 },
263 Err(e2) => {
264 return Err(e2.into());
265 },
266 },
267 None => match r {
268 Ok(_) => return Err(err("No value")),
269 Err(e2) => return Err(err("No value").also(e2.into())),
270 },
271 }
272 }
273
274 fn log(self, log: &Log, level: Level, message: impl ToString) {
275 if self.is_none() {
276 log.log_err(level, err("No value").context(message));
277 }
278 }
279
280 fn log_with(
281 self,
282 log: &Log,
283 level: Level,
284 message: impl ToString,
285 attrs: impl Fn(&mut HashMap<&'static str, String>) -> (),
286 ) {
287 if self.is_none() {
288 log.log_err(level, err("No value").context_with(message, attrs));
289 }
290 }
291}
292
293pub trait ResultIgnore {
294 fn ignore(self);
299}
300
301impl<T, E> ResultIgnore for Result<T, E> {
302 fn ignore(self) {
303 _ = self;
304 }
305}