Skip to main content

g_err/
result_ext.rs

1extern crate alloc;
2use alloc::boxed::Box;
3
4use crate::GErrSource;
5use crate::{
6    Config,
7    gerr::{GErr, Result},
8    sealed,
9};
10use core::error::Error;
11use core::panic::Location;
12
13use alloc::borrow::Cow;
14
15impl<T, E> sealed::Sealed for core::result::Result<T, E> {}
16
17/// Extension for Result wrapping `E` as any error.
18///
19/// This is for general error, including GErr itself.
20///
21/// Passing GErr will be parsed as general error.
22pub trait ResultExt<T>: sealed::Sealed {
23    /// Wrap `E` inside GErr as source with manually-set id.
24    #[track_caller]
25    fn context<C: Config, D>(
26        self,
27        id: C::Id,
28        message: impl Into<Cow<'static, str>>,
29    ) -> Result<T, C, D>;
30
31    /// Wrap `E` inside GErr as source with auto-generated id and code.
32    #[track_caller]
33    fn context_auto<C: Config, D>(self, message: impl Into<Cow<'static, str>>) -> Result<T, C, D>;
34
35    /// Wrap `E` inside GErr
36    #[track_caller]
37    fn wrap_err<C: Config, D>(self, gerr: GErr<C, D>) -> Result<T, C, D>;
38}
39
40impl<T, E> ResultExt<T> for core::result::Result<T, E>
41where
42    E: Error + Send + Sync + 'static,
43{
44    #[track_caller]
45    fn context<C: Config, D>(
46        self,
47        id: C::Id,
48        message: impl Into<Cow<'static, str>>,
49    ) -> Result<T, C, D> {
50        let location = Location::caller();
51        self.map_err(|source| {
52            GErr::<C, D>::new_with_id_untracked(Some(id), message.into(), location)
53                .add_source(source)
54        })
55    }
56
57    #[track_caller]
58    fn context_auto<C: Config, D>(self, message: impl Into<Cow<'static, str>>) -> Result<T, C, D> {
59        let location = Location::caller();
60        self.map_err(|source| {
61            GErr::<C, D>::new_untracked(message.into(), location).add_source(source)
62        })
63    }
64
65    #[track_caller]
66    fn wrap_err<C: Config, D>(self, gerr: GErr<C, D>) -> Result<T, C, D> {
67        self.map_err(|err| gerr.add_source(err))
68    }
69}
70
71/// Result extension where `E` is GErr or any error implementing `Into<GErrSource>`.
72///
73/// Use this extension if you pass GErr or `Into<GErrSource>` from Result's E and want to keep the detail attributes.
74pub trait GResultExt<T, E>: sealed::Sealed {
75    /// Wrap `E` as GErr's source, where E is `Into<GErrSource>`, and id is manually-set.
76    #[track_caller]
77    fn gerr<C: Config, D>(
78        self,
79        id: C::Id,
80        message: impl Into<Cow<'static, str>>,
81    ) -> Result<T, C, D>;
82
83    /// Wrap `E` as GErr's source, where E is `Into<GErrSource>`, and id is auto-generated.
84    #[track_caller]
85    fn gerr_auto<C: Config, D>(self, message: impl Into<Cow<'static, str>>) -> Result<T, C, D>;
86
87    /// Wrap `E` inside GErr
88    #[track_caller]
89    fn wrap_gerr<C: Config, D>(self, gerr: GErr<C, D>) -> Result<T, C, D>;
90
91    /// Box `E`
92    fn boxed(self) -> core::result::Result<T, Box<E>>;
93}
94
95impl<T, E> GResultExt<T, E> for core::result::Result<T, E>
96where
97    E: Into<GErrSource> + Error + Send + Sync + 'static,
98{
99    #[track_caller]
100    fn gerr<C: Config, D>(
101        self,
102        id: C::Id,
103        message: impl Into<Cow<'static, str>>,
104    ) -> Result<T, C, D> {
105        let location = Location::caller();
106        self.map_err(|source| {
107            GErr::<C, D>::new_with_id_untracked(Some(id), message.into(), location)
108                .add_source_gerr(source)
109        })
110    }
111
112    #[track_caller]
113    fn gerr_auto<C: Config, D>(self, message: impl Into<Cow<'static, str>>) -> Result<T, C, D> {
114        let location = Location::caller();
115        self.map_err(|source| {
116            GErr::<C, D>::new_untracked(message.into(), location).add_source_gerr(source)
117        })
118    }
119
120    /// Wrap `E` inside GErr
121    #[track_caller]
122    fn wrap_gerr<C: Config, D>(self, gerr: GErr<C, D>) -> Result<T, C, D> {
123        self.map_err(|err| gerr.add_source_gerr(err))
124    }
125
126    #[inline]
127    fn boxed(self) -> core::result::Result<T, Box<E>> {
128        self.map_err(Box::new)
129    }
130}