From d515e20a26cc959db912504706189ad1cce9dbfa Mon Sep 17 00:00:00 2001 From: Igor Tolmachev Date: Sun, 14 Jul 2024 17:15:24 +0900 Subject: Add file indexation --- src/zip/driver.rs | 66 ++++++++++++++++++++++++++++++++----------------------- 1 file changed, 39 insertions(+), 27 deletions(-) (limited to 'src/zip/driver.rs') diff --git a/src/zip/driver.rs b/src/zip/driver.rs index 4782e65..0905d9a 100644 --- a/src/zip/driver.rs +++ b/src/zip/driver.rs @@ -6,7 +6,7 @@ use crate::zip::{ BitFlag, CompressionMethod, ZipError, ZipFileInfo, ZipFileReader, ZipFileWriter, ZipResult, }; use chrono::{DateTime, Local, NaiveDate, NaiveDateTime, NaiveTime}; -use std::collections::BTreeMap as Map; +use std::collections::HashMap as Map; use std::fs::File; use std::io::{Read, Seek, SeekFrom, Write}; @@ -47,7 +47,8 @@ fn timestamp_to_local(time: i32) -> ZipResult> { pub struct Zip { io: Io, - files: Map, + indexes: Map, + files: Vec, comment: String, } @@ -106,12 +107,13 @@ impl ArchiveRead for Zip { }; // Read cd records - let mut files = Map::new(); + let mut indexes = Map::with_capacity(cd_records as usize); + let mut files = Vec::with_capacity(cd_records as usize); io.seek(SeekFrom::Start(cd_pointer))?; let buf = io.read_vec(cd_size as usize)?; let mut p: usize = 0; - for _ in 0..cd_records { + for i in 0..cd_records as usize { if u32::from_le_bytes(buf[p..p + 4].try_into().unwrap()) != 0x02014b50 { return Err(ZipError::InvalidCDRSignature.into()); } @@ -215,39 +217,49 @@ impl ArchiveRead for Zip { } } - files.insert( - name.clone(), - ZipFileInfo::new( - CompressionMethod::from_struct_id(cdr.compression_method)?, - bit_flag, - mtime, - atime, - ctime, - cdr.crc, - compressed_size, - size, - header_pointer, - name, - comment, - ), - ); + indexes.insert(name.clone(), i); + files.push(ZipFileInfo::new( + CompressionMethod::from_struct_id(cdr.compression_method)?, + bit_flag, + mtime, + atime, + ctime, + cdr.crc, + compressed_size, + size, + header_pointer, + name, + comment, + )); } - Ok(Self { io, files, comment }) + Ok(Self { + io, + indexes, + files, + comment, + }) } - fn files(&self) -> Vec<&Self::FileInfo> { - self.files.values().collect() + fn files(&self) -> &Vec { + &self.files } - fn get_file_info(&self, name: &str) -> ZipResult<&Self::FileInfo> { - self.files.get(name).ok_or(ZipError::FileNotFound.into()) + fn get_file_index(&self, name: &str) -> crate::ArchiveResult { + self.indexes + .get(name) + .ok_or(ZipError::FileNotFound.into()) + .copied() } - fn get_file_reader<'d>(&'d mut self, name: &str) -> ZipResult> { + fn get_file_info(&self, index: usize) -> ZipResult<&Self::FileInfo> { + self.files.get(index).ok_or(ZipError::FileNotFound.into()) + } + + fn get_file_reader<'d>(&'d mut self, index: usize) -> ZipResult> { Ok(ZipFileReader::new( &mut self.io, - self.files.get(name).ok_or(ZipError::FileNotFound)?, + self.files.get(index).ok_or(ZipError::FileNotFound)?, )?) } } -- cgit v1.2.3