unwrap_or_log/
lib.rs

1//!# unwrap_or_log
2//! This crate adds a function to all [`std::results::Result<T,E>`] where E implements [`std::error::Error`] by implementing the trait [`LogError`] for them
3//!
4//! The trait [`LogError`] exposes a function [`LogError::log_error`] that takes a result, logs it if it's an error and returns it unmodified:
5
6use log::error;
7///Trait exposing the  interface
8pub trait LogError {
9    ///This function should check if self is an error and if so logs the error then returns the initial value
10    fn log_error(self) -> Self;
11}
12
13impl<T, E: std::error::Error> LogError for std::result::Result<T, E> {
14    ///Log the error and returns itself
15    fn log_error(self) -> Self {
16        if let Some(error) = self.as_ref().err() {
17            error!("{error}");
18        }
19        self
20    }
21}
22
23#[cfg(test)]
24mod testing {
25    use crate::LogError;
26    use simple_logger::SimpleLogger;
27    use std::panic::set_hook;
28    use std::thread::spawn;
29    use thiserror::Error;
30
31    #[derive(Error, Debug, PartialOrd, PartialEq)]
32    enum TestError {
33        #[error("Unwrap or Log")]
34        UnwrapOrLog,
35        #[error("Log if error")]
36        LogIfError,
37        #[error("Ok or Log")]
38        OkOrLogError,
39    }
40
41    type TestResult<T> = std::result::Result<T, TestError>;
42
43    #[test]
44    fn test_unwrap_or_log_ok() {
45        let _ = SimpleLogger::default().init();
46        let data = 42;
47        let process = spawn(move || {
48            let value = TestResult::Ok(data).log_error().unwrap();
49            value
50        });
51
52        let join_result = process.join().unwrap();
53        assert_eq!(join_result, data);
54    }
55
56    #[test]
57    fn test_unwrap_or_log_error() {
58        let _ = SimpleLogger::default().init();
59        set_hook(Box::new(|_| {}));
60        let process = spawn(move || {
61            let value: i32 = TestResult::Err(TestError::UnwrapOrLog).log_error().unwrap();
62            value
63        });
64
65        let join_result = process.join();
66        assert!(join_result.is_err())
67    }
68
69    #[test]
70    fn test_log_if_error_ok() {
71        let _ = SimpleLogger::default().init();
72        let data = 42;
73        let result = TestResult::Ok(data).log_error();
74        assert_eq!(result, Ok(data))
75    }
76
77    #[test]
78    fn test_log_if_error_error() {
79        let _ = SimpleLogger::default().init();
80        let result: TestResult<i32> = TestResult::Err(TestError::LogIfError).log_error();
81        assert_eq!(result, Err(TestError::LogIfError))
82    }
83
84    #[test]
85    fn ok_or_log_ok() {
86        let _ = SimpleLogger::default().init();
87        let data = 42;
88        let result = TestResult::Ok(data).log_error().ok();
89        assert_eq!(result, Some(data))
90    }
91
92    #[test]
93    fn ok_or_log_error() {
94        let _ = SimpleLogger::default().init();
95        let result: Option<i32> = TestResult::Err(TestError::OkOrLogError).log_error().ok();
96        assert_eq!(result, None)
97    }
98}