1use core::fmt::{Display, Formatter, Result};
7
8#[derive(Debug, Clone, Copy, PartialEq, Eq)]
10#[non_exhaustive]
11pub enum ParseError {
12 LengthIsTooLarge,
17 InvalidPrefix,
22 InvalidCharacter,
24 InvalidStringLength,
26 InvalidChecksum,
28}
29impl Display for ParseError {
30 fn fmt(&self, f: &mut Formatter<'_>) -> Result {
31 f.write_str(match self {
32 ParseError::LengthIsTooLarge => "length field is too large",
33 ParseError::InvalidPrefix => "encountered an invalid prefix",
34 ParseError::InvalidCharacter => "encountered an invalid character",
35 ParseError::InvalidStringLength => "string length is invalid",
36 ParseError::InvalidChecksum => "has an invalid checksum field",
37 })
38 }
39}
40#[cfg(feature = "std")]
41#[cfg_attr(feature = "unstable", doc(cfg(all())))]
42impl std::error::Error for ParseError {}
43#[cfg(all(not(feature = "std"), fast_tlsh_error_in_core = "stable"))]
44impl core::error::Error for ParseError {}
45
46#[derive(Debug, Clone, Copy, PartialEq, Eq)]
48#[non_exhaustive]
49pub enum OperationError {
50 BufferIsTooSmall,
55}
56impl Display for OperationError {
57 fn fmt(&self, f: &mut Formatter<'_>) -> Result {
58 f.write_str(match self {
59 OperationError::BufferIsTooSmall => "buffer is too small to store the result",
60 })
61 }
62}
63#[cfg(feature = "std")]
64#[cfg_attr(feature = "unstable", doc(cfg(all())))]
65impl std::error::Error for OperationError {}
66#[cfg(all(not(feature = "std"), fast_tlsh_error_in_core = "stable"))]
67impl core::error::Error for OperationError {}
68
69#[derive(Debug, Clone, Copy, PartialEq, Eq)]
71#[non_exhaustive]
72pub enum GeneratorErrorCategory {
73 DataLength,
75
76 DataDistribution,
79}
80
81#[derive(Debug, Clone, Copy, PartialEq, Eq)]
83#[non_exhaustive]
84pub enum GeneratorError {
85 TooLargeInput,
87 TooSmallInput,
95 BucketsAreHalfEmpty,
102 BucketsAreThreeQuarterEmpty,
108}
109impl GeneratorError {
110 pub fn category(&self) -> GeneratorErrorCategory {
112 match *self {
113 GeneratorError::TooLargeInput => GeneratorErrorCategory::DataLength,
114 GeneratorError::TooSmallInput => GeneratorErrorCategory::DataLength,
115 GeneratorError::BucketsAreHalfEmpty => GeneratorErrorCategory::DataDistribution,
116 GeneratorError::BucketsAreThreeQuarterEmpty => GeneratorErrorCategory::DataDistribution,
117 }
118 }
119}
120impl Display for GeneratorError {
121 fn fmt(&self, f: &mut Formatter<'_>) -> Result {
122 f.write_str(match self {
123 GeneratorError::TooLargeInput => "input data is too large to process",
124 GeneratorError::TooSmallInput => "input data is too small to process",
125 GeneratorError::BucketsAreHalfEmpty => {
126 "approximately half or more effective buckets are empty"
127 }
128 GeneratorError::BucketsAreThreeQuarterEmpty => {
129 "approximately 3/4 or more effective buckets are empty"
130 }
131 })
132 }
133}
134#[cfg(feature = "std")]
135#[cfg_attr(feature = "unstable", doc(cfg(all())))]
136impl std::error::Error for GeneratorError {}
137#[cfg(all(not(feature = "std"), fast_tlsh_error_in_core = "stable"))]
138impl core::error::Error for GeneratorError {}
139
140#[cfg(feature = "easy-functions")]
142#[derive(Debug, Clone, Copy, PartialEq, Eq)]
143pub enum ParseErrorSide {
144 Left,
146 Right,
148}
149
150#[cfg(feature = "easy-functions")]
153#[derive(Debug, Clone, Copy, PartialEq, Eq)]
154pub struct ParseErrorEither(pub(crate) ParseErrorSide, pub(crate) ParseError);
155#[cfg(feature = "easy-functions")]
156impl ParseErrorEither {
157 pub fn side(&self) -> ParseErrorSide {
159 self.0
160 }
161
162 pub fn inner_err(&self) -> ParseError {
164 self.1
165 }
166}
167#[cfg(feature = "easy-functions")]
168impl Display for ParseErrorEither {
169 fn fmt(&self, f: &mut Formatter<'_>) -> Result {
170 write!(
171 f,
172 "error occurred while parsing fuzzy hash {side} ({msg})",
173 side = match self.side() {
174 ParseErrorSide::Left => 1,
175 ParseErrorSide::Right => 2,
176 },
177 msg = self.inner_err()
178 )
179 }
180}
181#[cfg(all(feature = "easy-functions", feature = "std"))]
182#[cfg_attr(feature = "unstable", doc(cfg(all())))]
183impl std::error::Error for ParseErrorEither {}
184#[cfg(all(
185 feature = "easy-functions",
186 not(feature = "std"),
187 fast_tlsh_error_in_core = "stable"
188))]
189impl core::error::Error for ParseErrorEither {}
190
191#[cfg(all(feature = "easy-functions", feature = "std"))]
197#[derive(Debug)]
198pub enum GeneratorOrIOError {
199 GeneratorError(GeneratorError),
201 IOError(std::io::Error),
203}
204#[cfg(all(feature = "easy-functions", feature = "std"))]
205impl Display for GeneratorOrIOError {
206 fn fmt(&self, f: &mut Formatter<'_>) -> Result {
207 match self {
208 GeneratorOrIOError::GeneratorError(err) => err.fmt(f),
209 GeneratorOrIOError::IOError(err) => err.fmt(f),
210 }
211 }
212}
213#[cfg(all(feature = "easy-functions", feature = "std"))]
214impl From<GeneratorError> for GeneratorOrIOError {
215 fn from(value: GeneratorError) -> Self {
217 GeneratorOrIOError::GeneratorError(value)
218 }
219}
220#[cfg(all(feature = "easy-functions", feature = "std"))]
221impl From<std::io::Error> for GeneratorOrIOError {
222 fn from(value: std::io::Error) -> Self {
224 GeneratorOrIOError::IOError(value)
225 }
226}
227#[cfg(all(feature = "easy-functions", feature = "std"))]
228impl std::error::Error for GeneratorOrIOError {
229 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
230 match self {
231 GeneratorOrIOError::GeneratorError(err) => Some(err),
232 GeneratorOrIOError::IOError(err) => Some(err),
233 }
234 }
235}
236
237mod tests;