This commit is contained in:
Chris Hennick 2024-04-19 18:50:27 -07:00
parent 91a549d0f9
commit 174825229c
No known key found for this signature in database
GPG key ID: DA47AABA4961C509
27 changed files with 88 additions and 88 deletions

View file

@ -116,7 +116,7 @@
### Merged from upstream
- Added experimental [`zip_next::unstable::write::FileOptions::with_deprecated_encryption`] API to enable encrypting
- Added experimental [`zip::unstable::write::FileOptions::with_deprecated_encryption`] API to enable encrypting
files with PKWARE encryption.
## [0.7.5]
@ -134,7 +134,7 @@
### Changed
- Alignment and extra-data fields are now attributes of [`zip_next::unstable::write::FileOptions`], allowing them to be
- Alignment and extra-data fields are now attributes of [`zip::unstable::write::FileOptions`], allowing them to be
specified for `add_directory` and `add_symlink`.
- Extra-data fields are now formatted by the `FileOptions` method `add_extra_data`.
- Improved performance, especially for `shallow_copy_file` and `deep_copy_file` on files with extra data.
@ -197,7 +197,7 @@
### Added
- `zlib-ng` for fast Deflate compression. This is now the default for compression levels 0-9.
- `chrono` to convert zip_next::DateTime to and from chrono::NaiveDateTime
- `chrono` to convert zip::DateTime to and from chrono::NaiveDateTime
## [0.10.0]

View file

