diff options
Diffstat (limited to 'src/zip/driver.rs')
| -rw-r--r-- | src/zip/driver.rs | 88 |
1 files changed, 50 insertions, 38 deletions
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 @@ | |||
| 1 | use crate::driver::{ArchiveRead, ArchiveWrite, Driver}; | 1 | use crate::driver::{ArchiveRead, ArchiveWrite, Driver}; |
| 2 | use crate::zip::structs::{deserialize, EOCDR64Locator, ExtraHeader, CDR, EOCDR, EOCDR64}; | 2 | use crate::zip::structs::{deserialize, EOCDR64Locator, ExtraHeader, CDR, EOCDR, EOCDR64}; |
| 3 | use crate::zip::{BitFlag, CompressionMethod, ZipError, ZipFile, ZipFileInfo, ZipResult}; | 3 | use crate::zip::{ |
| 4 | BitFlag, CompressionMethod, ZipError, ZipFileInfo, ZipFileReader, ZipFileWriter, ZipResult, | ||
| 5 | }; | ||
| 4 | use chrono::{Local, NaiveDate, NaiveDateTime, NaiveTime}; | 6 | use chrono::{Local, NaiveDate, NaiveDateTime, NaiveTime}; |
| 7 | use std::collections::HashMap as Map; | ||
| 8 | use std::fs::File; | ||
| 5 | use std::io::{Read, Seek, SeekFrom, Write}; | 9 | use std::io::{Read, Seek, SeekFrom, Write}; |
| 6 | 10 | ||
| 7 | pub struct Zip<Io> { | 11 | pub struct Zip<Io = File> { |
| 8 | io: Io, | 12 | io: Io, |
| 9 | 13 | ||
| 10 | files: Vec<ZipFileInfo>, | 14 | files: Map<String, ZipFileInfo>, |
| 11 | comment: String, | 15 | comment: String, |
| 12 | } | 16 | } |
| 13 | 17 | ||
| @@ -15,11 +19,12 @@ impl<Io> Driver for Zip<Io> { | |||
| 15 | type Error = ZipError; | 19 | type Error = ZipError; |
| 16 | 20 | ||
| 17 | type Io = Io; | 21 | type Io = Io; |
| 18 | type FileDriver<'d> = ZipFile<'d, Self::Io> where Self::Io: 'd; | ||
| 19 | type FileInfo = ZipFileInfo; | 22 | type FileInfo = ZipFileInfo; |
| 20 | } | 23 | } |
| 21 | 24 | ||
| 22 | impl<Io: Read + Seek> ArchiveRead for Zip<Io> { | 25 | impl<Io: Read + Seek> ArchiveRead for Zip<Io> { |
| 26 | type FileReader<'d> = ZipFileReader<'d, Io> where Io: 'd; | ||
| 27 | |||
| 23 | fn read(mut io: Self::Io) -> ZipResult<Self> { | 28 | fn read(mut io: Self::Io) -> ZipResult<Self> { |
| 24 | // Search eocdr | 29 | // Search eocdr |
| 25 | let limit = 65557.min(io.seek(SeekFrom::End(0))?) as i64; | 30 | let limit = 65557.min(io.seek(SeekFrom::End(0))?) as i64; |
| @@ -79,7 +84,7 @@ impl<Io: Read + Seek> ArchiveRead for Zip<Io> { | |||
| 79 | }; | 84 | }; |
| 80 | 85 | ||
| 81 | // Read cd records | 86 | // Read cd records |
| 82 | let mut files = Vec::with_capacity(cd_records as usize); | 87 | let mut files = Map::with_capacity(cd_records as usize); |
| 83 | io.seek(SeekFrom::Start(cd_pointer))?; | 88 | io.seek(SeekFrom::Start(cd_pointer))?; |
| 84 | let buf = { | 89 | let buf = { |
| 85 | let mut buf = vec![0; cd_size as usize]; | 90 | let mut buf = vec![0; cd_size as usize]; |
| @@ -134,49 +139,54 @@ impl<Io: Read + Seek> ArchiveRead for Zip<Io> { | |||
| 134 | } | 139 | } |
| 135 | } | 140 | } |
| 136 | 141 | ||
| 137 | files.push(ZipFileInfo::new( | 142 | files.insert( |
| 138 | CompressionMethod::from_struct_id(cdr.compression_method)?, | 143 | name.clone(), |
| 139 | BitFlag::new(cdr.bit_flag), | 144 | ZipFileInfo::new( |
| 140 | NaiveDateTime::new( | 145 | CompressionMethod::from_struct_id(cdr.compression_method)?, |
| 141 | NaiveDate::from_ymd_opt( | 146 | BitFlag::new(cdr.bit_flag), |
| 142 | (cdr.dos_date as i32 >> 9 & 0x7F) + 1980, | 147 | NaiveDateTime::new( |
| 143 | cdr.dos_date as u32 >> 5 & 0xF, | 148 | NaiveDate::from_ymd_opt( |
| 144 | cdr.dos_date as u32 & 0x1F, | 149 | (cdr.dos_date as i32 >> 9 & 0x7F) + 1980, |
| 145 | ) | 150 | cdr.dos_date as u32 >> 5 & 0xF, |
| 146 | .ok_or(ZipError::InvalidDate)?, | 151 | cdr.dos_date as u32 & 0x1F, |
| 147 | NaiveTime::from_hms_opt( | 152 | ) |
| 148 | (cdr.dos_time as u32 >> 11) & 0x1F, | 153 | .ok_or(ZipError::InvalidDate)?, |
| 149 | (cdr.dos_time as u32 >> 5) & 0x3F, | 154 | NaiveTime::from_hms_opt( |
| 150 | (cdr.dos_time as u32 & 0x1F) * 2, | 155 | (cdr.dos_time as u32 >> 11) & 0x1F, |
| 156 | (cdr.dos_time as u32 >> 5) & 0x3F, | ||
| 157 | (cdr.dos_time as u32 & 0x1F) * 2, | ||
| 158 | ) | ||
| 159 | .ok_or(ZipError::InvalidTime)?, | ||
| 151 | ) | 160 | ) |
| 152 | .ok_or(ZipError::InvalidTime)?, | 161 | .and_local_timezone(Local) |
| 153 | ) | 162 | .unwrap(), |
| 154 | .and_local_timezone(Local) | 163 | cdr.crc, |
| 155 | .unwrap(), | 164 | compressed_size, |
| 156 | cdr.crc, | 165 | size, |
| 157 | compressed_size, | 166 | header_pointer, |
| 158 | size, | 167 | name, |
| 159 | header_pointer, | 168 | comment, |
| 160 | name, | 169 | ), |
| 161 | comment, | 170 | ); |
| 162 | )); | ||
| 163 | } | 171 | } |
| 164 | 172 | ||
| 165 | Ok(Self { io, files, comment }) | 173 | Ok(Self { io, files, comment }) |
| 166 | } | 174 | } |
| 167 | 175 | ||
| 168 | fn files(&self) -> &Vec<Self::FileInfo> { | 176 | fn files(&self) -> Vec<&Self::FileInfo> { |
| 169 | &self.files | 177 | let mut files: Vec<&Self::FileInfo> = self.files.values().collect(); |
| 178 | files.sort_by_key(|f| &f.name); | ||
| 179 | files | ||
| 170 | } | 180 | } |
| 171 | 181 | ||
| 172 | fn get_file_info(&self, index: usize) -> ZipResult<&Self::FileInfo> { | 182 | fn get_file_info(&self, name: &str) -> ZipResult<&Self::FileInfo> { |
| 173 | self.files.get(index).ok_or(ZipError::FileNotFound.into()) | 183 | self.files.get(name).ok_or(ZipError::FileNotFound.into()) |
| 174 | } | 184 | } |
| 175 | 185 | ||
| 176 | fn get_file_reader<'d>(&'d mut self, index: usize) -> ZipResult<Self::FileDriver<'d>> { | 186 | fn get_file_reader<'d>(&'d mut self, name: &str) -> ZipResult<Self::FileReader<'d>> { |
| 177 | Ok(ZipFile::new( | 187 | Ok(ZipFileReader::new( |
| 178 | &mut self.io, | 188 | &mut self.io, |
| 179 | self.files.get(index).ok_or(ZipError::FileNotFound)?, | 189 | self.files.get(name).ok_or(ZipError::FileNotFound)?, |
| 180 | )?) | 190 | )?) |
| 181 | } | 191 | } |
| 182 | } | 192 | } |
| @@ -187,6 +197,8 @@ impl<Io: Read + Seek> Zip<Io> { | |||
| 187 | } | 197 | } |
| 188 | } | 198 | } |
| 189 | 199 | ||
| 190 | impl<Io: Read + Write + Seek> ArchiveWrite for Zip<Io> {} | 200 | impl<Io: Read + Write + Seek> ArchiveWrite for Zip<Io> { |
| 201 | type FileWriter<'d> = ZipFileWriter<'d, Io> where Io: 'd; | ||
| 202 | } | ||
| 191 | 203 | ||
| 192 | impl<Io: Read + Write + Seek> Zip<Io> {} | 204 | impl<Io: Read + Write + Seek> Zip<Io> {} |
