Skip to main content

tzip/
error.rs

1//! Error types for tzip crate.
2
3use std::io;
4use thiserror::Error;
5
6/// Result type alias for tzip operations.
7pub type Result<T> = std::result::Result<T, Error>;
8
9/// Main error type for tzip operations.
10#[derive(Error, Debug)]
11pub enum Error {
12    /// I/O error during read/write operations
13    #[error("I/O error: {0}")]
14    Io(#[from] io::Error),
15
16    /// Compression error
17    #[error("Compression error: {0}")]
18    Compression(String),
19
20    /// Invalid ZIP structure
21    #[error("Invalid ZIP structure: {0}")]
22    InvalidZip(String),
23
24    /// TorrentZip validation failed
25    #[error("TorrentZip validation failed: {0}")]
26    ValidationFailed(String),
27
28    /// CRC32 mismatch
29    #[error("CRC32 mismatch: expected {expected:08X}, got {actual:08X}")]
30    CrcMismatch { expected: u32, actual: u32 },
31
32    /// File too large for standard ZIP (needs ZIP64)
33    #[error("File too large: {size} bytes (max 4GB for standard ZIP)")]
34    FileTooLarge { size: u64 },
35
36    /// Too many files for standard ZIP (needs ZIP64)
37    #[error("Too many files: {count} (max 65535 for standard ZIP)")]
38    TooManyFiles { count: usize },
39
40    /// Operation called before finish() was called
41    #[error("Archive not finished")]
42    NotFinished,
43
44    /// Operation called after finish() was called
45    #[error("Archive already finished")]
46    AlreadyFinished,
47
48    /// Empty archive (no files added)
49    #[error("Cannot create empty TorrentZip archive")]
50    EmptyArchive,
51}
52
53/// Validation error for TorrentZip compliance checking.
54#[derive(Error, Debug, Clone, PartialEq, Eq)]
55pub enum ValidationError {
56    /// Timestamp is not the fixed TorrentZip value (Dec 24, 1996 23:32:00)
57    #[error("Wrong timestamp: expected TorrentZip fixed time (Dec 24, 1996 23:32:00)")]
58    WrongTimestamp,
59
60    /// Compression method is not DEFLATE
61    #[error("Wrong compression method: expected DEFLATE (8), got {0}")]
62    WrongCompressionMethod(u16),
63
64    /// General purpose bit flag is incorrect
65    #[error("Wrong general purpose bit flag: expected 0x0002, got 0x{0:04X}")]
66    WrongGeneralFlag(u16),
67
68    /// Files are not sorted by lowercase filename
69    #[error("Files not sorted by lowercase name: {0:?} comes before {1:?}")]
70    FilesNotSorted(String, String),
71
72    /// Archive comment is missing or invalid
73    #[error("Invalid or missing TorrentZip comment")]
74    InvalidComment,
75
76    /// Comment CRC32 doesn't match central directory
77    #[error("Comment CRC32 mismatch: expected {expected:08X}, got {actual:08X}")]
78    CommentCrcMismatch { expected: u32, actual: u32 },
79
80    /// Compression level is not maximum (9)
81    #[error("Compression level is not maximum (level 9 required)")]
82    WrongCompressionLevel,
83
84    /// Extra data fields present (not allowed in TorrentZip)
85    #[error("Extra data fields present (not allowed in TorrentZip)")]
86    ExtraDataPresent,
87
88    /// File comments present (not allowed in TorrentZip)
89    #[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}