use core::fmt::Debug;
#[derive(Debug, thiserror::Error)]
pub enum Error<R: Debug, F: Debug> {
#[error("Remote Error: {0}")]
Remote(R),
#[error("Filesystem Error: {0}")]
FileSystem(F),
#[error("Internal error while joining background tasks")]
JoinError,
#[error("Remote zip invalid, invalid local header signature while trying to read: {file_name}")]
InvalidLocalHeaderSignature { file_name: String },
#[error(
"The calculated byte range to download a batch is too short. Was downloading file: {file_name}. Storage \
contains {storage_size} bytes, but {expected_compressed_size} are necessary"
)]
InsufficientDownloadRange {
file_name: String,
storage_size: u64,
expected_compressed_size: u64,
},
#[error("Overlapping filesizes from download detected")]
OverlappingBytesForDifferentFiles,
#[error("Invalid UTF-8 filename. This code requires filenames to match UTF-8")]
InvalidUtf8Filename,
#[error(
"The bytes length: {bytes_cnt} passed to unzip doesn't match the file '{file_name}' compressed size: \
{expected_compressed_size}"
)]
WrongBytesLength {
file_name: String,
bytes_cnt: u64,
expected_compressed_size: u64,
},
#[error("Invalid compression method found, the field contains the value: {0}")]
InvalidCompressionMethod(u16),
#[error("Unsupported compression method found: '{0}', value {1}")]
UnsupportedCompressionMethod(String, u16),
#[error("The compression method returned an error decompressing the file")]
CompressionError,
#[error("The remote file hash: {remote} doesn't match its calculated one: {calculated}")]
InvalidHash { remote: u32, calculated: u32 },
}
impl<R: Debug, F: Debug> Clone for Error<R, F>
where
R: Clone,
F: Clone,
{
fn clone(&self) -> Self {
match self {
Error::Remote(r) => Error::Remote(r.clone()),
Error::FileSystem(f) => Error::FileSystem(f.clone()),
Error::JoinError => Error::JoinError,
Error::InvalidLocalHeaderSignature { file_name } => Error::InvalidLocalHeaderSignature {
file_name: file_name.clone(),
},
Error::InsufficientDownloadRange {
file_name,
storage_size,
expected_compressed_size,
} => Error::InsufficientDownloadRange {
file_name: file_name.clone(),
storage_size: *storage_size,
expected_compressed_size: *expected_compressed_size,
},
Error::OverlappingBytesForDifferentFiles => Error::OverlappingBytesForDifferentFiles,
Error::InvalidUtf8Filename => Error::InvalidUtf8Filename,
Error::WrongBytesLength {
file_name,
bytes_cnt,
expected_compressed_size,
} => Error::WrongBytesLength {
file_name: file_name.clone(),
bytes_cnt: *bytes_cnt,
expected_compressed_size: *expected_compressed_size,
},
Error::InvalidCompressionMethod(e) => Error::InvalidCompressionMethod(*e),
Error::UnsupportedCompressionMethod(n, v) => Error::UnsupportedCompressionMethod(n.clone(), *v),
Error::CompressionError => Error::CompressionError,
Error::InvalidHash { remote, calculated } => Error::InvalidHash {
remote: *remote,
calculated: *calculated,
},
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_error_clone_variants() {
let err1 = Error::<String, ()>::Remote("error".to_string());
let err2 = Error::<(), String>::FileSystem("fs error".to_string());
let err3 = Error::<(), ()>::JoinError;
let err4 = Error::<(), ()>::InvalidLocalHeaderSignature {
file_name: "file".to_string(),
};
let err5 = Error::<(), ()>::InsufficientDownloadRange {
file_name: "file".to_string(),
storage_size: 10,
expected_compressed_size: 20,
};
let err6 = Error::<(), ()>::OverlappingBytesForDifferentFiles;
let err7 = Error::<(), ()>::InvalidUtf8Filename;
let err8 = Error::<(), ()>::WrongBytesLength {
file_name: "file".to_string(),
bytes_cnt: 10,
expected_compressed_size: 20,
};
let err9 = Error::<(), ()>::InvalidCompressionMethod(0);
let err10 = Error::<(), ()>::UnsupportedCompressionMethod("".to_string(), 0);
let err11 = Error::<(), ()>::CompressionError;
let err12 = Error::<(), ()>::InvalidHash {
remote: 0,
calculated: 0,
};
assert!(matches!(err1.clone(), Error::<String, ()>::Remote(_)));
assert!(matches!(err2.clone(), Error::<(), String>::FileSystem(_)));
assert!(matches!(err3.clone(), Error::<(), ()>::JoinError));
assert!(matches!(
err4.clone(),
Error::<(), ()>::InvalidLocalHeaderSignature { .. }
));
assert!(matches!(
err5.clone(),
Error::<(), ()>::InsufficientDownloadRange { .. }
));
assert!(matches!(
err6.clone(),
Error::<(), ()>::OverlappingBytesForDifferentFiles
));
assert!(matches!(err7.clone(), Error::<(), ()>::InvalidUtf8Filename));
assert!(matches!(err8.clone(), Error::<(), ()>::WrongBytesLength { .. }));
assert!(matches!(err9.clone(), Error::<(), ()>::InvalidCompressionMethod(_)));
assert!(matches!(
err10.clone(),
Error::<(), ()>::UnsupportedCompressionMethod(_, _)
));
assert!(matches!(err11.clone(), Error::<(), ()>::CompressionError));
assert!(matches!(err12.clone(), Error::<(), ()>::InvalidHash { .. }));
}
}