@ -1,5 +1,5 @@
[package]
name = "zip_next"
name = "zip"
version = "1.1.0"
authors = [
"Mathijs van de Nes <git@mathijs.vd-nes.nl>",

View file

@ -1,10 +1,10 @@
zip_next
zip
========
[![Build Status](https://github.com/Pr0methean/zip-next/actions/workflows/ci.yaml/badge.svg)](https://github.com/Pr0methean/zip-next/actions?query=branch%3Amaster+workflow%3ACI)
[![Crates.io version](https://img.shields.io/crates/v/zip_next.svg)](https://crates.io/crates/zip_next)
[![Crates.io version](https://img.shields.io/crates/v/zip.svg)](https://crates.io/crates/zip)
[Documentation](https://docs.rs/zip_next/1.1.0/zip_next/)
[Documentation](https://docs.rs/zip/1.1.0/zip/)
Info
----
@ -33,14 +33,14 @@ With all default features:
```toml
[dependencies]
zip_next = "1.1.0"
zip = "1.1.0"
```
Without the default features:
```toml
[dependencies]
zip_next = { version = "1.1.0", default-features = false }
zip = { version = "1.1.0", default-features = false }
```
The features available are:
@ -56,7 +56,7 @@ The features available are:
* `deflate64`: Enables the deflate64 compression algorithm. Decompression is only supported.
* `bzip2`: Enables the BZip2 compression algorithm.
* `time`: Enables features using the [time](https://github.com/rust-lang-deprecated/time) crate.
* `chrono`: Enables converting last-modified `zip_next::DateTime` to and from `chrono::NaiveDateTime`.
* `chrono`: Enables converting last-modified `zip::DateTime` to and from `chrono::NaiveDateTime`.
* `zstd`: Enables the Zstandard compression algorithm.
By default `aes-crypto`, `deflate`, `deflate-zlib-ng`, `deflate-zopfli`, `bzip2`, `time` and `zstd` are enabled.

View file

@ -4,13 +4,13 @@ use std::io::{Cursor, Read, Write};
use bencher::Bencher;
use getrandom::getrandom;
use zip_next::{write::SimpleFileOptions, ZipArchive, ZipWriter};
use zip::{write::SimpleFileOptions, ZipArchive, ZipWriter};
fn generate_random_archive(size: usize) -> Vec<u8> {
let data = Vec::new();
let mut writer = ZipWriter::new(Cursor::new(data));
let options =
SimpleFileOptions::default().compression_method(zip_next::CompressionMethod::Stored);
SimpleFileOptions::default().compression_method(zip::CompressionMethod::Stored);
writer.start_file("random.dat", options).unwrap();
let mut bytes = vec![0u8; size];

View file

@ -3,8 +3,8 @@ use bencher::{benchmark_group, benchmark_main};
use std::io::{Cursor, Write};
use bencher::Bencher;
use zip_next::write::SimpleFileOptions;
use zip_next::{CompressionMethod, ZipArchive, ZipWriter};
use zip::write::SimpleFileOptions;
use zip::{CompressionMethod, ZipArchive, ZipWriter};
const FILE_COUNT: usize = 15_000;
const FILE_SIZE: usize = 1024;

View file

@ -14,7 +14,7 @@ fn real_main() -> i32 {
let fname = std::path::Path::new(&*args[1]);
let file = fs::File::open(fname).unwrap();
let mut archive = zip_next::ZipArchive::new(file).unwrap();
let mut archive = zip::ZipArchive::new(file).unwrap();
for i in 0..archive.len() {
let mut file = archive.by_index(i).unwrap();

View file

@ -13,7 +13,7 @@ fn real_main() -> i32 {
let fname = std::path::Path::new(&*args[1]);
let zipfile = std::fs::File::open(fname).unwrap();
let mut archive = zip_next::ZipArchive::new(zipfile).unwrap();
let mut archive = zip::ZipArchive::new(zipfile).unwrap();
let mut file = match archive.by_name("test/lorem_ipsum.txt") {
Ok(file) => file,

View file

@ -15,7 +15,7 @@ fn real_main() -> i32 {
let file = fs::File::open(fname).unwrap();
let reader = BufReader::new(file);
let mut archive = zip_next::ZipArchive::new(reader).unwrap();
let mut archive = zip::ZipArchive::new(reader).unwrap();
for i in 0..archive.len() {
let file = archive.by_index(i).unwrap();

View file

@ -10,7 +10,7 @@ fn real_main() -> i32 {
let mut buf = [0u8; 16];
loop {
match zip_next::read::read_zipfile_from_stream(&mut stdin_handle) {
match zip::read::read_zipfile_from_stream(&mut stdin_handle) {
Ok(Some(mut file)) => {
println!(
"{}: {} bytes ({} bytes packed)",

View file

@ -1,6 +1,6 @@
use anyhow::Context;
use std::io::prelude::*;
use zip_next::{result::ZipError, write::SimpleFileOptions};
use zip::{result::ZipError, write::SimpleFileOptions};
use std::fs::File;
use std::path::Path;
@ -10,8 +10,8 @@ fn main() {
std::process::exit(real_main());
}
const METHOD_STORED: Option<zip_next::CompressionMethod> =
Some(zip_next::CompressionMethod::Stored);
const METHOD_STORED: Option<zip::CompressionMethod> =
Some(zip::CompressionMethod::Stored);
#[cfg(any(
feature = "deflate",
@ -19,8 +19,8 @@ const METHOD_STORED: Option<zip_next::CompressionMethod> =
feature = "deflate-zlib",
feature = "deflate-zlib-ng"
))]
const METHOD_DEFLATED: Option<zip_next::CompressionMethod> =
Some(zip_next::CompressionMethod::Deflated);
const METHOD_DEFLATED: Option<zip::CompressionMethod> =
Some(zip::CompressionMethod::Deflated);
#[cfg(not(any(
feature = "deflate",
feature = "deflate-miniz",
@ -28,17 +28,17 @@ const METHOD_DEFLATED: Option<zip_next::CompressionMethod> =
feature = "deflate-zlib-ng",
feature = "deflate-zopfli"
)))]
const METHOD_DEFLATED: Option<zip_next::CompressionMethod> = None;
const METHOD_DEFLATED: Option<zip::CompressionMethod> = None;
#[cfg(feature = "bzip2")]
const METHOD_BZIP2: Option<zip_next::CompressionMethod> = Some(zip_next::CompressionMethod::Bzip2);
const METHOD_BZIP2: Option<zip::CompressionMethod> = Some(zip::CompressionMethod::Bzip2);
#[cfg(not(feature = "bzip2"))]
const METHOD_BZIP2: Option<zip_next::CompressionMethod> = None;
const METHOD_BZIP2: Option<zip::CompressionMethod> = None;
#[cfg(feature = "zstd")]
const METHOD_ZSTD: Option<zip_next::CompressionMethod> = Some(zip_next::CompressionMethod::Zstd);
const METHOD_ZSTD: Option<zip::CompressionMethod> = Some(zip::CompressionMethod::Zstd);
#[cfg(not(feature = "zstd"))]
const METHOD_ZSTD: Option<zip_next::CompressionMethod> = None;
const METHOD_ZSTD: Option<zip::CompressionMethod> = None;
fn real_main() -> i32 {
let args: Vec<_> = std::env::args().collect();
@ -69,12 +69,12 @@ fn zip_dir<T>(
it: &mut dyn Iterator<Item = DirEntry>,
prefix: &str,
writer: T,
method: zip_next::CompressionMethod,
method: zip::CompressionMethod,
) -> anyhow::Result<()>
where
T: Write + Seek,
{
let mut zip = zip_next::ZipWriter::new(writer);
let mut zip = zip::ZipWriter::new(writer);
let options = SimpleFileOptions::default()
.compression_method(method)
.unix_permissions(0o755);
@ -110,7 +110,7 @@ where
Ok(())
}
fn doit(src_dir: &str, dst_file: &str, method: zip_next::CompressionMethod) -> anyhow::Result<()> {
fn doit(src_dir: &str, dst_file: &str, method: zip::CompressionMethod) -> anyhow::Result<()> {
if !Path::new(src_dir).is_dir() {
return Err(ZipError::FileNotFound.into());
}

View file

@ -1,5 +1,5 @@
use std::io::prelude::*;
use zip_next::write::SimpleFileOptions;
use zip::write::SimpleFileOptions;
fn main() {
std::process::exit(real_main());
@ -21,16 +21,16 @@ fn real_main() -> i32 {
0
}
fn doit(filename: &str) -> zip_next::result::ZipResult<()> {
fn doit(filename: &str) -> zip::result::ZipResult<()> {
let path = std::path::Path::new(filename);
let file = std::fs::File::create(path).unwrap();
let mut zip = zip_next::ZipWriter::new(file);
let mut zip = zip::ZipWriter::new(file);
zip.add_directory("test/", SimpleFileOptions::default())?;
let options = SimpleFileOptions::default()
.compression_method(zip_next::CompressionMethod::Stored)
.compression_method(zip::CompressionMethod::Stored)
.unix_permissions(0o755);
zip.start_file("test/☃.txt", options)?;
zip.write_all(b"Hello, World!\n")?;

View file

@ -12,13 +12,13 @@ cargo-fuzz = true
libfuzzer-sys = "0.4"
arbitrary = { version = "1.3.0", features = ["derive"] }
[dependencies.zip_next]
[dependencies.zip]
path = ".."
default-features = false
[features]
zip_next_defaults = ["zip_next/default"]
default = ["zip_next_defaults"]
zip_defaults = ["zip/default"]
default = ["zip_defaults"]
# Prevent this from interfering with workspaces
[workspace]

View file

@ -6,7 +6,7 @@ const MAX_BYTES_TO_READ: u64 = 1 << 24;
fn decompress_all(data: &[u8]) -> Result<(), Box<dyn std::error::Error>> {
let reader = std::io::Cursor::new(data);
let mut zip = zip_next::ZipArchive::new(reader)?;
let mut zip = zip::ZipArchive::new(reader)?;
for i in 0..zip.len() {
let mut file = zip.by_index(i)?.take(MAX_BYTES_TO_READ);

View file

@ -10,12 +10,12 @@ use std::path::PathBuf;
pub enum BasicFileOperation {
WriteNormalFile {
contents: Vec<Vec<u8>>,
options: zip_next::write::FullFileOptions,
options: zip::write::FullFileOptions,
},
WriteDirectory(zip_next::write::FullFileOptions),
WriteDirectory(zip::write::FullFileOptions),
WriteSymlinkWithTarget {
target: Box<PathBuf>,
options: zip_next::write::FullFileOptions,
options: zip::write::FullFileOptions,
},
ShallowCopy(Box<FileOperation>),
DeepCopy(Box<FileOperation>),
@ -48,7 +48,7 @@ impl FileOperation {
}
fn do_operation<T>(
writer: &mut RefCell<zip_next::ZipWriter<T>>,
writer: &mut RefCell<zip::ZipWriter<T>>,
operation: FileOperation,
abort: bool,
flush_on_finish_file: bool,
@ -100,7 +100,7 @@ where
if operation.reopen {
let old_comment = writer.borrow().get_raw_comment().to_owned();
let new_writer =
zip_next::ZipWriter::new_append(writer.borrow_mut().finish().unwrap()).unwrap();
zip::ZipWriter::new_append(writer.borrow_mut().finish().unwrap()).unwrap();
assert_eq!(&old_comment, new_writer.get_raw_comment());
*writer = new_writer.into();
}
@ -108,7 +108,7 @@ where
}
fuzz_target!(|test_case: FuzzTestCase| {
let mut writer = RefCell::new(zip_next::ZipWriter::new(Cursor::new(Vec::new())));
let mut writer = RefCell::new(zip::ZipWriter::new(Cursor::new(Vec::new())));
writer.borrow_mut().set_raw_comment(test_case.comment);
for (operation, abort) in test_case.operations {
let _ = do_operation(
@ -118,5 +118,5 @@ fuzz_target!(|test_case: FuzzTestCase| {
test_case.flush_on_finish_file,
);
}
let _ = zip_next::ZipArchive::new(writer.borrow_mut().finish().unwrap());
let _ = zip::ZipArchive::new(writer.borrow_mut().finish().unwrap());
});

View file

@ -9,7 +9,7 @@
//!
//! ---
//!
//! [`zip_next`](`crate`) has support for the most common ZIP archives found in common use.
//! [`zip`](`crate`) has support for the most common ZIP archives found in common use.
//! However, in special cases,
//! there are some zip archives that are difficult to read or write.
//!
@ -53,6 +53,6 @@ mod zipcrypto;
///
/// ```toml
/// [dependencies]
/// zip_next = "=1.1.0"
/// zip = "=1.1.0"
/// ```
pub mod unstable;

View file

@ -63,8 +63,8 @@ pub(crate) mod zip_archive {
///
/// ```no_run
/// use std::io::prelude::*;
/// fn list_zip_contents(reader: impl Read + Seek) -> zip_next::result::ZipResult<()> {
/// let mut zip = zip_next::ZipArchive::new(reader)?;
/// fn list_zip_contents(reader: impl Read + Seek) -> zip::result::ZipResult<()> {
/// let mut zip = zip::ZipArchive::new(reader)?;
///
/// for i in 0..zip.len() {
/// let mut file = zip.by_index(i)?;

View file

@ -66,8 +66,8 @@ impl ZipError {
/// The text used as an error when a password is required and not supplied
///
/// ```rust,no_run
/// # use zip_next::result::ZipError;
/// # let mut archive = zip_next::ZipArchive::new(std::io::Cursor::new(&[])).unwrap();
/// # use zip::result::ZipError;
/// # let mut archive = zip::ZipArchive::new(std::io::Cursor::new(&[])).unwrap();
/// match archive.by_index(1) {
/// Err(ZipError::UnsupportedArchive(ZipError::PASSWORD_REQUIRED)) => eprintln!("a password is needed to unzip this file"),
/// _ => (),

View file

@ -96,17 +96,17 @@ pub(crate) mod zip_writer {
/// API to edit its contents.
///
/// ```
/// # fn doit() -> zip_next::result::ZipResult<()>
/// # fn doit() -> zip::result::ZipResult<()>
/// # {
/// # use zip_next::ZipWriter;
/// # use zip::ZipWriter;
/// use std::io::Write;
/// use zip_next::write::SimpleFileOptions;
/// use zip::write::SimpleFileOptions;
///
/// // We use a buffer here, though you'd normally use a `File`
/// let mut buf = [0; 65536];
/// let mut zip = ZipWriter::new(std::io::Cursor::new(&mut buf[..]));
///
/// let options = SimpleFileOptions::default().compression_method(zip_next::CompressionMethod::Stored);
/// let options = SimpleFileOptions::default().compression_method(zip::CompressionMethod::Stored);
/// zip.start_file("hello_world.txt", options)?;
/// zip.write(b"Hello, World!")?;
///
@ -951,12 +951,12 @@ impl<W: Write + Seek> ZipWriter<W> {
/// ```no_run
/// use std::fs::File;
/// use std::io::{Read, Seek, Write};
/// use zip_next::{ZipArchive, ZipWriter};
/// use zip::{ZipArchive, ZipWriter};
///
/// fn copy_rename<R, W>(
/// src: &mut ZipArchive<R>,
/// dst: &mut ZipWriter<W>,
/// ) -> zip_next::result::ZipResult<()>
/// ) -> zip::result::ZipResult<()>
/// where
/// R: Read + Seek,
/// W: Write + Seek,
@ -1005,9 +1005,9 @@ impl<W: Write + Seek> ZipWriter<W> {
/// ```no_run
/// use std::fs::File;
/// use std::io::{Read, Seek, Write};
/// use zip_next::{ZipArchive, ZipWriter};
/// use zip::{ZipArchive, ZipWriter};
///
/// fn copy<R, W>(src: &mut ZipArchive<R>, dst: &mut ZipWriter<W>) -> zip_next::result::ZipResult<()>
/// fn copy<R, W>(src: &mut ZipArchive<R>, dst: &mut ZipWriter<W>) -> zip::result::ZipResult<()>
/// where
/// R: Read + Seek,
/// W: Write + Seek,

View file

@ -1,7 +1,7 @@
#![cfg(feature = "aes-crypto")]
use std::io::{self, Read};
use zip_next::ZipArchive;
use zip::ZipArchive;
const SECRET_CONTENT: &str = "Lorem ipsum dolor sit amet";

View file

@ -1,7 +1,7 @@
#![cfg(feature = "deflate64")]
use std::io::{self, Read};
use zip_next::ZipArchive;
use zip::ZipArchive;
#[test]
fn decompress_deflate64() {

View file

@ -2,11 +2,11 @@ use byteorder::{LittleEndian, WriteBytesExt};
use std::collections::HashSet;
use std::io::prelude::*;
use std::io::Cursor;
use zip_next::result::ZipResult;
use zip_next::write::ExtendedFileOptions;
use zip_next::write::FileOptions;
use zip_next::write::SimpleFileOptions;
use zip_next::{CompressionMethod, ZipWriter, SUPPORTED_COMPRESSION_METHODS};
use zip::result::ZipResult;
use zip::write::ExtendedFileOptions;
use zip::write::FileOptions;
use zip::write::SimpleFileOptions;
use zip::{CompressionMethod, ZipWriter, SUPPORTED_COMPRESSION_METHODS};
// This test asserts that after creating a zip file, then reading its contents back out,
// the extracted data will *always* be exactly the same as the original data.
@ -41,7 +41,7 @@ fn copy() {
let mut tgt_file = &mut Cursor::new(Vec::new());
{
let mut src_archive = zip_next::ZipArchive::new(src_file).unwrap();
let mut src_archive = zip::ZipArchive::new(src_file).unwrap();
let mut zip = ZipWriter::new(&mut tgt_file);
{
@ -62,7 +62,7 @@ fn copy() {
}
}
let mut tgt_archive = zip_next::ZipArchive::new(tgt_file).unwrap();
let mut tgt_archive = zip::ZipArchive::new(tgt_file).unwrap();
check_archive_file_contents(&mut tgt_archive, ENTRY_NAME, LOREM_IPSUM);
check_archive_file_contents(&mut tgt_archive, COPY_ENTRY_NAME, LOREM_IPSUM);
@ -95,7 +95,7 @@ fn append() {
zip.finish().unwrap();
}
let mut zip = zip_next::ZipArchive::new(&mut file).unwrap();
let mut zip = zip::ZipArchive::new(&mut file).unwrap();
check_archive_file_contents(&mut zip, ENTRY_NAME, LOREM_IPSUM);
check_archive_file_contents(&mut zip, COPY_ENTRY_NAME, LOREM_IPSUM);
check_archive_file_contents(&mut zip, INTERNAL_COPY_ENTRY_NAME, LOREM_IPSUM);
@ -138,8 +138,8 @@ fn write_test_archive(file: &mut Cursor<Vec<u8>>, method: CompressionMethod, sha
}
// Load an archive from buffer and check for test data.
fn check_test_archive<R: Read + Seek>(zip_file: R) -> ZipResult<zip_next::ZipArchive<R>> {
let mut archive = zip_next::ZipArchive::new(zip_file).unwrap();
fn check_test_archive<R: Read + Seek>(zip_file: R) -> ZipResult<zip::ZipArchive<R>> {
let mut archive = zip::ZipArchive::new(zip_file).unwrap();
// Check archive contains expected file names.
{
@ -173,7 +173,7 @@ fn check_test_archive<R: Read + Seek>(zip_file: R) -> ZipResult<zip_next::ZipArc
// Read a file in the archive as a string.
fn read_archive_file<R: Read + Seek>(
archive: &mut zip_next::ZipArchive<R>,
archive: &mut zip::ZipArchive<R>,
name: &str,
) -> ZipResult<String> {
let mut file = archive.by_name(name)?;
@ -209,7 +209,7 @@ fn check_archive_file(
// Check a file in the archive contains the given data.
fn check_archive_file_contents<R: Read + Seek>(
archive: &mut zip_next::ZipArchive<R>,
archive: &mut zip::ZipArchive<R>,
name: &str,
expected: &[u8],
) {

View file

@ -1,5 +1,5 @@
use std::io::Cursor;
use zip_next::read::ZipArchive;
use zip::read::ZipArchive;
const BUF: &[u8] = &[
0x50, 0x4b, 0x03, 0x04, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,

View file

@ -1,4 +1,4 @@
use zip_next::result::ZipError;
use zip::result::ZipError;
const BUF: &[u8] = &[
0, 80, 75, 1, 2, 127, 120, 0, 3, 3, 75, 80, 232, 3, 0, 0, 0, 0, 0, 0, 3, 0, 1, 0, 7, 0, 0, 0,
@ -23,7 +23,7 @@ const BUF: &[u8] = &[
#[test]
fn invalid_header() {
let reader = std::io::Cursor::new(&BUF);
let archive = zip_next::ZipArchive::new(reader);
let archive = zip::ZipArchive::new(reader);
match archive {
Err(ZipError::InvalidArchive(_)) => {}
value => panic!("Unexpected value: {value:?}"),

View file

@ -1,7 +1,7 @@
#![cfg(feature = "lzma")]
use std::io::{self, Read};
use zip_next::ZipArchive;
use zip::ZipArchive;
#[test]
fn decompress_lzma() {

View file

@ -190,7 +190,7 @@ impl Read for Zip64File {
#[test]
fn zip64_large() {
let zipfile = Zip64File::new();
let mut archive = zip_next::ZipArchive::new(zipfile).unwrap();
let mut archive = zip::ZipArchive::new(zipfile).unwrap();
let mut buf = [0u8; 32];
for i in 0..archive.len() {

View file

@ -18,7 +18,7 @@
// 0000002e
use std::io;
use zip_next::ZipArchive;
use zip::ZipArchive;
#[test]
fn correctly_handle_zip_with_garbage_after_comment() {

View file

@ -18,24 +18,24 @@
// 000000c5
use std::io::Cursor;
use zip_next::result::ZipError;
use zip::result::ZipError;
#[test]
fn encrypting_file() {
use std::io::{Read, Write};
use zip_next::unstable::write::FileOptionsExt;
use zip::unstable::write::FileOptionsExt;
let mut buf = vec![0; 2048];
let mut archive = zip_next::write::ZipWriter::new(Cursor::new(&mut buf));
let mut archive = zip::write::ZipWriter::new(Cursor::new(&mut buf));
archive
.start_file(
"name",
zip_next::write::SimpleFileOptions::default().with_deprecated_encryption(b"password"),
zip::write::SimpleFileOptions::default().with_deprecated_encryption(b"password"),
)
.unwrap();
archive.write_all(b"test").unwrap();
archive.finish().unwrap();
drop(archive);
let mut archive = zip_next::ZipArchive::new(Cursor::new(&mut buf)).unwrap();
let mut archive = zip::ZipArchive::new(Cursor::new(&mut buf)).unwrap();
let mut file = archive.by_index_decrypt(0, b"password").unwrap();
let mut buf = Vec::new();
file.read_to_end(&mut buf).unwrap();
@ -61,7 +61,7 @@ fn encrypted_file() {
0x00, 0x00,
]);
let mut archive = zip_next::ZipArchive::new(zip_file_bytes).unwrap();
let mut archive = zip::ZipArchive::new(zip_file_bytes).unwrap();
assert_eq!(archive.len(), 1); //Only one file inside archive: `test.txt`
@ -69,8 +69,8 @@ fn encrypted_file() {
// No password
let file = archive.by_index(0);
match file {
Err(zip_next::result::ZipError::UnsupportedArchive(
zip_next::result::ZipError::PASSWORD_REQUIRED,
Err(zip::result::ZipError::UnsupportedArchive(
zip::result::ZipError::PASSWORD_REQUIRED,
)) => (),
Err(_) => panic!(
"Expected PasswordRequired error when opening encrypted file without password"