nullnet_liblogging/
error.rs

1use std::fmt::Display;
2
3#[derive(Debug)]
4/// General error type for Nullnet
5pub struct Error {
6    message: String,
7}
8
9impl Error {
10    #[must_use]
11    /// Returns the error message as a string
12    pub fn to_str(&self) -> &str {
13        &self.message
14    }
15}
16
17/// Trait for logging and handling errors in a unified way
18pub trait ErrorHandler<T, E> {
19    #[allow(clippy::missing_errors_doc)]
20    fn handle_err(self, loc: Location) -> Result<T, Error>;
21}
22
23impl<T, E: Display> ErrorHandler<T, E> for Result<T, E> {
24    fn handle_err(self, location: Location) -> Result<T, Error> {
25        self.map_err(|e| {
26            log::error!("[{}:{}] {e}", location.file, location.line);
27            Error {
28                message: e.to_string(),
29            }
30        })
31    }
32}
33
34pub struct Location {
35    pub file: &'static str,
36    pub line: u32,
37}
38
39#[macro_export]
40macro_rules! location {
41    () => {
42        Location {
43            file: file!(),
44            line: line!(),
45        }
46    };
47}
48
49#[cfg(test)]
50#[cfg_attr(coverage_nightly, coverage(off))]
51mod tests {
52    use super::*;
53
54    #[test]
55    fn test_error_handler() {
56        let err_result: Result<usize, &str> = Err("test_error");
57        let err_handled = err_result.handle_err(location!());
58        assert_eq!(err_handled.unwrap_err().to_str(), "test_error");
59
60        let ok_result: Result<usize, &str> = Ok(2);
61        let ok_handled = ok_result.handle_err(location!());
62        assert_eq!(ok_handled.unwrap(), 2);
63    }
64}