1use std::io;
4use thiserror::Error;
5
6pub type Result<T> = std::result::Result<T, Error>;
8
9#[derive(Error, Debug)]
11pub enum Error {
12 #[error("I/O error: {0}")]
14 Io(#[from] io::Error),
15
16 #[error("Compression error: {0}")]
18 Compression(String),
19
20 #[error("Invalid ZIP structure: {0}")]
22 InvalidZip(String),
23
24 #[error("TorrentZip validation failed: {0}")]
26 ValidationFailed(String),
27
28 #[error("CRC32 mismatch: expected {expected:08X}, got {actual:08X}")]
30 CrcMismatch { expected: u32, actual: u32 },
31
32 #[error("File too large: {size} bytes (max 4GB for standard ZIP)")]
34 FileTooLarge { size: u64 },
35
36 #[error("Too many files: {count} (max 65535 for standard ZIP)")]
38 TooManyFiles { count: usize },
39
40 #[error("Archive not finished")]
42 NotFinished,
43
44 #[error("Archive already finished")]
46 AlreadyFinished,
47
48 #[error("Cannot create empty TorrentZip archive")]
50 EmptyArchive,
51}
52
53#[derive(Error, Debug, Clone, PartialEq, Eq)]
55pub enum ValidationError {
56 #[error("Wrong timestamp: expected TorrentZip fixed time (Dec 24, 1996 23:32:00)")]
58 WrongTimestamp,
59
60 #[error("Wrong compression method: expected DEFLATE (8), got {0}")]
62 WrongCompressionMethod(u16),
63
64 #[error("Wrong general purpose bit flag: expected 0x0002, got 0x{0:04X}")]
66 WrongGeneralFlag(u16),
67
68 #[error("Files not sorted by lowercase name: {0:?} comes before {1:?}")]
70 FilesNotSorted(String, String),
71
72 #[error("Invalid or missing TorrentZip comment")]
74 InvalidComment,
75
76 #[error("Comment CRC32 mismatch: expected {expected:08X}, got {actual:08X}")]
78 CommentCrcMismatch { expected: u32, actual: u32 },
79
80 #[error("Compression level is not maximum (level 9 required)")]
82 WrongCompressionLevel,
83
84 #[error("Extra data fields present (not allowed in TorrentZip)")]
86 ExtraDataPresent,
87
88 #[error("File comments present (not allowed in TorrentZip)")]
90 FileCommentsPresent,
91}
92
93impl From<flate2::CompressError> for Error {
94 fn from(err: flate2::CompressError) -> Self {
95 Error::Compression(err.to_string())
96 }
97}
98
99impl From<flate2::DecompressError> for Error {
100 fn from(err: flate2::DecompressError) -> Self {
101 Error::Compression(err.to_string())
102 }
103}