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