wherr/
lib.rs

1//! `wherr` crate provides a way to enhance Rust errors with file and line number information.
2//!
3//! The main struct `Wherr` represents an error containing additional metadata about where it originated from.
4//!
5//! The `wherr` attribute macro, defined in the `wherr_macro` crate, is re-exported here for ease of use.
6
7use std::fmt;
8
9// Re-export the procedural macro from the `wherr_macro` crate.
10pub use wherr_macro::wherr;
11
12#[cfg(feature = "anyhow")]
13use anyhow::Error as AnyhowError;
14
15#[cfg(feature = "anyhow")]
16type Wherror = AnyhowError;
17#[cfg(not(feature = "anyhow"))]
18type Wherror = Box<dyn std::error::Error>;
19
20/// Represents an error that includes file and line number metadata.
21///
22/// This error struct wraps around any error and provides a consistent interface to access the original error
23/// and the file and line where it originated from.
24pub struct Wherr {
25    pub inner: Wherror,
26    pub file: &'static str,
27    pub line: u32,
28}
29
30impl Wherr {
31    /// Create a new `Wherr` error from the given error, file, and line.
32    ///
33    /// # Parameters
34    /// * `err`: The original error to wrap.
35    /// * `file`: The file where the error occurred.
36    /// * `line`: The line number where the error occurred.
37    pub fn new(err: Wherror, file: &'static str, line: u32) -> Self {
38        Wherr {
39            inner: err,
40            file,
41            line,
42        }
43    }
44}
45
46impl fmt::Display for Wherr {
47    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
48        write!(
49            f,
50            "{}\nerror at {}:{}",
51            self.inner, self.file, self.line
52        )
53    }
54}
55
56impl fmt::Debug for Wherr {
57    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
58        write!(
59            f,
60            "{:?}\nerror at {}:{}",
61            self.inner, self.file, self.line
62        )
63    }
64}
65
66impl std::error::Error for Wherr {}
67
68/// Utility function to wrap the given error into a `Wherr` struct, adding file and line number details.
69///
70/// # Parameters
71/// * `result`: The result containing the error to wrap.
72/// * `file`: The file where the error occurred.
73/// * `line`: The line number where the error occurred.
74///
75/// # Returns
76/// If the original error is already of type `Wherr`, it is returned as is.
77/// Otherwise, the original error is wrapped inside a `Wherr` and returned.
78pub fn wherrapper<T, E>(
79    result: Result<T, E>,
80    file: &'static str,
81    line: u32,
82) -> Result<T, Wherror>
83where
84    E: Into<Wherror>,
85{
86    match result {
87        Ok(val) => Ok(val),
88        Err(err) => {
89            let error: Wherror = err.into();
90            if error.is::<Wherr>() {
91                Err(error)
92            } else {
93                Err(Wherr::new(error, file, line).into())
94            }
95        }
96    }
97}