use std::io;
use thiserror::Error;
pub type Result<T> = std::result::Result<T, Error>;
#[derive(Error, Debug)]
pub enum Error {
#[error("I/O error: {0}")]
Io(#[from] io::Error),
#[error("Compression error: {0}")]
Compression(String),
#[error("Invalid ZIP structure: {0}")]
InvalidZip(String),
#[error("TorrentZip validation failed: {0}")]
ValidationFailed(String),
#[error("CRC32 mismatch: expected {expected:08X}, got {actual:08X}")]
CrcMismatch { expected: u32, actual: u32 },
#[error("File too large: {size} bytes (max 4GB for standard ZIP)")]
FileTooLarge { size: u64 },
#[error("Too many files: {count} (max 65535 for standard ZIP)")]
TooManyFiles { count: usize },
#[error("Archive not finished")]
NotFinished,
#[error("Archive already finished")]
AlreadyFinished,
#[error("Cannot create empty TorrentZip archive")]
EmptyArchive,
}
#[derive(Error, Debug, Clone, PartialEq, Eq)]
pub enum ValidationError {
#[error("Wrong timestamp: expected TorrentZip fixed time (Dec 24, 1996 23:32:00)")]
WrongTimestamp,
#[error("Wrong compression method: expected DEFLATE (8), got {0}")]
WrongCompressionMethod(u16),
#[error("Wrong general purpose bit flag: expected 0x0002, got 0x{0:04X}")]
WrongGeneralFlag(u16),
#[error("Files not sorted by lowercase name: {0:?} comes before {1:?}")]
FilesNotSorted(String, String),
#[error("Invalid or missing TorrentZip comment")]
InvalidComment,
#[error("Comment CRC32 mismatch: expected {expected:08X}, got {actual:08X}")]
CommentCrcMismatch { expected: u32, actual: u32 },
#[error("Compression level is not maximum (level 9 required)")]
WrongCompressionLevel,
#[error("Extra data fields present (not allowed in TorrentZip)")]
ExtraDataPresent,
#[error("File comments present (not allowed in TorrentZip)")]
FileCommentsPresent,
}
impl From<flate2::CompressError> for Error {
fn from(err: flate2::CompressError) -> Self {
Error::Compression(err.to_string())
}
}
impl From<flate2::DecompressError> for Error {
fn from(err: flate2::DecompressError) -> Self {
Error::Compression(err.to_string())
}
}