rawzip/
errors.rs

1/// An error that occurred while reading or writing a zip file
2#[derive(Debug)]
3pub struct Error {
4    inner: Box<ErrorInner>,
5}
6
7impl Error {
8    /// Returns the offset of the end of central directory (EOCD) signature
9    ///
10    /// Useful for reparsing input that contains a false EOCD signature.
11    pub fn eocd_offset(&self) -> Option<u64> {
12        self.inner.eocd_offset
13    }
14
15    /// Sets the false signature offset on this error
16    pub(crate) fn with_eocd_offset(mut self, offset: u64) -> Self {
17        self.inner.eocd_offset = Some(offset);
18        self
19    }
20}
21
22impl Error {
23    pub(crate) fn io(err: std::io::Error) -> Error {
24        Error::from(ErrorKind::IO(err))
25    }
26
27    pub(crate) fn utf8(err: std::str::Utf8Error) -> Error {
28        Error::from(ErrorKind::InvalidUtf8(err))
29    }
30
31    pub(crate) fn is_eof(&self) -> bool {
32        matches!(self.inner.kind, ErrorKind::Eof)
33    }
34
35    /// The kind of error that occurred
36    pub fn kind(&self) -> &ErrorKind {
37        &self.inner.kind
38    }
39}
40
41#[derive(Debug)]
42struct ErrorInner {
43    kind: ErrorKind,
44    eocd_offset: Option<u64>,
45}
46
47/// The kind of error that occurred
48#[derive(Debug)]
49#[non_exhaustive]
50pub enum ErrorKind {
51    /// Missing end of central directory
52    MissingEndOfCentralDirectory,
53
54    /// Missing zip64 end of central directory
55    MissingZip64EndOfCentralDirectory,
56
57    /// Buffer size too small
58    BufferTooSmall,
59
60    /// Invalid end of central directory signature
61    InvalidSignature { expected: u32, actual: u32 },
62
63    /// Invalid inflated file crc checksum
64    InvalidChecksum { expected: u32, actual: u32 },
65
66    /// An unexpected inflated file size
67    InvalidSize { expected: u64, actual: u64 },
68
69    /// Invalid UTF-8 sequence
70    InvalidUtf8(std::str::Utf8Error),
71
72    /// An invalid input error with associated message
73    InvalidInput { msg: String },
74
75    /// Could not construct an archive with the given end of central directory
76    InvalidEndOfCentralDirectory,
77
78    /// An IO error
79    IO(std::io::Error),
80
81    /// An unexpected end of file
82    Eof,
83}
84
85impl std::error::Error for Error {}
86
87impl std::fmt::Display for Error {
88    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
89        write!(f, "{}", self.inner.kind)?;
90        Ok(())
91    }
92}
93
94impl std::fmt::Display for ErrorKind {
95    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
96        match *self {
97            ErrorKind::IO(ref err) => err.fmt(f),
98            ErrorKind::MissingEndOfCentralDirectory => {
99                write!(f, "Missing end of central directory")
100            }
101            ErrorKind::MissingZip64EndOfCentralDirectory => {
102                write!(f, "Missing zip64 end of central directory")
103            }
104            ErrorKind::BufferTooSmall => {
105                write!(f, "Buffer size too small")
106            }
107            ErrorKind::Eof => {
108                write!(f, "Unexpected end of file")
109            }
110            ErrorKind::InvalidSignature { expected, actual } => {
111                write!(
112                    f,
113                    "Invalid signature: expected 0x{:08x}, got 0x{:08x}",
114                    expected, actual
115                )
116            }
117            ErrorKind::InvalidChecksum { expected, actual } => {
118                write!(
119                    f,
120                    "Invalid checksum: expected 0x{:08x}, got 0x{:08x}",
121                    expected, actual
122                )
123            }
124            ErrorKind::InvalidSize { expected, actual } => {
125                write!(f, "Invalid size: expected {}, got {}", expected, actual)
126            }
127            ErrorKind::InvalidUtf8(ref err) => {
128                write!(f, "Invalid UTF-8: {}", err)
129            }
130            ErrorKind::InvalidInput { ref msg } => {
131                write!(f, "Invalid input: {}", msg)
132            }
133            ErrorKind::InvalidEndOfCentralDirectory => {
134                write!(f, "Invalid end of central directory")
135            }
136        }
137    }
138}
139
140impl From<ErrorKind> for Error {
141    fn from(kind: ErrorKind) -> Error {
142        Error {
143            inner: Box::new(ErrorInner {
144                kind,
145                eocd_offset: None,
146            }),
147        }
148    }
149}
150
151impl From<std::io::Error> for Error {
152    fn from(err: std::io::Error) -> Error {
153        Error::from(ErrorKind::IO(err))
154    }
155}