diff options
Diffstat (limited to 'src/zip')
| -rw-r--r-- | src/zip/driver.rs | 66 |
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 | }; |
| 8 | use chrono::{DateTime, Local, NaiveDate, NaiveDateTime, NaiveTime}; | 8 | use chrono::{DateTime, Local, NaiveDate, NaiveDateTime, NaiveTime}; |
| 9 | use std::collections::BTreeMap as Map; | 9 | use std::collections::HashMap as Map; |
| 10 | use std::fs::File; | 10 | use std::fs::File; |
| 11 | use std::io::{Read, Seek, SeekFrom, Write}; | 11 | use std::io::{Read, Seek, SeekFrom, Write}; |
| 12 | 12 | ||
| @@ -47,7 +47,8 @@ fn timestamp_to_local(time: i32) -> ZipResult<DateTime<Local>> { | |||
| 47 | pub struct Zip<Io = File> { | 47 | pub 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 | } |
