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}