1use std::fmt::{Display, Formatter};
7use thiserror::Error;
8
9pub type Result<V> = std::result::Result<V, ZipError>;
11
12#[derive(Debug, PartialEq, Eq)]
13pub enum Zip64ErrorCase {
14 TooManyFiles,
15 LargeFile,
16}
17
18impl Display for Zip64ErrorCase {
19 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
20 match self {
21 Self::TooManyFiles => write!(f, "More than 65536 files in archive"),
22 Self::LargeFile => write!(f, "File is larger than 4 GiB"),
23 }
24 }
25}
26
27#[non_exhaustive]
29#[derive(Debug, Error)]
30pub enum ZipError {
31 #[error("feature not supported: '{0}'")]
32 FeatureNotSupported(&'static str),
33 #[error("compression not supported: {0}")]
34 CompressionNotSupported(u16),
35 #[error("host attribute compatibility not supported: {0}")]
36 AttributeCompatibilityNotSupported(u16),
37 #[error("attempted to read a ZIP64 file whilst on a 32-bit target")]
38 TargetZip64NotSupported,
39 #[error("attempted to write a ZIP file with force_no_zip64 when ZIP64 is needed: {0}")]
40 Zip64Needed(Zip64ErrorCase),
41 #[error("end of file has not been reached")]
42 EOFNotReached,
43 #[error("extra fields exceeded maximum size")]
44 ExtraFieldTooLarge,
45 #[error("comment exceeded maximum size")]
46 CommentTooLarge,
47 #[error("filename exceeded maximum size")]
48 FileNameTooLarge,
49 #[error("filename contained an embedded NUL byte")]
50 FileNameContainsNul { filename: Vec<u8> },
51 #[error("attempted to convert non-UTF8 bytes to a string/str")]
52 StringNotUtf8,
53
54 #[error("unable to locate the end of central directory record")]
55 UnableToLocateEOCDR,
56 #[error("ZIP file contains trailing contents after the end-of-central-directory record")]
57 TrailingContents,
58 #[error("ZIP file contains a comment that appears to be an embedded ZIP file")]
59 ZipInZip,
60 #[error("extra field size was indicated to be {0} but fewer than {0} bytes remain")]
61 InvalidExtraFieldHeader(u16),
62 #[error("zip64 extended information field was incomplete")]
63 Zip64ExtendedFieldIncomplete,
64 #[error("an extra field with id {0:#x} was duplicated in the header")]
65 DuplicateExtraFieldHeader(u16),
66
67 #[error("an upstream reader returned an error: {0}")]
68 UpstreamReadError(#[from] std::io::Error),
69 #[error("a computed CRC32 value did not match the expected value")]
70 CRC32CheckError,
71 #[error("entry index was out of bounds")]
72 EntryIndexOutOfBounds,
73 #[error("the local file header name did not match the central directory name")]
74 LocalFileHeaderNameMismatch,
75 #[error("local file header data-descriptor flag did not match the central directory flag")]
76 LocalFileHeaderDataDescriptorMismatch,
77 #[error("local file header sizes did not match the central directory sizes")]
78 LocalFileHeaderSizeMismatch,
79 #[error("entry data range was invalid")]
80 InvalidEntryDataRange,
81 #[error("entry data range ({start:#x}..{end:#x}) overlapped ZIP structure at {boundary:#x}")]
82 EntryDataRangeOverlap { start: u64, end: u64, boundary: u64 },
83 #[error("ZIP version {version} is too low for compression method {compression}; expected {required}")]
84 InvalidCompressionVersion { version: u16, required: u16, compression: u16 },
85 #[error("Encountered an unexpected header (actual: {0:#x}, expected: {1:#x}).")]
86 UnexpectedHeaderError(u32, u32),
87
88 #[error("Info-ZIP Unicode Comment Extra Field was incomplete")]
89 InfoZipUnicodeCommentFieldIncomplete,
90 #[error("Info-ZIP Unicode Path Extra Field was incomplete")]
91 InfoZipUnicodePathFieldIncomplete,
92 #[error("Info-ZIP Unicode Path Extra Field contains invalid UTF-8")]
93 InfoZipUnicodePathFieldInvalidUtf8,
94
95 #[error("the end of central directory offset ({0:#x}) did not match the actual offset ({1:#x})")]
96 InvalidEndOfCentralDirectoryOffset(u64, u64),
97 #[error("the central directory size ({expected:#x}) did not match the observed byte span ({actual:#x})")]
98 InvalidCentralDirectorySize { expected: u64, actual: u64 },
99 #[error("the central directory range ({start:#x}..{end:#x}) extends past the end record offset ({boundary:#x})")]
100 InvalidCentralDirectoryRange { start: u64, end: u64, boundary: u64 },
101 #[error("the central directory end ({directory_end:#x}) did not bind to the end record at {end_record:#x}")]
102 InvalidCentralDirectoryBinding { directory_end: u64, end_record: u64 },
103 #[error("the central directory entry count ({entries}) exceeds the available central directory range")]
104 InvalidCentralDirectoryEntryCount { entries: u64 },
105 #[error("the zip64 end of central directory locator was not found")]
106 MissingZip64EndOfCentralDirectoryLocator,
107 #[error("the zip64 end of central directory locator offset ({0:#x}) did not match the actual offset ({1:#x})")]
108 InvalidZip64EndOfCentralDirectoryLocatorOffset(u64, u64),
109 #[error("the zip64 end of central directory record size ({0}) was smaller than the minimum 44 bytes")]
110 InvalidZip64EndOfCentralDirectorySize(u64),
111 #[error(
112 "the {field} in the end of central directory record ({legacy:#x}) did not match the zip64 end record ({zip64:#x})"
113 )]
114 MismatchedZip64EndOfCentralDirectoryField { field: &'static str, legacy: u64, zip64: u64 },
115 #[error(
116 "zip64 extended information field was too long: expected {expected} bytes, but {actual} bytes were provided"
117 )]
118 Zip64ExtendedInformationFieldTooLong { expected: usize, actual: usize },
119}