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