diff options
| author | igorechek06 <me@igorek.dev> | 2024-08-10 15:11:42 +0900 |
|---|---|---|
| committer | igorechek06 <me@igorek.dev> | 2024-08-10 15:11:42 +0900 |
| commit | 51f2737ca7af016e3dd3ad03673f48a754a1642e (patch) | |
| tree | 5b3ccba6cb3e82eb87b6cf9d9ef5c524b5d285bb | |
| parent | 4c411b76cad9cc735687dc739d2e2db5d00e5eac (diff) | |
| download | archivator-51f2737ca7af016e3dd3ad03673f48a754a1642e.tar.gz archivator-51f2737ca7af016e3dd3ad03673f48a754a1642e.zip | |
Replace Vec with Iterator
| -rw-r--r-- | src/zip/driver.rs | 41 | ||||
| -rw-r--r-- | src/zip/structs.rs | 2 | ||||
| -rw-r--r-- | tests/zip.rs | 14 |
3 files changed, 32 insertions, 25 deletions
diff --git a/src/zip/driver.rs b/src/zip/driver.rs index 8dc902f..b4217c8 100644 --- a/src/zip/driver.rs +++ b/src/zip/driver.rs | |||
| @@ -15,21 +15,30 @@ use std::collections::HashMap as Map; | |||
| 15 | use std::fs::File; | 15 | use std::fs::File; |
| 16 | use std::io::{BufReader, Read, Seek, SeekFrom, Write}; | 16 | use std::io::{BufReader, Read, Seek, SeekFrom, Write}; |
| 17 | 17 | ||
| 18 | #[inline] | 18 | struct Fields<'b> { |
| 19 | fn split_fields(bytes: &[u8]) -> Option<Vec<(u16, &[u8])>> { | 19 | pointer: usize, |
| 20 | let mut fields = Vec::new(); | 20 | bytes: &'b [u8], |
| 21 | 21 | } | |
| 22 | let mut p = 0; | ||
| 23 | while p < bytes.len() { | ||
| 24 | let header: ExtraHeader = deserialize(bytes.get(p..p + 4)?).unwrap(); | ||
| 25 | p += 4; | ||
| 26 | let data = bytes.get(p..p + header.size as usize)?; | ||
| 27 | p += header.size as usize; | ||
| 28 | 22 | ||
| 29 | fields.push((header.id, data)); | 23 | impl<'b> Fields<'b> { |
| 24 | pub fn new(bytes: &'b [u8]) -> Self { | ||
| 25 | Self { pointer: 0, bytes } | ||
| 30 | } | 26 | } |
| 27 | } | ||
| 31 | 28 | ||
| 32 | Some(fields) | 29 | impl<'b> Iterator for Fields<'b> { |
| 30 | type Item = (u16, &'b [u8]); | ||
| 31 | |||
| 32 | fn next(&mut self) -> Option<Self::Item> { | ||
| 33 | let header: ExtraHeader = | ||
| 34 | deserialize(self.bytes.get(self.pointer..self.pointer + 4)?).unwrap(); | ||
| 35 | self.pointer += 4; | ||
| 36 | let data = self | ||
| 37 | .bytes | ||
| 38 | .get(self.pointer..self.pointer + header.size as usize)?; | ||
| 39 | self.pointer += header.size as usize; | ||
| 40 | Some((header.id, data)) | ||
| 41 | } | ||
| 33 | } | 42 | } |
| 34 | 43 | ||
| 35 | #[inline] | 44 | #[inline] |
| @@ -159,7 +168,7 @@ impl<Io: Read + Seek> ArchiveRead for Zip<Io> { | |||
| 159 | let mut ctime = None; | 168 | let mut ctime = None; |
| 160 | 169 | ||
| 161 | // Parse extensible data fields | 170 | // Parse extensible data fields |
| 162 | for (id, mut data) in split_fields(&extra_fields).ok_or(ZipError::InvalidExtraFields)? { | 171 | for (id, mut data) in Fields::new(&extra_fields) { |
| 163 | match id { | 172 | match id { |
| 164 | // Zip64 | 173 | // Zip64 |
| 165 | 0x0001 => { | 174 | 0x0001 => { |
| @@ -175,9 +184,7 @@ impl<Io: Read + Seek> ArchiveRead for Zip<Io> { | |||
| 175 | } | 184 | } |
| 176 | // NTFS | 185 | // NTFS |
| 177 | 0x000a => { | 186 | 0x000a => { |
| 178 | for (id, mut data) in | 187 | for (id, mut data) in Fields::new(&data[4..]) { |
| 179 | split_fields(&data).ok_or(ZipError::InvalidExtraFields)? | ||
| 180 | { | ||
| 181 | match id { | 188 | match id { |
| 182 | 0x0001 => { | 189 | 0x0001 => { |
| 183 | mtime = ntfs_to_local(u64::from_le_bytes(data.read_arr()?)) | 190 | mtime = ntfs_to_local(u64::from_le_bytes(data.read_arr()?)) |
| @@ -198,7 +205,7 @@ impl<Io: Read + Seek> ArchiveRead for Zip<Io> { | |||
| 198 | // AES | 205 | // AES |
| 199 | 0x9901 => { | 206 | 0x9901 => { |
| 200 | let aes: AesField = deserialize(&data.read_arr::<7>()?).unwrap(); | 207 | let aes: AesField = deserialize(&data.read_arr::<7>()?).unwrap(); |
| 201 | if aes.id != 0x4541 { | 208 | if aes.id != [0x41, 0x45] { |
| 202 | return Err(ZipError::InvalidExtraFields); | 209 | return Err(ZipError::InvalidExtraFields); |
| 203 | } | 210 | } |
| 204 | encryption_method = match aes.strength { | 211 | encryption_method = match aes.strength { |
diff --git a/src/zip/structs.rs b/src/zip/structs.rs index 8b25400..4b4524f 100644 --- a/src/zip/structs.rs +++ b/src/zip/structs.rs | |||
| @@ -67,7 +67,7 @@ pub struct ExtraHeader { | |||
| 67 | #[derive(Serialize, Deserialize)] | 67 | #[derive(Serialize, Deserialize)] |
| 68 | pub struct AesField { | 68 | pub struct AesField { |
| 69 | pub version: u16, | 69 | pub version: u16, |
| 70 | pub id: u16, | 70 | pub id: [u8; 2], |
| 71 | pub strength: u8, | 71 | pub strength: u8, |
| 72 | pub compression_method: u16, | 72 | pub compression_method: u16, |
| 73 | } | 73 | } |
diff --git a/tests/zip.rs b/tests/zip.rs index 9283df3..e44098c 100644 --- a/tests/zip.rs +++ b/tests/zip.rs | |||
| @@ -92,6 +92,13 @@ fn test_zip_weak() { | |||
| 92 | 92 | ||
| 93 | #[test] | 93 | #[test] |
| 94 | fn test_zip() { | 94 | fn test_zip() { |
| 95 | assert_eq!( | ||
| 96 | Archive::<Zip>::read_from_file("tests/files/empty.zip") | ||
| 97 | .unwrap() | ||
| 98 | .len(), | ||
| 99 | 0 | ||
| 100 | ); | ||
| 101 | |||
| 95 | let mut archive = Archive::<Zip>::read_from_file("tests/files/archive.zip").unwrap(); | 102 | let mut archive = Archive::<Zip>::read_from_file("tests/files/archive.zip").unwrap(); |
| 96 | 103 | ||
| 97 | assert_eq!(archive.comment(), "archive comment"); | 104 | assert_eq!(archive.comment(), "archive comment"); |
| @@ -158,11 +165,4 @@ fn test_zip() { | |||
| 158 | fn test_bad_zip() { | 165 | fn test_bad_zip() { |
| 159 | assert!(Archive::<Zip>::read_from_file("tests/files/blank") | 166 | assert!(Archive::<Zip>::read_from_file("tests/files/blank") |
| 160 | .is_err_and(|e| e == ZipError::EocdrNotFound)); | 167 | .is_err_and(|e| e == ZipError::EocdrNotFound)); |
| 161 | |||
| 162 | assert_eq!( | ||
| 163 | Archive::<Zip>::read_from_file("tests/files/empty.zip") | ||
| 164 | .unwrap() | ||
| 165 | .len(), | ||
| 166 | 0 | ||
| 167 | ); | ||
| 168 | } | 168 | } |
