error_tools/
error.rs

1/// Internal namespace.
2mod private
3{
4  pub use std::error::Error as ErrorTrait;
5
6  /// This trait allows adding extra context or information to an error, creating a tuple of the additional
7  /// context and the original error. This is particularly useful for error handling when you want to include
8  /// more details in the error without losing the original error value.
9  ///
10  /// The `ErrWith` trait provides methods to wrap an error with additional context, either by using a closure
11  /// that generates the context or by directly providing the context.
12  ///
13  /// ```
14  pub trait ErrWith< ReportErr, ReportOk, E >
15  {
16    /// Takes a closure `f` that returns a value of type `ReportErr`, and uses it to wrap an error of type `(ReportErr, E)`
17    /// in the context of a `Result` of type `ReportOk`.
18    ///
19    /// This method allows you to add additional context to an error by providing a closure that generates the context.
20    ///
21    /// # Arguments
22    ///
23    /// * `f` - A closure that returns the additional context of type `ReportErr`.
24    ///
25    /// # Returns
26    ///
27    /// A `Result` of type `ReportOk` if the original result is `Ok`, or a tuple `(ReportErr, E)` containing the additional
28    /// context and the original error if the original result is `Err`.
29    ///
30    /// # Example
31    ///
32    /// ```rust
33    /// use error_tools::ErrWith;
34    /// let result : Result< (), std::io::Error > = Err( std::io::Error::new( std::io::ErrorKind::Other, "an error occurred" ) );
35    /// let result_with_context : Result< (), ( &str, std::io::Error ) > = result.err_with( || "additional context" );
36    /// ```
37    fn err_with< F >( self, f : F ) -> std::result::Result< ReportOk, ( ReportErr, E ) >
38    where
39      F : FnOnce() -> ReportErr;
40
41    /// Takes a reference to a `ReportErr` value and uses it to wrap an error of type `(ReportErr, E)`
42    /// in the context of a `Result` of type `ReportOk`.
43    ///
44    /// This method allows you to add additional context to an error by providing a reference to the context.
45    ///
46    /// # Arguments
47    ///
48    /// * `report` - A reference to the additional context of type `ReportErr`.
49    ///
50    /// # Returns
51    ///
52    /// A `Result` of type `ReportOk` if the original result is `Ok`, or a tuple `(ReportErr, E)` containing the additional
53    /// context and the original error if the original result is `Err`.
54    ///
55    /// # Example
56    ///
57    /// ```rust
58    /// use error_tools::ErrWith;
59    /// let result : Result< (), std::io::Error > = Err( std::io::Error::new( std::io::ErrorKind::Other, "an error occurred" ) );
60    /// let report = "additional context";
61    /// let result_with_report : Result< (), ( &str, std::io::Error ) > = result.err_with_report( &report );
62    /// ```
63    fn err_with_report( self, report : &ReportErr ) -> std::result::Result< ReportOk, ( ReportErr, E ) >
64    where
65      ReportErr : Clone;
66
67  }
68
69  impl< ReportErr, ReportOk, E, IntoError > ErrWith< ReportErr, ReportOk, E >
70  for std::result::Result< ReportOk, IntoError >
71  where
72    IntoError : Into< E >,
73  {
74
75    fn err_with< F >( self, f : F ) -> std::result::Result< ReportOk, ( ReportErr, E ) >
76    where
77      F : FnOnce() -> ReportErr,
78    {
79      self.map_err( | e | ( f(), e.into() ) )
80    }
81
82    #[ inline( always ) ]
83    fn err_with_report( self, report : &ReportErr ) -> std::result::Result< ReportOk, ( ReportErr, E ) >
84    where
85      ReportErr : Clone,
86      Self : Sized,
87    {
88      self.map_err( | e | ( report.clone(), e.into() ) )
89    }
90
91  }
92
93  /// A type alias for a `Result` that contains an error which is a tuple of a report and an original error.
94  ///
95  /// This is useful when you want to report additional information along with an error. The `ResultWithReport` type
96  /// helps in defining such results more concisely.
97  pub type ResultWithReport< Report, Error > = Result< Report, ( Report, Error ) >;
98
99  ///
100  /// Macro to generate an error descriptor.
101  ///
102  /// ### Basic use-case.
103  /// ```rust
104  /// # use error_tools::{ BasicError, err };
105  /// fn f1() -> BasicError
106  /// {
107  ///   return err!( "No attr" );
108  /// }
109  /// ```
110  ///
111
112  #[ macro_export ]
113  macro_rules! err
114  {
115
116    ( $msg : expr ) =>
117    {
118      $crate::BasicError::new( $msg ).into()
119    };
120    ( $msg : expr, $( $arg : expr ),+ $(,)? ) =>
121    {
122      $crate::BasicError::new( format!( $msg, $( $arg ),+ ) ).into()
123    };
124
125  }
126
127  ///
128  /// Macro to return an Err( error ) generating error descriptor.
129  ///
130  /// ### Basic use-case.
131  /// ```rust
132  /// # use error_tools::{ BasicError, return_err };
133  /// fn f1() -> Result< (), BasicError >
134  /// {
135  ///   return_err!( "No attr" );
136  /// }
137  /// ```
138  ///
139
140  #[ macro_export ]
141  macro_rules! return_err
142  {
143
144    ( $msg : expr ) =>
145    {
146      return Result::Err( $crate::err!( $msg ) )
147    };
148    ( $msg : expr, $( $arg : expr ),+ $(,)? ) =>
149    {
150      return Result::Err( $crate::err!( $msg, $( $arg ),+ ) )
151    };
152
153  }
154
155  // zzz : review
156
157  /// baic implementation of generic BasicError
158
159  #[ derive( core::fmt::Debug, core::clone::Clone, core::cmp::PartialEq, core::cmp::Eq ) ]
160  pub struct BasicError
161  {
162    msg : String,
163  }
164
165  impl BasicError
166  {
167    /// Constructor expecting message with description.
168    pub fn new< Msg : Into< String > >( msg : Msg ) -> BasicError
169    {
170      BasicError { msg : msg.into() }
171    }
172    /// Message with description getter.
173    pub fn msg( &self ) -> &String
174    {
175      &self.msg
176    }
177  }
178
179  impl core::fmt::Display for BasicError
180  {
181    fn fmt(&self, f: &mut core::fmt::Formatter< '_ >) -> core::fmt::Result
182    {
183      write!( f, "{}", self.msg )
184    }
185  }
186
187  impl ErrorTrait for BasicError
188  {
189    fn description( &self ) -> &str
190    {
191      &self.msg
192    }
193  }
194
195  impl< T > From< BasicError > for Result< T, BasicError >
196  {
197    /// Returns the argument unchanged.
198    #[ inline( always ) ]
199    fn from( src : BasicError ) -> Self
200    {
201      Result::Err( src )
202    }
203  }
204
205  pub use err;
206  pub use return_err;
207
208  // qqq : write standard mod interface without using mod_interface /* aaa : Dmytro : added to each library file */
209}
210
211#[ doc( inline ) ]
212#[ allow( unused_imports ) ]
213pub use own::*;
214
215/// Own namespace of the module.
216#[ allow( unused_imports ) ]
217pub mod own
218{
219  use super::*;
220  #[ doc( inline ) ]
221  pub use orphan::*;
222}
223
224/// Shared with parent namespace of the module
225#[ allow( unused_imports ) ]
226pub mod orphan
227{
228  use super::*;
229  #[ doc( inline ) ]
230  pub use exposed::*;
231}
232
233/// Exposed namespace of the module.
234#[ allow( unused_imports ) ]
235pub mod exposed
236{
237  use super::*;
238
239  #[ doc( inline ) ]
240  pub use private::
241  {
242    ErrWith,
243    ResultWithReport,
244  };
245
246  #[ doc( inline ) ]
247  pub use prelude::*;
248}
249
250/// Prelude to use essentials: `use my_module::prelude::*`.
251#[ allow( unused_imports ) ]
252pub mod prelude
253{
254  use super::*;
255
256  #[ doc( inline ) ]
257  pub use private::
258  {
259    err,
260    return_err,
261    ErrorTrait,
262    BasicError,
263  };
264
265}