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    #[track_caller]
40    fn to_gerr<C: Config, D>(self) -> Result<T, C, D>;
41}
42
43impl<T, E> ResultExt<T> for core::result::Result<T, E>
44where
45    E: Error + Send + Sync + 'static,
46{
47    #[inline]
48    #[track_caller]
49    fn context<C: Config, D>(
50        self,
51        id: C::Id,
52        message: impl Into<Cow<'static, str>>,
53    ) -> Result<T, C, D> {
54        let location = Location::caller();
55        self.map_err(|source| {
56            GErr::<C, D>::new_with_id_untracked(Some(id), message.into(), location)
57                .add_source(source)
58        })
59    }
60
61    #[inline]
62    #[track_caller]
63    fn context_auto<C: Config, D>(self, message: impl Into<Cow<'static, str>>) -> Result<T, C, D> {
64        let location = Location::caller();
65        self.map_err(|source| {
66            GErr::<C, D>::new_untracked(message.into(), location).add_source(source)
67        })
68    }
69
70    #[inline]
71    fn wrap_err<C: Config, D>(self, gerr: GErr<C, D>) -> Result<T, C, D> {
72        self.map_err(|err| gerr.add_source(err))
73    }
74
75    #[inline]
76    #[track_caller]
77    fn to_gerr<C: Config, D>(self) -> Result<T, C, D> {
78        let location = Location::caller();
79        self.map_err(|err| GErr::new_untracked(err.to_string(), location))
80    }
81}
82
83/// Result extension where `E` is GErr or any error implementing `Into<GErrSource>`.
84///
85/// Use this extension if you pass GErr or `Into<GErrSource>` from Result's E and want to keep the detail attributes.
86pub trait GResultExt<T, E>: sealed::Sealed {
87    /// Wrap `E` as GErr's source, where E is `Into<GErrSource>`, and id is manually-set.
88    #[track_caller]
89    fn gerr<C: Config, D>(
90        self,
91        id: C::Id,
92        message: impl Into<Cow<'static, str>>,
93    ) -> Result<T, C, D>;
94
95    /// Wrap `E` as GErr's source, where E is `Into<GErrSource>`, and id is auto-generated.
96    #[track_caller]
97    fn gerr_auto<C: Config, D>(self, message: impl Into<Cow<'static, str>>) -> Result<T, C, D>;
98
99    /// Wrap `E` inside GErr
100    #[track_caller]
101    fn wrap_gerr<C: Config, D>(self, gerr: GErr<C, D>) -> Result<T, C, D>;
102
103    /// Convert to another GErr
104    #[track_caller]
105    fn to<C2: Config, D2>(self) -> Result<T, C2, D2>;
106
107    /// Box `E`
108    fn boxed(self) -> core::result::Result<T, Box<E>>;
109}
110
111impl<T, E> GResultExt<T, E> for core::result::Result<T, E>
112where
113    E: Into<GErrSource> + Error + Send + Sync + 'static,
114{
115    #[inline]
116    #[track_caller]
117    fn gerr<C: Config, D>(
118        self,
119        id: C::Id,
120        message: impl Into<Cow<'static, str>>,
121    ) -> Result<T, C, D> {
122        let location = Location::caller();
123        self.map_err(|source| {
124            GErr::<C, D>::new_with_id_untracked(Some(id), message.into(), location)
125                .add_source_gerr(source)
126        })
127    }
128
129    #[inline]
130    #[track_caller]
131    fn gerr_auto<C: Config, D>(self, message: impl Into<Cow<'static, str>>) -> Result<T, C, D> {
132        let location = Location::caller();
133        self.map_err(|source| {
134            GErr::<C, D>::new_untracked(message.into(), location).add_source_gerr(source)
135        })
136    }
137
138    #[inline]
139    fn wrap_gerr<C: Config, D>(self, gerr: GErr<C, D>) -> Result<T, C, D> {
140        self.map_err(|err| gerr.add_source_gerr(err))
141    }
142
143    #[inline]
144    #[track_caller]
145    fn to<C2: Config, D2>(self) -> Result<T, C2, D2> {
146        let location = Location::caller();
147        self.map_err(|gerr| GErr::from_gerr_untracked(gerr, location))
148    }
149
150    #[inline]
151    fn boxed(self) -> core::result::Result<T, Box<E>> {
152        self.map_err(Box::new)
153    }
154}