1use std::{error, fmt, io};
4
5use crate::parse::Method;
6
7use super::encoding;
8
9pub type Result<T> = std::result::Result<T, Error>;
11
12#[derive(Debug)]
14pub enum Error {
15 Format(FormatError),
17
18 Unsupported(UnsupportedError),
20
21 Encoding(encoding::DecodingError),
23
24 IO(io::Error),
26
27 Decompression {
29 method: Method,
31 msg: String,
33 },
34
35 UnknownSize,
37}
38
39impl Error {
40 pub fn method_not_supported(method: Method) -> Self {
42 Self::Unsupported(UnsupportedError::MethodNotSupported(method))
43 }
44
45 pub fn method_not_enabled(method: Method) -> Self {
47 Self::Unsupported(UnsupportedError::MethodNotEnabled(method))
48 }
49}
50
51impl From<FormatError> for Error {
52 fn from(fmt_err: FormatError) -> Self {
53 Self::Format(fmt_err)
54 }
55}
56
57impl From<UnsupportedError> for Error {
58 fn from(unsupported: UnsupportedError) -> Self {
59 Self::Unsupported(unsupported)
60 }
61}
62
63impl From<encoding::DecodingError> for Error {
64 fn from(enc: encoding::DecodingError) -> Self {
65 Self::Encoding(enc)
66 }
67}
68
69impl From<io::Error> for Error {
70 fn from(io: io::Error) -> Self {
71 Self::IO(io)
72 }
73}
74
75impl From<Error> for io::Error {
76 fn from(e: Error) -> Self {
77 match e {
78 Error::IO(e) => e,
79 e => io::Error::other(e),
80 }
81 }
82}
83
84impl fmt::Display for Error {
85 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
86 match self {
87 Self::Format(format) => write!(f, "format: {format}"),
88 Self::Unsupported(unsupported) => write!(f, "unsupported: {unsupported}"),
89 Self::Encoding(enc) => write!(f, "encoding: {enc:?}"),
90 Self::IO(io) => write!(f, "io: {io}"),
91 Self::Decompression { method, msg } => {
92 write!(f, "{method:?} decompression error: {msg}")
93 }
94 Self::UnknownSize => f.write_str("size must be known to open zip file"),
95 }
96 }
97}
98
99impl error::Error for Error {}
100
101#[derive(Debug)]
103pub enum UnsupportedError {
104 MethodNotSupported(Method),
106
107 MethodNotEnabled(Method),
109
110 LzmaVersionUnsupported {
112 major: u8,
114 minor: u8,
116 },
117
118 LzmaPropertiesHeaderWrongSize {
120 expected: u16,
122 actual: u16,
124 },
125}
126
127impl fmt::Display for UnsupportedError {
128 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
129 match self {
130 Self::MethodNotSupported(m) => write!(f, "compression method not supported: {m:?}"),
131 Self::MethodNotEnabled(m) => write!(
132 f,
133 "compression method supported, but not enabled in this build: {m:?}"
134 ),
135 Self::LzmaVersionUnsupported { major, minor } => {
136 write!(f, "only LZMA2.0 is supported, found LZMA{major}.{minor}")
137 }
138 Self::LzmaPropertiesHeaderWrongSize { expected, actual } => {
139 write!(f, "LZMA properties header wrong size: expected {expected} bytes, got {actual} bytes")
140 }
141 }
142 }
143}
144
145impl error::Error for UnsupportedError {}
146
147#[derive(Debug)]
150pub enum FormatError {
151 DirectoryEndSignatureNotFound,
155
156 Directory64EndRecordInvalid,
161
162 DirectoryOffsetPointsOutsideFile,
165
166 InvalidCentralRecord {
172 expected: u16,
174 actual: u16,
176 },
177
178 InvalidExtraField,
182
183 InvalidHeaderOffset,
187
188 ImpossibleNumberOfFiles {
193 claimed_records_count: u64,
195 zip_size: u64,
197 },
198
199 InvalidLocalHeader,
201
202 InvalidDataDescriptor,
204
205 WrongSize {
207 expected: u64,
209 actual: u64,
211 },
212
213 WrongChecksum {
215 expected: u32,
217 actual: u32,
219 },
220}
221
222impl fmt::Display for FormatError {
223 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
224 match self {
225 Self::DirectoryEndSignatureNotFound => {
226 f.write_str("end of central directory record not found")
227 }
228 Self::Directory64EndRecordInvalid => {
229 f.write_str("zip64 end of central directory record not found")
230 }
231 Self::DirectoryOffsetPointsOutsideFile => {
232 f.write_str("directory offset points outside of file")
233 }
234 Self::InvalidCentralRecord { expected, actual } => {
235 write!(
236 f,
237 "invalid central record: expected to read {expected} files, got {actual}"
238 )
239 }
240 Self::InvalidExtraField => f.write_str("could not decode extra field"),
241 Self::InvalidHeaderOffset => f.write_str("invalid header offset"),
242 Self::ImpossibleNumberOfFiles {
243 claimed_records_count,
244 zip_size,
245 } => {
246 write!(
247 f,
248 "impossible number of files: claims to have {claimed_records_count}, but zip size is {zip_size}"
249 )
250 }
251 Self::InvalidLocalHeader => f.write_str("invalid local file header"),
252 Self::InvalidDataDescriptor => f.write_str("invalid data descriptor"),
253 Self::WrongSize { expected, actual } => {
254 write!(
255 f,
256 "uncompressed size didn't match: expected {expected}, got {actual}"
257 )
258 }
259 Self::WrongChecksum { expected, actual } => {
260 write!(
261 f,
262 "checksum didn't match: expected {expected:x?}, got {actual:x?}"
263 )
264 }
265 }
266 }
267}
268
269impl error::Error for FormatError {}