chore: Fix merge
This commit is contained in:
parent
40b0af9494
commit
614879506c
4 changed files with 49 additions and 46 deletions
|
@ -28,8 +28,8 @@
|
||||||
#![warn(missing_docs)]
|
#![warn(missing_docs)]
|
||||||
|
|
||||||
pub use crate::compression::{CompressionMethod, SUPPORTED_COMPRESSION_METHODS};
|
pub use crate::compression::{CompressionMethod, SUPPORTED_COMPRESSION_METHODS};
|
||||||
pub use crate::read::ZipArchive;
|
|
||||||
pub use crate::read::HasZipMetadata;
|
pub use crate::read::HasZipMetadata;
|
||||||
|
pub use crate::read::ZipArchive;
|
||||||
pub use crate::types::DateTime;
|
pub use crate::types::DateTime;
|
||||||
pub use crate::write::ZipWriter;
|
pub use crate::write::ZipWriter;
|
||||||
|
|
||||||
|
|
83
src/read.rs
83
src/read.rs
|
@ -12,8 +12,7 @@ use crate::spec;
|
||||||
use crate::types::{AesMode, AesVendorVersion, DateTime, System, ZipFileData};
|
use crate::types::{AesMode, AesVendorVersion, DateTime, System, ZipFileData};
|
||||||
use crate::zipcrypto::{ZipCryptoReader, ZipCryptoReaderValid, ZipCryptoValidator};
|
use crate::zipcrypto::{ZipCryptoReader, ZipCryptoReaderValid, ZipCryptoValidator};
|
||||||
use indexmap::IndexMap;
|
use indexmap::IndexMap;
|
||||||
use std::borrow::{Borrow, Cow};
|
use std::borrow::Cow;
|
||||||
use std::collections::HashMap;
|
|
||||||
use std::io::{self, prelude::*, SeekFrom};
|
use std::io::{self, prelude::*, SeekFrom};
|
||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
|
@ -221,20 +220,19 @@ struct SeekableTake<'a, R> {
|
||||||
current_offset: u64,
|
current_offset: u64,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'a, R: Seek> SeekableTake<'a, R> {
|
||||||
impl <'a, R: Seek> SeekableTake<'a, R> {
|
|
||||||
pub fn new(inner: &'a mut R, length: u64) -> io::Result<Self> {
|
pub fn new(inner: &'a mut R, length: u64) -> io::Result<Self> {
|
||||||
let inner_starting_offset = inner.seek(SeekFrom::Current(0))?;
|
let inner_starting_offset = inner.stream_position()?;
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
inner,
|
inner,
|
||||||
inner_starting_offset,
|
inner_starting_offset,
|
||||||
length,
|
length,
|
||||||
current_offset: 0
|
current_offset: 0,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl <'a, R: Seek> Seek for SeekableTake<'a, R> {
|
impl<'a, R: Seek> Seek for SeekableTake<'a, R> {
|
||||||
fn seek(&mut self, pos: SeekFrom) -> io::Result<u64> {
|
fn seek(&mut self, pos: SeekFrom) -> io::Result<u64> {
|
||||||
let offset = match pos {
|
let offset = match pos {
|
||||||
SeekFrom::Start(offset) => Some(offset),
|
SeekFrom::Start(offset) => Some(offset),
|
||||||
|
@ -242,12 +240,15 @@ impl <'a, R: Seek> Seek for SeekableTake<'a, R> {
|
||||||
SeekFrom::Current(offset) => self.current_offset.checked_add_signed(offset),
|
SeekFrom::Current(offset) => self.current_offset.checked_add_signed(offset),
|
||||||
};
|
};
|
||||||
match offset {
|
match offset {
|
||||||
None => {
|
None => Err(io::Error::new(
|
||||||
Err(io::Error::new(io::ErrorKind::InvalidInput, "invalid seek to a negative or overflowing position"))
|
io::ErrorKind::InvalidInput,
|
||||||
}
|
"invalid seek to a negative or overflowing position",
|
||||||
|
)),
|
||||||
Some(offset) => {
|
Some(offset) => {
|
||||||
let clamped_offset = std::cmp::min(self.length, offset);
|
let clamped_offset = std::cmp::min(self.length, offset);
|
||||||
let new_inner_offset = self.inner.seek(SeekFrom::Start(self.inner_starting_offset + clamped_offset))?;
|
let new_inner_offset = self
|
||||||
|
.inner
|
||||||
|
.seek(SeekFrom::Start(self.inner_starting_offset + clamped_offset))?;
|
||||||
self.current_offset = new_inner_offset - self.inner_starting_offset;
|
self.current_offset = new_inner_offset - self.inner_starting_offset;
|
||||||
Ok(new_inner_offset)
|
Ok(new_inner_offset)
|
||||||
}
|
}
|
||||||
|
@ -255,9 +256,12 @@ impl <'a, R: Seek> Seek for SeekableTake<'a, R> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl <'a, R: Read> Read for SeekableTake<'a, R> {
|
impl<'a, R: Read> Read for SeekableTake<'a, R> {
|
||||||
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
|
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
|
||||||
let written = self.inner.take(self.length - self.current_offset).read(buf)?;
|
let written = self
|
||||||
|
.inner
|
||||||
|
.take(self.length - self.current_offset)
|
||||||
|
.read(buf)?;
|
||||||
self.current_offset += written as u64;
|
self.current_offset += written as u64;
|
||||||
Ok(written)
|
Ok(written)
|
||||||
}
|
}
|
||||||
|
@ -297,17 +301,17 @@ fn find_content_seek<'a, R: Read + Seek>(
|
||||||
) -> ZipResult<SeekableTake<'a, R>> {
|
) -> ZipResult<SeekableTake<'a, R>> {
|
||||||
// Parse local header
|
// Parse local header
|
||||||
reader.seek(io::SeekFrom::Start(data.header_start))?;
|
reader.seek(io::SeekFrom::Start(data.header_start))?;
|
||||||
let signature = reader.read_u32::<LittleEndian>()?;
|
let signature = reader.read_u32_le()?;
|
||||||
if signature != spec::LOCAL_FILE_HEADER_SIGNATURE {
|
if signature != spec::LOCAL_FILE_HEADER_SIGNATURE {
|
||||||
return Err(ZipError::InvalidArchive("Invalid local file header"));
|
return Err(ZipError::InvalidArchive("Invalid local file header"));
|
||||||
}
|
}
|
||||||
|
|
||||||
reader.seek(io::SeekFrom::Current(22))?;
|
reader.seek(io::SeekFrom::Current(22))?;
|
||||||
let file_name_length = reader.read_u16::<LittleEndian>()? as u64;
|
let file_name_length = reader.read_u16_le()? as u64;
|
||||||
let extra_field_length = reader.read_u16::<LittleEndian>()? as u64;
|
let extra_field_length = reader.read_u16_le()? as u64;
|
||||||
let magic_and_header = 4 + 22 + 2 + 2;
|
let magic_and_header = 4 + 22 + 2 + 2;
|
||||||
let data_start = data.header_start + magic_and_header + file_name_length + extra_field_length;
|
let data_start = data.header_start + magic_and_header + file_name_length + extra_field_length;
|
||||||
data.data_start.store(data_start);
|
data.data_start.get_or_init(|| data_start);
|
||||||
|
|
||||||
reader.seek(io::SeekFrom::Start(data_start))?;
|
reader.seek(io::SeekFrom::Start(data_start))?;
|
||||||
|
|
||||||
|
@ -822,13 +826,7 @@ impl<R: Read + Seek> ZipArchive<R> {
|
||||||
|
|
||||||
/// Search for a file entry by name and return a seekable object.
|
/// Search for a file entry by name and return a seekable object.
|
||||||
pub fn by_name_seek(&mut self, name: &str) -> ZipResult<ZipFileSeek<R>> {
|
pub fn by_name_seek(&mut self, name: &str) -> ZipResult<ZipFileSeek<R>> {
|
||||||
let index = match self.shared.names_map.get(name) {
|
self.by_index_seek(self.index_for_name(name).ok_or(ZipError::FileNotFound)?)
|
||||||
Some(index) => *index,
|
|
||||||
None => {
|
|
||||||
return Err(ZipError::FileNotFound);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
self.by_index_seek(index)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Search for a file entry by index and return a seekable object.
|
/// Search for a file entry by index and return a seekable object.
|
||||||
|
@ -836,15 +834,17 @@ impl<R: Read + Seek> ZipArchive<R> {
|
||||||
let reader = &mut self.reader;
|
let reader = &mut self.reader;
|
||||||
self.shared
|
self.shared
|
||||||
.files
|
.files
|
||||||
.get(index)
|
.get_index(index)
|
||||||
.ok_or(ZipError::FileNotFound)
|
.ok_or(ZipError::FileNotFound)
|
||||||
.and_then(move |data| {
|
.and_then(move |(_, data)| {
|
||||||
let seek_reader = match data.compression_method {
|
let seek_reader = match data.compression_method {
|
||||||
CompressionMethod::Stored => {
|
CompressionMethod::Stored => {
|
||||||
ZipFileSeekReader::Raw(find_content_seek(data, reader)?)
|
ZipFileSeekReader::Raw(find_content_seek(data, reader)?)
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
return Err(ZipError::UnsupportedArchive("Seekable compressed files are not yet supported"))
|
return Err(ZipError::UnsupportedArchive(
|
||||||
|
"Seekable compressed files are not yet supported",
|
||||||
|
))
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
Ok(ZipFileSeek {
|
Ok(ZipFileSeek {
|
||||||
|
@ -1272,7 +1272,10 @@ pub trait HasZipMetadata {
|
||||||
|
|
||||||
/// Get the extra data of the zip header for this file
|
/// Get the extra data of the zip header for this file
|
||||||
fn extra_data(&self) -> Option<&[u8]> {
|
fn extra_data(&self) -> Option<&[u8]> {
|
||||||
self.get_metadata().extra_field.as_ref().map(|v| v.deref().deref())
|
self.get_metadata()
|
||||||
|
.extra_field
|
||||||
|
.as_ref()
|
||||||
|
.map(|v| v.deref().deref())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the starting offset of the data of the compressed file
|
/// Get the starting offset of the data of the compressed file
|
||||||
|
@ -1308,12 +1311,6 @@ impl<'a> ZipFile<'a> {
|
||||||
}
|
}
|
||||||
&mut self.reader
|
&mut self.reader
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
impl <'a> HasZipMetadata for ZipFile<'a> {
|
|
||||||
fn get_metadata(&self) -> &ZipFileData {
|
|
||||||
self.data.as_ref()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// iterate through all extra fields
|
/// iterate through all extra fields
|
||||||
pub fn extra_data_fields(&self) -> impl Iterator<Item = &ExtraField> {
|
pub fn extra_data_fields(&self) -> impl Iterator<Item = &ExtraField> {
|
||||||
|
@ -1321,13 +1318,19 @@ impl <'a> HasZipMetadata for ZipFile<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'a> HasZipMetadata for ZipFile<'a> {
|
||||||
|
fn get_metadata(&self) -> &ZipFileData {
|
||||||
|
self.data.as_ref()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<'a> Read for ZipFile<'a> {
|
impl<'a> Read for ZipFile<'a> {
|
||||||
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
|
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
|
||||||
self.get_reader().read(buf)
|
self.get_reader().read(buf)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl <'a, R: Read> Read for ZipFileSeek<'a, R> {
|
impl<'a, R: Read> Read for ZipFileSeek<'a, R> {
|
||||||
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
|
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
|
||||||
match &mut self.reader {
|
match &mut self.reader {
|
||||||
ZipFileSeekReader::Raw(r) => r.read(buf),
|
ZipFileSeekReader::Raw(r) => r.read(buf),
|
||||||
|
@ -1335,7 +1338,7 @@ impl <'a, R: Read> Read for ZipFileSeek<'a, R> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl <'a, R: Seek> Seek for ZipFileSeek<'a, R> {
|
impl<'a, R: Seek> Seek for ZipFileSeek<'a, R> {
|
||||||
fn seek(&mut self, pos: SeekFrom) -> io::Result<u64> {
|
fn seek(&mut self, pos: SeekFrom) -> io::Result<u64> {
|
||||||
match &mut self.reader {
|
match &mut self.reader {
|
||||||
ZipFileSeekReader::Raw(r) => r.seek(pos),
|
ZipFileSeekReader::Raw(r) => r.seek(pos),
|
||||||
|
@ -1343,7 +1346,7 @@ impl <'a, R: Seek> Seek for ZipFileSeek<'a, R> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl <'a, R> HasZipMetadata for ZipFileSeek<'a, R> {
|
impl<'a, R> HasZipMetadata for ZipFileSeek<'a, R> {
|
||||||
fn get_metadata(&self) -> &ZipFileData {
|
fn get_metadata(&self) -> &ZipFileData {
|
||||||
self.data.as_ref()
|
self.data.as_ref()
|
||||||
}
|
}
|
||||||
|
@ -1534,8 +1537,8 @@ mod test {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn zip_contents() {
|
fn zip_contents() {
|
||||||
use super::ZipArchive;
|
|
||||||
use super::HasZipMetadata;
|
use super::HasZipMetadata;
|
||||||
|
use super::ZipArchive;
|
||||||
|
|
||||||
let mut v = Vec::new();
|
let mut v = Vec::new();
|
||||||
v.extend_from_slice(include_bytes!("../tests/data/mimetype.zip"));
|
v.extend_from_slice(include_bytes!("../tests/data/mimetype.zip"));
|
||||||
|
@ -1560,8 +1563,8 @@ mod test {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn zip_clone() {
|
fn zip_clone() {
|
||||||
use super::ZipArchive;
|
|
||||||
use super::HasZipMetadata;
|
use super::HasZipMetadata;
|
||||||
|
use super::ZipArchive;
|
||||||
use std::io::Read;
|
use std::io::Read;
|
||||||
|
|
||||||
let mut v = Vec::new();
|
let mut v = Vec::new();
|
||||||
|
@ -1602,8 +1605,8 @@ mod test {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn file_and_dir_predicates() {
|
fn file_and_dir_predicates() {
|
||||||
use super::ZipArchive;
|
|
||||||
use super::HasZipMetadata;
|
use super::HasZipMetadata;
|
||||||
|
use super::ZipArchive;
|
||||||
|
|
||||||
let mut v = Vec::new();
|
let mut v = Vec::new();
|
||||||
v.extend_from_slice(include_bytes!("../tests/data/files_and_dirs.zip"));
|
v.extend_from_slice(include_bytes!("../tests/data/files_and_dirs.zip"));
|
||||||
|
|
|
@ -4,8 +4,8 @@ use std::io::{self, Read};
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
central_header_to_zip_file_inner, read_zipfile_from_stream, spec, ZipError, ZipFile,
|
central_header_to_zip_file_inner, read_zipfile_from_stream, spec, HasZipMetadata, ZipError,
|
||||||
ZipFileData, ZipResult, HasZipMetadata,
|
ZipFile, ZipFileData, ZipResult,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Stream decoder for zip.
|
/// Stream decoder for zip.
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
//! Types for creating ZIP archives
|
//! Types for creating ZIP archives
|
||||||
|
|
||||||
use crate::compression::CompressionMethod;
|
use crate::compression::CompressionMethod;
|
||||||
use crate::read::{find_content, central_header_to_zip_file, ZipArchive, ZipFile};
|
use crate::read::{find_content, ZipArchive, ZipFile, ZipFileReader};
|
||||||
use crate::result::{ZipError, ZipResult};
|
use crate::result::{ZipError, ZipResult};
|
||||||
use crate::spec;
|
use crate::{HasZipMetadata, spec};
|
||||||
use crate::types::{ffi, DateTime, System, ZipFileData, DEFAULT_VERSION};
|
use crate::types::{ffi, DateTime, System, ZipFileData, DEFAULT_VERSION};
|
||||||
#[cfg(any(feature = "_deflate-any", feature = "bzip2", feature = "zstd",))]
|
#[cfg(any(feature = "_deflate-any", feature = "bzip2", feature = "zstd",))]
|
||||||
use core::num::NonZeroU64;
|
use core::num::NonZeroU64;
|
||||||
|
@ -1810,7 +1810,7 @@ mod test {
|
||||||
use crate::types::DateTime;
|
use crate::types::DateTime;
|
||||||
use crate::write::SimpleFileOptions;
|
use crate::write::SimpleFileOptions;
|
||||||
use crate::CompressionMethod::Stored;
|
use crate::CompressionMethod::Stored;
|
||||||
use crate::ZipArchive;
|
use crate::{HasZipMetadata, ZipArchive};
|
||||||
use std::io;
|
use std::io;
|
||||||
use std::io::{Cursor, Read, Write};
|
use std::io::{Cursor, Read, Write};
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
|
Loading…
Add table
Reference in a new issue