Use BTreeMap to look up files by name
This commit is contained in:
parent
adaacd90f0
commit
29b3052e18
1 changed files with 20 additions and 10 deletions
30
src/write.rs
30
src/write.rs
|
@ -8,6 +8,7 @@ use crate::types::{ffi, AtomicU64, DateTime, System, ZipFileData, DEFAULT_VERSIO
|
||||||
use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
|
use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
|
||||||
use crc32fast::Hasher;
|
use crc32fast::Hasher;
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
|
use std::collections::BTreeMap;
|
||||||
use std::convert::TryInto;
|
use std::convert::TryInto;
|
||||||
use std::default::Default;
|
use std::default::Default;
|
||||||
use std::io;
|
use std::io;
|
||||||
|
@ -50,6 +51,7 @@ enum GenericZipWriter<W: Write + Seek> {
|
||||||
pub(crate) mod zip_writer {
|
pub(crate) mod zip_writer {
|
||||||
use super::*;
|
use super::*;
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
|
use std::collections::BTreeMap;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
/// ZIP archive generator
|
/// ZIP archive generator
|
||||||
|
@ -83,6 +85,7 @@ pub(crate) mod zip_writer {
|
||||||
pub struct ZipWriter<W: Write + Seek> {
|
pub struct ZipWriter<W: Write + Seek> {
|
||||||
pub(super) inner: GenericZipWriter<W>,
|
pub(super) inner: GenericZipWriter<W>,
|
||||||
pub(super) files: Vec<Rc<RefCell<ZipFileData>>>,
|
pub(super) files: Vec<Rc<RefCell<ZipFileData>>>,
|
||||||
|
pub(super) files_by_name: BTreeMap<String, Rc<RefCell<ZipFileData>>>,
|
||||||
pub(super) stats: ZipWriterStats,
|
pub(super) stats: ZipWriterStats,
|
||||||
pub(super) writing_to_file: bool,
|
pub(super) writing_to_file: bool,
|
||||||
pub(super) writing_to_extra_field: bool,
|
pub(super) writing_to_extra_field: bool,
|
||||||
|
@ -291,11 +294,17 @@ impl<A: Read + Write + Seek> ZipWriter<A> {
|
||||||
.map(Rc::new))
|
.map(Rc::new))
|
||||||
.collect::<Result<Vec<_>, _>>()?;
|
.collect::<Result<Vec<_>, _>>()?;
|
||||||
|
|
||||||
|
let mut files_by_name = BTreeMap::new();
|
||||||
|
for file in files.iter() {
|
||||||
|
files_by_name.insert(file.borrow().file_name.to_owned(), file.to_owned());
|
||||||
|
}
|
||||||
|
|
||||||
let _ = readwriter.seek(SeekFrom::Start(directory_start)); // seek directory_start to overwrite it
|
let _ = readwriter.seek(SeekFrom::Start(directory_start)); // seek directory_start to overwrite it
|
||||||
|
|
||||||
Ok(ZipWriter {
|
Ok(ZipWriter {
|
||||||
inner: GenericZipWriter::Storer(readwriter),
|
inner: GenericZipWriter::Storer(readwriter),
|
||||||
files,
|
files,
|
||||||
|
files_by_name,
|
||||||
stats: Default::default(),
|
stats: Default::default(),
|
||||||
writing_to_file: false,
|
writing_to_file: false,
|
||||||
writing_to_extra_field: false,
|
writing_to_extra_field: false,
|
||||||
|
@ -357,6 +366,7 @@ impl<W: Write + Seek> ZipWriter<W> {
|
||||||
ZipWriter {
|
ZipWriter {
|
||||||
inner: GenericZipWriter::Storer(inner),
|
inner: GenericZipWriter::Storer(inner),
|
||||||
files: Vec::new(),
|
files: Vec::new(),
|
||||||
|
files_by_name: BTreeMap::new(),
|
||||||
stats: Default::default(),
|
stats: Default::default(),
|
||||||
writing_to_file: false,
|
writing_to_file: false,
|
||||||
writing_to_extra_field: false,
|
writing_to_extra_field: false,
|
||||||
|
@ -403,6 +413,7 @@ impl<W: Write + Seek> ZipWriter<W> {
|
||||||
{
|
{
|
||||||
let writer = self.inner.get_plain();
|
let writer = self.inner.get_plain();
|
||||||
let header_start = writer.stream_position()?;
|
let header_start = writer.stream_position()?;
|
||||||
|
let name = name.into();
|
||||||
|
|
||||||
let permissions = options.permissions.unwrap_or(0o100644);
|
let permissions = options.permissions.unwrap_or(0o100644);
|
||||||
let mut file = ZipFileData {
|
let mut file = ZipFileData {
|
||||||
|
@ -416,7 +427,7 @@ impl<W: Write + Seek> ZipWriter<W> {
|
||||||
crc32: raw_values.crc32,
|
crc32: raw_values.crc32,
|
||||||
compressed_size: raw_values.compressed_size,
|
compressed_size: raw_values.compressed_size,
|
||||||
uncompressed_size: raw_values.uncompressed_size,
|
uncompressed_size: raw_values.uncompressed_size,
|
||||||
file_name: name.into(),
|
file_name: name.to_owned(),
|
||||||
file_name_raw: Vec::new(), // Never used for saving
|
file_name_raw: Vec::new(), // Never used for saving
|
||||||
extra_field: Vec::new(),
|
extra_field: Vec::new(),
|
||||||
file_comment: String::new(),
|
file_comment: String::new(),
|
||||||
|
@ -436,7 +447,9 @@ impl<W: Write + Seek> ZipWriter<W> {
|
||||||
self.stats.bytes_written = 0;
|
self.stats.bytes_written = 0;
|
||||||
self.stats.hasher = Hasher::new();
|
self.stats.hasher = Hasher::new();
|
||||||
|
|
||||||
self.files.push(Rc::new(RefCell::new(file)));
|
let file = Rc::new(RefCell::new(file));
|
||||||
|
self.files.push(file.to_owned());
|
||||||
|
self.files_by_name.insert(name, file);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -904,13 +917,8 @@ impl<W: Write + Seek> ZipWriter<W> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn data_by_name(&self, name: &str) -> ZipResult<&RefCell<ZipFileData>> {
|
fn data_by_name(&self, name: &str) -> ZipResult<&Rc<RefCell<ZipFileData>>> {
|
||||||
for file in self.files.iter() {
|
self.files_by_name.get(name).ok_or(ZipError::FileNotFound)
|
||||||
if file.borrow().file_name == name {
|
|
||||||
return Ok(file);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Err(ZipError::FileNotFound)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Adds another entry to the central directory referring to the same content as an existing
|
/// Adds another entry to the central directory referring to the same content as an existing
|
||||||
|
@ -924,7 +932,9 @@ impl<W: Write + Seek> ZipWriter<W> {
|
||||||
let mut dest_data = src_data.to_owned();
|
let mut dest_data = src_data.to_owned();
|
||||||
drop(src_data);
|
drop(src_data);
|
||||||
dest_data.file_name = dest_name.into();
|
dest_data.file_name = dest_name.into();
|
||||||
self.files.push(Rc::new(RefCell::new(dest_data)));
|
let dest_data = Rc::new(RefCell::new(dest_data));
|
||||||
|
self.files.push(dest_data.to_owned());
|
||||||
|
self.files_by_name.insert(dest_name.into(), dest_data);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue