1#![allow(unknown_lints)] #![allow(non_local_definitions)]
3use std::borrow::Cow;
6use std::error::Error;
7use std::fmt::{self, Display, Formatter};
8use std::io;
9use std::num::TryFromIntError;
10use std::string::FromUtf8Error;
11
12pub type ZipResult<T> = Result<T, ZipError>;
14
15#[derive(Debug)]
17#[non_exhaustive]
18pub enum ZipError {
19 Io(io::Error),
21
22 InvalidArchive(Cow<'static, str>),
24
25 UnsupportedArchive(&'static str),
27
28 FileNotFound,
30
31 InvalidPassword,
33}
34
35impl ZipError {
36 pub const PASSWORD_REQUIRED: &'static str = "Password required to decrypt file";
48}
49
50impl Display for ZipError {
51 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
52 match self {
53 Self::Io(_) => f.write_str("i/o error"),
54 Self::InvalidArchive(e) => write!(f, "invalid Zip archive: {}", e),
55 Self::UnsupportedArchive(e) => write!(f, "unsupported Zip archive: {}", e),
56 Self::FileNotFound => f.write_str("specified file not found in archive"),
57 Self::InvalidPassword => f.write_str("provided password is incorrect"),
58 }
59 }
60}
61
62impl Error for ZipError {
63 fn source(&self) -> Option<&(dyn Error + 'static)> {
64 match self {
65 Self::Io(e) => Some(e),
66 Self::InvalidArchive(_)
67 | Self::UnsupportedArchive(_)
68 | Self::FileNotFound
69 | Self::InvalidPassword => None,
70 }
71 }
72}
73
74impl From<ZipError> for io::Error {
75 fn from(err: ZipError) -> io::Error {
76 let kind = match &err {
77 ZipError::Io(err) => err.kind(),
78 ZipError::InvalidArchive(_) => io::ErrorKind::InvalidData,
79 ZipError::UnsupportedArchive(_) => io::ErrorKind::Unsupported,
80 ZipError::FileNotFound => io::ErrorKind::NotFound,
81 ZipError::InvalidPassword => io::ErrorKind::InvalidInput,
82 };
83
84 io::Error::new(kind, err)
85 }
86}
87
88impl From<io::Error> for ZipError {
89 fn from(value: io::Error) -> Self {
90 Self::Io(value)
91 }
92}
93
94impl From<DateTimeRangeError> for ZipError {
95 fn from(_: DateTimeRangeError) -> Self {
96 invalid!("Invalid date or time")
97 }
98}
99
100impl From<FromUtf8Error> for ZipError {
101 fn from(_: FromUtf8Error) -> Self {
102 invalid!("Invalid UTF-8")
103 }
104}
105
106#[derive(Debug)]
108pub struct DateTimeRangeError;
109
110impl From<TryFromIntError> for DateTimeRangeError {
112 fn from(_value: TryFromIntError) -> Self {
113 DateTimeRangeError
114 }
115}
116
117impl fmt::Display for DateTimeRangeError {
118 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
119 write!(
120 fmt,
121 "a date could not be represented within the bounds the MS-DOS date range (1980-2107)"
122 )
123 }
124}
125
126impl Error for DateTimeRangeError {}
127
128pub(crate) fn invalid_archive<M: Into<Cow<'static, str>>>(message: M) -> ZipError {
129 ZipError::InvalidArchive(message.into())
130}
131
132pub(crate) const fn invalid_archive_const(message: &'static str) -> ZipError {
133 ZipError::InvalidArchive(Cow::Borrowed(message))
134}
135
136macro_rules! invalid {
137 ($message:literal) => {
138 crate::result::invalid_archive_const($message)
139 };
140 ($($arg:tt)*) => {
141 crate::result::invalid_archive(format!($($arg)*))
142 };
143}
144pub(crate) use invalid;