Skip to main content

error_stack/
result.rs

1use core::error::Error;
2
3use crate::{Attachment, IntoReport, OpaqueAttachment, Report};
4
5/// Extension trait for [`Result`] to provide context information on
6/// [`Report`]s.
7pub trait ResultExt {
8    /// The context type of the [`Result`] which becomes the `C` in `Report<C>`.
9    type Context: ?Sized;
10
11    /// Type of the [`Ok`] value in the [`Result`].
12    type Ok;
13
14    /// Adds a new printable attachment to the [`Report`] inside the [`Result`].
15    ///
16    /// Applies [`Report::attach`] on the [`Err`] variant, refer to it for more
17    /// information.
18    fn attach<A>(self, attachment: A) -> Result<Self::Ok, Report<Self::Context>>
19    where
20        A: Attachment;
21
22    /// Lazily adds a new printable attachment to the [`Report`] inside the [`Result`].
23    ///
24    /// Applies [`Report::attach`] on the [`Err`] variant, refer to it for more
25    /// information.
26    fn attach_with<A, F>(self, attachment: F) -> Result<Self::Ok, Report<Self::Context>>
27    where
28        A: Attachment,
29        F: FnOnce() -> A;
30
31    /// Adds a new attachment to the [`Report`] inside the [`Result`].
32    ///
33    /// Applies [`Report::attach_opaque`] on the [`Err`] variant, refer to it for more information.
34    fn attach_opaque<A>(self, attachment: A) -> Result<Self::Ok, Report<Self::Context>>
35    where
36        A: OpaqueAttachment;
37
38    /// Lazily adds a new attachment to the [`Report`] inside the [`Result`].
39    ///
40    /// Applies [`Report::attach_opaque`] on the [`Err`] variant, refer to it for more information.
41    fn attach_opaque_with<A, F>(self, attachment: F) -> Result<Self::Ok, Report<Self::Context>>
42    where
43        A: OpaqueAttachment,
44        F: FnOnce() -> A;
45
46    /// Changes the context of the [`Report`] inside the [`Result`].
47    ///
48    /// Applies [`Report::change_context`] on the [`Err`] variant, refer to it for more information.
49    fn change_context<C>(self, context: C) -> Result<Self::Ok, Report<C>>
50    where
51        C: Error + Send + Sync + 'static;
52
53    /// Lazily changes the context of the [`Report`] inside the [`Result`].
54    ///
55    /// Applies [`Report::change_context`] on the [`Err`] variant, refer to it for more information.
56    fn change_context_lazy<C, F>(self, context: F) -> Result<Self::Ok, Report<C>>
57    where
58        C: Error + Send + Sync + 'static,
59        F: FnOnce() -> C;
60}
61
62impl<T, E> ResultExt for Result<T, E>
63where
64    E: IntoReport,
65{
66    type Context = E::Context;
67    type Ok = T;
68
69    #[track_caller]
70    fn attach<A>(self, attachment: A) -> Result<T, Report<E::Context>>
71    where
72        A: Attachment,
73    {
74        match self {
75            Ok(value) => Ok(value),
76            Err(error) => Err(error.into_report().attach(attachment)),
77        }
78    }
79
80    #[track_caller]
81    fn attach_with<A, F>(self, attachment: F) -> Result<T, Report<E::Context>>
82    where
83        A: Attachment,
84        F: FnOnce() -> A,
85    {
86        match self {
87            Ok(value) => Ok(value),
88            Err(error) => Err(error.into_report().attach(attachment())),
89        }
90    }
91
92    #[track_caller]
93    fn attach_opaque<A>(self, attachment: A) -> Result<T, Report<E::Context>>
94    where
95        A: OpaqueAttachment,
96    {
97        match self {
98            Ok(value) => Ok(value),
99            Err(error) => Err(error.into_report().attach_opaque(attachment)),
100        }
101    }
102
103    #[track_caller]
104    fn attach_opaque_with<A, F>(self, attachment: F) -> Result<T, Report<E::Context>>
105    where
106        A: OpaqueAttachment,
107        F: FnOnce() -> A,
108    {
109        match self {
110            Ok(value) => Ok(value),
111            Err(error) => Err(error.into_report().attach_opaque(attachment())),
112        }
113    }
114
115    #[track_caller]
116    fn change_context<C>(self, context: C) -> Result<T, Report<C>>
117    where
118        C: Error + Send + Sync + 'static,
119    {
120        match self {
121            Ok(value) => Ok(value),
122            Err(error) => Err(error.into_report().change_context(context)),
123        }
124    }
125
126    #[track_caller]
127    fn change_context_lazy<C, F>(self, context: F) -> Result<T, Report<C>>
128    where
129        C: Error + Send + Sync + 'static,
130        F: FnOnce() -> C,
131    {
132        match self {
133            Ok(value) => Ok(value),
134            Err(error) => Err(error.into_report().change_context(context())),
135        }
136    }
137}