aboutsummaryrefslogtreecommitdiff
path: root/src/zip
diff options
context:
space:
mode:
Diffstat (limited to 'src/zip')
-rw-r--r--src/zip/driver.rs66
1 files changed, 39 insertions, 27 deletions
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::{
6 BitFlag, CompressionMethod, ZipError, ZipFileInfo, ZipFileReader, ZipFileWriter, ZipResult, 6 BitFlag, CompressionMethod, ZipError, ZipFileInfo, ZipFileReader, ZipFileWriter, ZipResult,
7}; 7};
8use chrono::{DateTime, Local, NaiveDate, NaiveDateTime, NaiveTime}; 8use chrono::{DateTime, Local, NaiveDate, NaiveDateTime, NaiveTime};
9use std::collections::BTreeMap as Map; 9use std::collections::HashMap as Map;
10use std::fs::File; 10use std::fs::File;
11use std::io::{Read, Seek, SeekFrom, Write}; 11use std::io::{Read, Seek, SeekFrom, Write};
12 12
@@ -47,7 +47,8 @@ fn timestamp_to_local(time: i32) -> ZipResult<DateTime<Local>> {
47pub struct Zip<Io = File> { 47pub struct Zip<Io = File> {
48 io: Io, 48 io: Io,
49 49
50 files: Map<String, ZipFileInfo>, 50 indexes: Map<String, usize>,
51 files: Vec<ZipFileInfo>,
51 comment: String, 52 comment: String,
52} 53}
53 54
@@ -106,12 +107,13 @@ impl<Io: Read + Seek> ArchiveRead for Zip<Io> {
106 }; 107 };
107 108
108 // Read cd records 109 // Read cd records
109 let mut files = Map::new(); 110 let mut indexes = Map::with_capacity(cd_records as usize);
111 let mut files = Vec::with_capacity(cd_records as usize);
110 io.seek(SeekFrom::Start(cd_pointer))?; 112 io.seek(SeekFrom::Start(cd_pointer))?;
111 let buf = io.read_vec(cd_size as usize)?; 113 let buf = io.read_vec(cd_size as usize)?;
112 114
113 let mut p: usize = 0; 115 let mut p: usize = 0;
114 for _ in 0..cd_records { 116 for i in 0..cd_records as usize {
115 if u32::from_le_bytes(buf[p..p + 4].try_into().unwrap()) != 0x02014b50 { 117 if u32::from_le_bytes(buf[p..p + 4].try_into().unwrap()) != 0x02014b50 {
116 return Err(ZipError::InvalidCDRSignature.into()); 118 return Err(ZipError::InvalidCDRSignature.into());
117 } 119 }
@@ -215,39 +217,49 @@ impl<Io: Read + Seek> ArchiveRead for Zip<Io> {
215 } 217 }
216 } 218 }
217 219
218 files.insert( 220 indexes.insert(name.clone(), i);
219 name.clone(), 221 files.push(ZipFileInfo::new(
220 ZipFileInfo::new( 222 CompressionMethod::from_struct_id(cdr.compression_method)?,
221 CompressionMethod::from_struct_id(cdr.compression_method)?, 223 bit_flag,
222 bit_flag, 224 mtime,
223 mtime, 225 atime,
224 atime, 226 ctime,
225 ctime, 227 cdr.crc,
226 cdr.crc, 228 compressed_size,
227 compressed_size, 229 size,
228 size, 230 header_pointer,
229 header_pointer, 231 name,
230 name, 232 comment,
231 comment, 233 ));
232 ),
233 );
234 } 234 }
235 235
236 Ok(Self { io, files, comment }) 236 Ok(Self {
237 io,
238 indexes,
239 files,
240 comment,
241 })
237 } 242 }
238 243
239 fn files(&self) -> Vec<&Self::FileInfo> { 244 fn files(&self) -> &Vec<Self::FileInfo> {
240 self.files.values().collect() 245 &self.files
241 } 246 }
242 247
243 fn get_file_info(&self, name: &str) -> ZipResult<&Self::FileInfo> { 248 fn get_file_index(&self, name: &str) -> crate::ArchiveResult<usize, Self::Error> {
244 self.files.get(name).ok_or(ZipError::FileNotFound.into()) 249 self.indexes
250 .get(name)
251 .ok_or(ZipError::FileNotFound.into())
252 .copied()
245 } 253 }
246 254
247 fn get_file_reader<'d>(&'d mut self, name: &str) -> ZipResult<Self::FileReader<'d>> { 255 fn get_file_info(&self, index: usize) -> ZipResult<&Self::FileInfo> {
256 self.files.get(index).ok_or(ZipError::FileNotFound.into())
257 }
258
259 fn get_file_reader<'d>(&'d mut self, index: usize) -> ZipResult<Self::FileReader<'d>> {
248 Ok(ZipFileReader::new( 260 Ok(ZipFileReader::new(
249 &mut self.io, 261 &mut self.io,
250 self.files.get(name).ok_or(ZipError::FileNotFound)?, 262 self.files.get(index).ok_or(ZipError::FileNotFound)?,
251 )?) 263 )?)
252 } 264 }
253} 265}