forensic_rs/
err.rs

1use std::{borrow::Cow, fmt::Display};
2
3pub type ForensicResult<T> = Result<T, ForensicError>;
4
5/// Cannot parse certain data because the format is invalid
6#[derive(Debug, Clone, PartialEq, Eq)]
7pub struct BadFormatError(Cow<'static, str>);
8
9impl  Display for BadFormatError {
10    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
11        self.0.fmt(f)
12    }
13}
14
15/// The expected content cannot be found
16#[derive(Debug, Clone, PartialEq, Eq)]
17pub struct MissingError(Cow<'static, str>);
18
19impl std::fmt::Display for MissingError {
20    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
21        f.write_str(&self.0)
22    }
23}
24
25#[derive(Debug)]
26pub enum ForensicError {
27    PermissionError,
28    NoMoreData,
29    Other(String),
30    Missing(MissingError),
31    BadFormat(BadFormatError),
32    Io(std::io::Error),
33    CastError,
34    IllegalTimestamp(String)
35}
36
37impl ForensicError {
38    /// Create a BadFormatError from a static string slice
39    pub fn bad_format_str(err: &'static str) -> Self {
40        Self::BadFormat(BadFormatError(Cow::Borrowed(err)))
41    }
42    /// Create a BadFormatError from a String
43    pub fn bad_format_string(err: String) -> Self {
44        Self::BadFormat(BadFormatError(Cow::Owned(err)))
45    }
46    /// Create a MissingError from a static string slice
47    pub fn missing_str(err: &'static str) -> Self {
48        Self::Missing(MissingError(Cow::Borrowed(err)))
49    }
50    /// Create a MissingError from a String
51    pub fn missing_string(err: String) -> Self {
52        Self::Missing(MissingError(Cow::Owned(err)))
53    }
54}
55
56impl Clone for ForensicError {
57    fn clone(&self) -> Self {
58        match self {
59            Self::PermissionError => Self::PermissionError,
60            Self::CastError => Self::CastError,
61            Self::NoMoreData => Self::NoMoreData,
62            Self::Other(arg0) => Self::Other(arg0.clone()),
63            Self::Missing(e) => Self::Missing(e.clone()),
64            Self::BadFormat(e) => Self::BadFormat(e.clone()),
65            Self::Io(e) => Self::Io(std::io::Error::new(e.kind(), e.to_string())),
66            Self::IllegalTimestamp(reason) => Self::IllegalTimestamp(reason.clone()),
67        }
68    }
69}
70
71impl PartialEq for ForensicError {
72    fn eq(&self, other: &Self) -> bool {
73        match (self, other) {
74            (Self::Other(l0), Self::Other(r0)) => l0 == r0,
75            (Self::Missing(l0), Self::Missing(r0)) => l0 == r0,
76            (Self::BadFormat(l0), Self::BadFormat(r0)) => l0 == r0,
77            (Self::PermissionError, Self::PermissionError) => true,
78            (Self::NoMoreData, Self::NoMoreData) => true,
79            (Self::CastError, Self::CastError) => true,
80            (Self::IllegalTimestamp(l0), Self::IllegalTimestamp(r0)) => l0 == r0,
81            _ => false
82        }
83    }
84}
85impl Eq for ForensicError {}
86
87impl From<std::io::Error> for ForensicError {
88    fn from(e: std::io::Error) -> Self {
89        ForensicError::Io(e)
90    }
91}
92
93impl From<MissingError> for ForensicError {
94    fn from(value: MissingError) -> Self {
95        ForensicError::Missing(value)
96    }
97}
98impl From<&MissingError> for ForensicError {
99    fn from(value: &MissingError) -> Self {
100        ForensicError::Missing(MissingError(match &value.0 {
101            Cow::Borrowed(v) => Cow::Borrowed(v),
102            Cow::Owned(v) => Cow::Owned(v.clone()),
103        }))
104    }
105}
106
107impl From<BadFormatError> for ForensicError {
108    fn from(value: BadFormatError) -> Self {
109        ForensicError::BadFormat(value)
110    }
111}
112impl From<&BadFormatError> for ForensicError {
113    fn from(value: &BadFormatError) -> Self {
114        ForensicError::BadFormat(BadFormatError(match &value.0 {
115            Cow::Borrowed(v) => Cow::Borrowed(v),
116            Cow::Owned(v) => Cow::Owned(v.clone()),
117        }))
118    }
119}
120
121impl From<String> for ForensicError {
122    fn from(value: String) -> Self {
123        ForensicError::Other(value)
124    }
125}
126impl From<&str> for ForensicError {
127    fn from(value: &str) -> Self {
128        ForensicError::Other(value.to_string())
129    }
130}
131impl From<&String> for ForensicError {
132    fn from(value: &String) -> Self {
133        ForensicError::Other(value.to_string())
134    }
135}
136
137impl std::fmt::Display for ForensicError {
138    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
139        match self {
140            ForensicError::PermissionError => f.write_str("Not enough permissions"),
141            ForensicError::NoMoreData => f.write_str("No more content/data/files"),
142            ForensicError::Other(e) => f.write_fmt(format_args!("An error ocurred: {}", e)),
143            ForensicError::Missing(e) => f.write_fmt(format_args!("A file/data cannot be found: {}", e)),
144            ForensicError::BadFormat(e) => f.write_fmt(format_args!("The data have an unexpected format: {}", e)),
145            ForensicError::Io(e) => f.write_fmt(format_args!("IO operations error: {}", e)),
146            ForensicError::CastError => f.write_str("The Into/Form operation cannot be executed"),
147            ForensicError::IllegalTimestamp(reason) => f.write_fmt(format_args!("Illegal timestamp: '{reason}'"))
148        }
149    }
150}
151
152impl std::error::Error for ForensicError {
153    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
154        None
155    }
156
157    fn description(&self) -> &str {
158        match self {
159            ForensicError::PermissionError => "Not enough permissions",
160            ForensicError::NoMoreData => "No more content/data/files",
161            ForensicError::Other(e) => e,
162            ForensicError::Missing(e) => &e.0,
163            ForensicError::BadFormat(e) => &e.0,
164            ForensicError::Io(_) => "IO operations error",
165            ForensicError::CastError => "The Into/Form operation cannot be executed",
166            ForensicError::IllegalTimestamp(_) => "Illegal timestamp"
167        }
168    }
169
170    fn cause(&self) -> Option<&dyn std::error::Error> {
171        self.source()
172    }
173    
174}
175
176#[test]
177fn error_compatible_with_anyhow() {
178    fn this_returns_error() -> anyhow::Result<u64> {
179        let value = second_function()?;
180        Ok(value)
181    }
182    fn second_function() -> ForensicResult<u64> {
183        Err(ForensicError::bad_format_str("Invalid prefetch format"))
184    }
185
186    let error = this_returns_error().unwrap_err();
187    let frns_err = error.downcast_ref::<ForensicError>().unwrap();
188    assert_eq!(&ForensicError::bad_format_str("Invalid prefetch format"), frns_err);
189}