From 5d3d32ded672b67471d9d7c85ebbe691129cc51c Mon Sep 17 00:00:00 2001 From: Igor Tolmachev Date: Mon, 1 Jul 2024 19:12:40 +0900 Subject: Add compression support (lzma and xz are broken) --- src/zip/driver.rs | 88 +++++++++++++++++++++++++++++++------------------------ 1 file changed, 50 insertions(+), 38 deletions(-) (limited to 'src/zip/driver.rs') diff --git a/src/zip/driver.rs b/src/zip/driver.rs index a280dc7..e276844 100644 --- a/src/zip/driver.rs +++ b/src/zip/driver.rs @@ -1,13 +1,17 @@ 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 crate::zip::{ + BitFlag, CompressionMethod, ZipError, ZipFileInfo, ZipFileReader, ZipFileWriter, ZipResult, +}; use chrono::{Local, NaiveDate, NaiveDateTime, NaiveTime}; +use std::collections::HashMap as Map; +use std::fs::File; use std::io::{Read, Seek, SeekFrom, Write}; -pub struct Zip { +pub struct Zip { io: Io, - files: Vec, + files: Map, comment: String, } @@ -15,11 +19,12 @@ impl Driver for Zip { type Error = ZipError; type Io = Io; - type FileDriver<'d> = ZipFile<'d, Self::Io> where Self::Io: 'd; type FileInfo = ZipFileInfo; } impl ArchiveRead for Zip { + type FileReader<'d> = ZipFileReader<'d, Io> where Io: 'd; + fn read(mut io: Self::Io) -> ZipResult { // Search eocdr let limit = 65557.min(io.seek(SeekFrom::End(0))?) as i64; @@ -79,7 +84,7 @@ impl ArchiveRead for Zip { }; // Read cd records - let mut files = Vec::with_capacity(cd_records as usize); + let mut files = Map::with_capacity(cd_records as usize); io.seek(SeekFrom::Start(cd_pointer))?; let buf = { let mut buf = vec![0; cd_size as usize]; @@ -134,49 +139,54 @@ impl ArchiveRead for Zip { } } - 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, - ) - .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, + 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)?, ) - .ok_or(ZipError::InvalidTime)?, - ) - .and_local_timezone(Local) - .unwrap(), - cdr.crc, - compressed_size, - size, - header_pointer, - name, - comment, - )); + .and_local_timezone(Local) + .unwrap(), + cdr.crc, + compressed_size, + size, + header_pointer, + name, + comment, + ), + ); } Ok(Self { io, files, comment }) } - fn files(&self) -> &Vec { - &self.files + 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 get_file_info(&self, index: usize) -> ZipResult<&Self::FileInfo> { - self.files.get(index).ok_or(ZipError::FileNotFound.into()) + fn get_file_info(&self, name: &str) -> ZipResult<&Self::FileInfo> { + self.files.get(name).ok_or(ZipError::FileNotFound.into()) } - fn get_file_reader<'d>(&'d mut self, index: usize) -> ZipResult> { - Ok(ZipFile::new( + fn get_file_reader<'d>(&'d mut self, name: &str) -> ZipResult> { + Ok(ZipFileReader::new( &mut self.io, - self.files.get(index).ok_or(ZipError::FileNotFound)?, + self.files.get(name).ok_or(ZipError::FileNotFound)?, )?) } } @@ -187,6 +197,8 @@ impl Zip { } } -impl ArchiveWrite for Zip {} +impl ArchiveWrite for Zip { + type FileWriter<'d> = ZipFileWriter<'d, Io> where Io: 'd; +} impl Zip {} -- cgit v1.2.3