module/merge/context.rs
1use core::fmt::Display;
2
3use super::Error;
4use super::error::Trace;
5
6mod private {
7 pub trait Sealed {}
8}
9use self::private::Sealed;
10
11/// Extension trait for [`Result`].
12///
13/// Adds methods for adding context to an [`Error`].
14///
15/// This trait is **sealed** and cannot be implemented for any other types.
16///
17/// [`Error`]: super::Error
18pub trait Context: Sealed {
19 /// Add the name of this module to the context of the error.
20 ///
21 /// This method adds context to the [`Error`] so that it knows in which
22 /// module the error occurred. It is perfectly fine to never use it, as long
23 /// as you don't mind cryptic errors.
24 ///
25 /// Modules should be added in the following order, from the module where
26 /// the error occured and then its parent module up until the root module.
27 fn module<D>(self, name: D) -> Self
28 where
29 D: Display,
30 Self: Sized;
31
32 /// The same as [`Context::module`] but lazily-evaluated.
33 fn with_module<D>(self, f: impl FnOnce() -> D) -> Self
34 where
35 D: Display;
36
37 /// Set the trace of the error.
38 ///
39 /// This method overwrites the module trace completely with `trace`.
40 fn trace(self, trace: Trace) -> Self;
41
42 /// Set the trace of the error.
43 ///
44 /// The same as [`Context::trace`] but lazily-evaluated.
45 fn with_trace(self, f: impl FnOnce() -> Trace) -> Self;
46
47 /// Add the name of the value to the context of the error.
48 ///
49 /// This method adds context to the [`Error`] so that it knows in which
50 /// value the error occurred. It is perfectly fine to never use it, as long
51 /// as you don't mind cryptic errors.
52 fn value<D>(self, name: D) -> Self
53 where
54 D: Display,
55 Self: Sized;
56
57 /// The same as [`Context::value`] but lazily-evaluated.
58 fn with_value<D>(self, f: impl FnOnce() -> D) -> Self
59 where
60 D: Display,
61 Self: Sized;
62}
63
64impl<T> Sealed for core::result::Result<T, Error> {}
65
66impl<T> Context for core::result::Result<T, Error> {
67 fn module<D>(self, name: D) -> Self
68 where
69 D: Display,
70 Self: Sized,
71 {
72 self.with_module(|| name)
73 }
74
75 fn with_module<D>(self, f: impl FnOnce() -> D) -> Self
76 where
77 D: Display,
78 {
79 self.map_err(|mut e| {
80 e.trace.push_front(f());
81 e
82 })
83 }
84
85 fn trace(self, trace: Trace) -> Self {
86 self.with_trace(|| trace)
87 }
88
89 fn with_trace(self, f: impl FnOnce() -> Trace) -> Self {
90 self.map_err(|mut e| {
91 e.trace = f();
92 e
93 })
94 }
95
96 fn value<D>(self, name: D) -> Self
97 where
98 D: Display,
99 Self: Sized,
100 {
101 self.with_value(|| name)
102 }
103
104 fn with_value<D>(self, f: impl FnOnce() -> D) -> Self
105 where
106 D: Display,
107 Self: Sized,
108 {
109 self.map_err(|mut e| {
110 e.value.push_front(f());
111 e
112 })
113 }
114}