From 6d5f8f046b3b24e50cb1a0e7751c6bc9170ed9d1 Mon Sep 17 00:00:00 2001 From: Igor Tolmachev Date: Sat, 29 Jun 2024 22:53:47 +0900 Subject: Add `Clone` derive and edit trait types --- Cargo.toml | 1 + src/archive.rs | 13 +++++---- src/driver/driver.rs | 15 ++++++---- src/zip/driver.rs | 75 ++++++++++++++++++++++++-------------------------- src/zip/error.rs | 2 ++ src/zip/file_driver.rs | 3 +- src/zip/file_info.rs | 6 ++-- tests/zip.rs | 4 +-- 8 files changed, 62 insertions(+), 57 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 71fef29..f2ae11c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -13,4 +13,5 @@ exclude = [".vscode/"] [dependencies] chrono = "0.4.29" +flate2 = "1.0.30" serde = { version = "1.0.203", features = ["derive"] } diff --git a/src/archive.rs b/src/archive.rs index 4a70867..8a9e8de 100644 --- a/src/archive.rs +++ b/src/archive.rs @@ -25,16 +25,19 @@ where Self::read(File::open(path)?) } - pub fn files(&self) -> Vec<&D::FileInfo> { + pub fn files(&self) -> &Vec { self.driver.files() } - pub fn get_file_info(&self, name: &str) -> Option<&D::FileInfo> { - self.driver.get_file_info(name) + pub fn get_file_info(&self, index: usize) -> ArchiveResult<&D::FileInfo, D::Error> { + self.driver.get_file_info(index) } - pub fn get_file_reader<'d>(&'d mut self, name: &str) -> Option>> { - Some(ArchiveFile::new(self.driver.get_file_reader(name)?)) + pub fn get_file_reader<'d>( + &'d mut self, + index: usize, + ) -> ArchiveResult>, D::Error> { + Ok(ArchiveFile::new(self.driver.get_file_reader(index)?)) } } diff --git a/src/driver/driver.rs b/src/driver/driver.rs index 5bd2319..4c6baad 100644 --- a/src/driver/driver.rs +++ b/src/driver/driver.rs @@ -21,14 +21,17 @@ where // Create driver instance fn read(io: Self::Io) -> ArchiveResult; - // Return vec of files (sorted by name) - fn files(&self) -> Vec<&Self::FileInfo>; + // Return vec of file info + fn files(&self) -> &Vec; - // Return file info by name - fn get_file_info(&self, name: &str) -> Option<&Self::FileInfo>; + // Return file info by index + fn get_file_info(&self, index: usize) -> ArchiveResult<&Self::FileInfo, Self::Error>; - // Return file reader by name - fn get_file_reader<'d>(&'d mut self, name: &str) -> Option>; + // Return file reader by index + fn get_file_reader<'d>( + &'d mut self, + index: usize, + ) -> ArchiveResult, Self::Error>; } pub trait ArchiveWrite: Driver diff --git a/src/zip/driver.rs b/src/zip/driver.rs index 0db845d..a280dc7 100644 --- a/src/zip/driver.rs +++ b/src/zip/driver.rs @@ -2,13 +2,12 @@ use crate::driver::{ArchiveRead, ArchiveWrite, Driver}; use crate::zip::structs::{deserialize, EOCDR64Locator, ExtraHeader, CDR, EOCDR, EOCDR64}; use crate::zip::{BitFlag, CompressionMethod, ZipError, ZipFile, ZipFileInfo, ZipResult}; use chrono::{Local, NaiveDate, NaiveDateTime, NaiveTime}; -use std::collections::HashMap as Map; use std::io::{Read, Seek, SeekFrom, Write}; pub struct Zip { io: Io, - files: Map, + files: Vec, comment: String, } @@ -80,7 +79,7 @@ impl ArchiveRead for Zip { }; // Read cd records - let mut files = 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 = { let mut buf = vec![0; cd_size as usize]; @@ -135,52 +134,50 @@ impl ArchiveRead for Zip { } } - files.insert( - name.clone(), - ZipFileInfo::new( - CompressionMethod::from_struct_id(cdr.compression_method)?, - BitFlag::new(cdr.bit_flag), - NaiveDateTime::new( - NaiveDate::from_ymd_opt( - (cdr.dos_date as i32 >> 9 & 0x7F) + 1980, - cdr.dos_date as u32 >> 5 & 0xF, - cdr.dos_date as u32 & 0x1F, - ) - .ok_or(ZipError::InvalidDate)?, - NaiveTime::from_hms_opt( - (cdr.dos_time as u32 >> 11) & 0x1F, - (cdr.dos_time as u32 >> 5) & 0x3F, - (cdr.dos_time as u32 & 0x1F) * 2, - ) - .ok_or(ZipError::InvalidTime)?, + files.push(ZipFileInfo::new( + CompressionMethod::from_struct_id(cdr.compression_method)?, + BitFlag::new(cdr.bit_flag), + NaiveDateTime::new( + NaiveDate::from_ymd_opt( + (cdr.dos_date as i32 >> 9 & 0x7F) + 1980, + cdr.dos_date as u32 >> 5 & 0xF, + cdr.dos_date as u32 & 0x1F, ) - .and_local_timezone(Local) - .unwrap(), - cdr.crc, - compressed_size, - size, - header_pointer, - name, - comment, - ), - ); + .ok_or(ZipError::InvalidDate)?, + NaiveTime::from_hms_opt( + (cdr.dos_time as u32 >> 11) & 0x1F, + (cdr.dos_time as u32 >> 5) & 0x3F, + (cdr.dos_time as u32 & 0x1F) * 2, + ) + .ok_or(ZipError::InvalidTime)?, + ) + .and_local_timezone(Local) + .unwrap(), + cdr.crc, + compressed_size, + size, + header_pointer, + name, + comment, + )); } Ok(Self { io, files, comment }) } - fn files(&self) -> Vec<&Self::FileInfo> { - let mut files: Vec<&Self::FileInfo> = self.files.values().collect(); - files.sort_by_key(|f| &f.name); - files + fn files(&self) -> &Vec { + &self.files } - fn get_file_info(&self, name: &str) -> Option<&Self::FileInfo> { - self.files.get(name) + 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, name: &str) -> Option> { - Some(ZipFile::new(&mut self.io, self.files.get(name)?).unwrap()) + fn get_file_reader<'d>(&'d mut self, index: usize) -> ZipResult> { + Ok(ZipFile::new( + &mut self.io, + self.files.get(index).ok_or(ZipError::FileNotFound)?, + )?) } } diff --git a/src/zip/error.rs b/src/zip/error.rs index d82de78..3acbf8c 100644 --- a/src/zip/error.rs +++ b/src/zip/error.rs @@ -20,6 +20,7 @@ pub enum ZipError { InvalidFileComment, NegativeFileOffset, + FileNotFound, } impl From for ArchiveError { @@ -57,6 +58,7 @@ impl Display for ZipError { Self::InvalidFileComment => write!(f, "Invalid file comment"), Self::NegativeFileOffset => write!(f, "Negative file offset"), + Self::FileNotFound => write!(f, "File not found"), } } } diff --git a/src/zip/file_driver.rs b/src/zip/file_driver.rs index 47b4242..51075e4 100644 --- a/src/zip/file_driver.rs +++ b/src/zip/file_driver.rs @@ -1,8 +1,7 @@ use crate::driver::FileDriver; use crate::zip::{ZipError, ZipFileInfo, ZipResult}; use std::io::{ - Error as IoError, ErrorKind as IoErrorKind, Read, Result as IoResult, Seek, SeekFrom, Take, - Write, + Error as IoError, ErrorKind as IoErrorKind, Read, Result as IoResult, Seek, SeekFrom, Write, }; pub struct ZipFile<'d, Io> { diff --git a/src/zip/file_info.rs b/src/zip/file_info.rs index 88322be..92d52f7 100644 --- a/src/zip/file_info.rs +++ b/src/zip/file_info.rs @@ -2,7 +2,7 @@ use crate::driver::ArchiveFileInfo; use crate::zip::{ZipError, ZipResult}; use chrono::{DateTime, Local}; -#[derive(Debug)] +#[derive(Debug, Clone)] pub enum CompressionMethod { Store, Deflate, @@ -29,7 +29,7 @@ impl CompressionMethod { } } -#[derive(Debug)] +#[derive(Debug, Clone)] pub struct BitFlag { flag: u16, } @@ -121,7 +121,7 @@ impl BitFlag { } } -#[derive(Debug)] +#[derive(Debug, Clone)] pub struct ZipFileInfo { pub compression_method: CompressionMethod, pub bit_flag: BitFlag, diff --git a/tests/zip.rs b/tests/zip.rs index 25f1f76..e5872c5 100644 --- a/tests/zip.rs +++ b/tests/zip.rs @@ -12,10 +12,10 @@ fn test_zip() { .iter() .map(|f| &f.name) .collect::>(), - vec!["a", "b", "c"] + vec!["b", "c", "a"] ); - let mut f = archive.get_file_reader("a").unwrap(); + let mut f = archive.get_file_reader(2).unwrap(); let mut data = String::new(); f.read_to_string(&mut data).unwrap(); -- cgit v1.2.3