1use std::{borrow::Cow, fmt::Display};
2
3pub type ForensicResult<T> = Result<T, ForensicError>;
4
5#[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#[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 pub fn bad_format_str(err: &'static str) -> Self {
40 Self::BadFormat(BadFormatError(Cow::Borrowed(err)))
41 }
42 pub fn bad_format_string(err: String) -> Self {
44 Self::BadFormat(BadFormatError(Cow::Owned(err)))
45 }
46 pub fn missing_str(err: &'static str) -> Self {
48 Self::Missing(MissingError(Cow::Borrowed(err)))
49 }
50 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}