diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/structs/error.rs | 6 | ||||
| -rw-r--r-- | src/structs/settings.rs | 20 | ||||
| -rw-r--r-- | src/zip/driver.rs | 113 | ||||
| -rw-r--r-- | src/zip/error.rs | 36 | ||||
| -rw-r--r-- | src/zip/file.rs | 69 | ||||
| -rw-r--r-- | src/zip/mod.rs | 2 | ||||
| -rw-r--r-- | src/zip/structs.rs | 8 |
7 files changed, 162 insertions, 92 deletions
diff --git a/src/structs/error.rs b/src/structs/error.rs index f08c9a3..3e74e45 100644 --- a/src/structs/error.rs +++ b/src/structs/error.rs | |||
| @@ -23,13 +23,13 @@ impl From<StructError> for ArchiveError<StructError> { | |||
| 23 | impl Display for StructError { | 23 | impl Display for StructError { |
| 24 | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { | 24 | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { |
| 25 | match self { | 25 | match self { |
| 26 | StructError::SerializationNotSupported { type_name } => { | 26 | Self::SerializationNotSupported { type_name } => { |
| 27 | writeln!(f, "Serialization for type '{type_name}' not supported") | 27 | writeln!(f, "Serialization for type '{type_name}' not supported") |
| 28 | } | 28 | } |
| 29 | StructError::DeserializationNotSupported { type_name } => { | 29 | Self::DeserializationNotSupported { type_name } => { |
| 30 | writeln!(f, "Deserialization for type '{type_name}' not supported") | 30 | writeln!(f, "Deserialization for type '{type_name}' not supported") |
| 31 | } | 31 | } |
| 32 | StructError::UnexpectedEOF => writeln!(f, "Unexpected EOF"), | 32 | Self::UnexpectedEOF => writeln!(f, "Unexpected EOF"), |
| 33 | } | 33 | } |
| 34 | } | 34 | } |
| 35 | } | 35 | } |
diff --git a/src/structs/settings.rs b/src/structs/settings.rs index fce6d9e..cf71453 100644 --- a/src/structs/settings.rs +++ b/src/structs/settings.rs | |||
| @@ -20,17 +20,17 @@ macro_rules! impl_byte_order { | |||
| 20 | impl ByteOrder {$( | 20 | impl ByteOrder {$( |
| 21 | pub fn $fr(&self, num: $n) -> Vec<u8> { | 21 | pub fn $fr(&self, num: $n) -> Vec<u8> { |
| 22 | match self { | 22 | match self { |
| 23 | ByteOrder::Le => num.to_le_bytes().to_vec(), | 23 | Self::Le => num.to_le_bytes().to_vec(), |
| 24 | ByteOrder::Be => num.to_be_bytes().to_vec(), | 24 | Self::Be => num.to_be_bytes().to_vec(), |
| 25 | ByteOrder::Ne => num.to_ne_bytes().to_vec(), | 25 | Self::Ne => num.to_ne_bytes().to_vec(), |
| 26 | } | 26 | } |
| 27 | } | 27 | } |
| 28 | 28 | ||
| 29 | pub fn $to(&self, bytes: [u8; size_of::<$n>()]) -> $n { | 29 | pub fn $to(&self, bytes: [u8; size_of::<$n>()]) -> $n { |
| 30 | match self { | 30 | match self { |
| 31 | ByteOrder::Le => $n::from_le_bytes(bytes), | 31 | Self::Le => $n::from_le_bytes(bytes), |
| 32 | ByteOrder::Be => $n::from_be_bytes(bytes), | 32 | Self::Be => $n::from_be_bytes(bytes), |
| 33 | ByteOrder::Ne => $n::from_ne_bytes(bytes), | 33 | Self::Ne => $n::from_ne_bytes(bytes), |
| 34 | } | 34 | } |
| 35 | } | 35 | } |
| 36 | )+} | 36 | )+} |
| @@ -55,10 +55,10 @@ impl_byte_order!( | |||
| 55 | impl VariantIndexType { | 55 | impl VariantIndexType { |
| 56 | pub fn cast(&self, num: u32, byte_order: &ByteOrder) -> Vec<u8> { | 56 | pub fn cast(&self, num: u32, byte_order: &ByteOrder) -> Vec<u8> { |
| 57 | match self { | 57 | match self { |
| 58 | VariantIndexType::U8 => byte_order.from_u8(num as u8), | 58 | Self::U8 => byte_order.from_u8(num as u8), |
| 59 | VariantIndexType::U16 => byte_order.form_u16(num as u16), | 59 | Self::U16 => byte_order.form_u16(num as u16), |
| 60 | VariantIndexType::U32 => byte_order.form_u32(num as u32), | 60 | Self::U32 => byte_order.form_u32(num), |
| 61 | VariantIndexType::U64 => byte_order.form_u64(num as u64), | 61 | Self::U64 => byte_order.form_u64(num as u64), |
| 62 | } | 62 | } |
| 63 | } | 63 | } |
| 64 | } | 64 | } |
diff --git a/src/zip/driver.rs b/src/zip/driver.rs index e5aa58d..8e8c27c 100644 --- a/src/zip/driver.rs +++ b/src/zip/driver.rs | |||
| @@ -1,7 +1,8 @@ | |||
| 1 | use crate::driver::{ArchiveRead, ArchiveWrite, Driver}; | 1 | use crate::driver::{ArchiveRead, ArchiveWrite, Driver}; |
| 2 | use crate::zip::error::{ZipError, ZipResult}; | 2 | use crate::zip::file::CompressionMethod; |
| 3 | use crate::zip::structs::{deserialize, EOCDR64Locator, CDR, EOCDR, EOCDR64}; | 3 | use crate::zip::structs::{deserialize, EOCDR64Locator, ExtraHeader, CDR, EOCDR, EOCDR64}; |
| 4 | use crate::zip::ZipFile; | 4 | use crate::zip::{ZipError, ZipFile, ZipResult}; |
| 5 | use chrono::{Local, NaiveDate, NaiveDateTime, NaiveTime}; | ||
| 5 | use std::collections::HashMap as Map; | 6 | use std::collections::HashMap as Map; |
| 6 | use std::fs::File; | 7 | use std::fs::File; |
| 7 | use std::io::{Read, Seek, SeekFrom, Write}; | 8 | use std::io::{Read, Seek, SeekFrom, Write}; |
| @@ -41,7 +42,7 @@ impl<IO: Read + Seek> ArchiveRead for Zip<IO> { | |||
| 41 | io.read(&mut buf)?; | 42 | io.read(&mut buf)?; |
| 42 | buf | 43 | buf |
| 43 | }; | 44 | }; |
| 44 | let eocdr: EOCDR = deserialize(&buf).map_err(|_| ZipError::InvalidEOCDR)?; | 45 | let eocdr: EOCDR = deserialize(&buf).unwrap(); |
| 45 | let comment = { | 46 | let comment = { |
| 46 | let mut buf: Vec<u8> = vec![0; eocdr.comment_len as usize]; | 47 | let mut buf: Vec<u8> = vec![0; eocdr.comment_len as usize]; |
| 47 | io.read(&mut buf)?; | 48 | io.read(&mut buf)?; |
| @@ -55,31 +56,29 @@ impl<IO: Read + Seek> ArchiveRead for Zip<IO> { | |||
| 55 | io.read(&mut buf)?; | 56 | io.read(&mut buf)?; |
| 56 | buf | 57 | buf |
| 57 | }; | 58 | }; |
| 58 | let (cd_pointer, cd_size, cd_records) = if u32::from_le_bytes(buf[0..4].try_into().unwrap()) | 59 | let (cd_pointer, cd_size, cd_records) = |
| 59 | == 0x07064b50 | 60 | if u32::from_le_bytes(buf[0..4].try_into().unwrap()) == 0x07064b50 { |
| 60 | { | 61 | let eocdr64locator: EOCDR64Locator = deserialize(&buf[4..]).unwrap(); |
| 61 | let eocdr64locator: EOCDR64Locator = | 62 | |
| 62 | deserialize(&buf[4..]).map_err(|_| ZipError::InvalidEOCDR64Locator)?; | 63 | io.seek(SeekFrom::Start(eocdr64locator.eocdr64_pointer))?; |
| 63 | 64 | let buf = { | |
| 64 | io.seek(SeekFrom::Start(eocdr64locator.eocdr64_pointer))?; | 65 | let mut buf = [0; 56]; |
| 65 | let buf = { | 66 | io.read(&mut buf)?; |
| 66 | let mut buf = [0; 56]; | 67 | buf |
| 67 | io.read(&mut buf)?; | 68 | }; |
| 68 | buf | 69 | if u32::from_le_bytes(buf[0..4].try_into().unwrap()) != 0x06064b50 { |
| 70 | return Err(ZipError::InvalidEOCDR64Signature.into()); | ||
| 71 | } | ||
| 72 | let eocdr64: EOCDR64 = deserialize(&buf[4..]).unwrap(); | ||
| 73 | |||
| 74 | (eocdr64.cd_pointer, eocdr64.cd_size, eocdr64.cd_records) | ||
| 75 | } else { | ||
| 76 | ( | ||
| 77 | eocdr.cd_pointer as u64, | ||
| 78 | eocdr.cd_size as u64, | ||
| 79 | eocdr.cd_records as u64, | ||
| 80 | ) | ||
| 69 | }; | 81 | }; |
| 70 | if u32::from_le_bytes(buf[0..4].try_into().unwrap()) != 0x06064b50 { | ||
| 71 | return Err(ZipError::InvalidEOCDR64Signature.into()); | ||
| 72 | } | ||
| 73 | let eocdr64: EOCDR64 = deserialize(&buf[4..]).map_err(|_| ZipError::InvalidEOCDR64)?; | ||
| 74 | |||
| 75 | (eocdr64.cd_pointer, eocdr64.cd_size, eocdr64.cd_records) | ||
| 76 | } else { | ||
| 77 | ( | ||
| 78 | eocdr.cd_pointer as u64, | ||
| 79 | eocdr.cd_size as u64, | ||
| 80 | eocdr.cd_records as u64, | ||
| 81 | ) | ||
| 82 | }; | ||
| 83 | 82 | ||
| 84 | // Read cd records | 83 | // Read cd records |
| 85 | let mut files = Map::with_capacity(cd_records as usize); | 84 | let mut files = Map::with_capacity(cd_records as usize); |
| @@ -96,7 +95,7 @@ impl<IO: Read + Seek> ArchiveRead for Zip<IO> { | |||
| 96 | return Err(ZipError::InvalidCDRSignature.into()); | 95 | return Err(ZipError::InvalidCDRSignature.into()); |
| 97 | } | 96 | } |
| 98 | p += 4; | 97 | p += 4; |
| 99 | let cdr: CDR = deserialize(&buf[p..p + 42]).map_err(|_| ZipError::InvalidCDR)?; | 98 | let cdr: CDR = deserialize(&buf[p..p + 42]).unwrap(); |
| 100 | p += 42; | 99 | p += 42; |
| 101 | let name = String::from_utf8(buf[p..p + cdr.name_len as usize].into()).unwrap(); | 100 | let name = String::from_utf8(buf[p..p + cdr.name_len as usize].into()).unwrap(); |
| 102 | p += cdr.name_len as usize; | 101 | p += cdr.name_len as usize; |
| @@ -105,15 +104,61 @@ impl<IO: Read + Seek> ArchiveRead for Zip<IO> { | |||
| 105 | let comment = String::from_utf8(buf[p..p + cdr.comment_len as usize].into()).unwrap(); | 104 | let comment = String::from_utf8(buf[p..p + cdr.comment_len as usize].into()).unwrap(); |
| 106 | p += cdr.comment_len as usize; | 105 | p += cdr.comment_len as usize; |
| 107 | 106 | ||
| 107 | let mut compressed_size = cdr.compressed_size as u64; | ||
| 108 | let mut size = cdr.size as u64; | ||
| 109 | let mut header_pointer = cdr.header_pointer as u64; | ||
| 110 | |||
| 111 | let mut ep: usize = 0; | ||
| 112 | while ep < cdr.extra_field_len as usize { | ||
| 113 | let header: ExtraHeader = deserialize(&extra_fields[ep..ep + 4]).unwrap(); | ||
| 114 | ep += 4; | ||
| 115 | match header.id { | ||
| 116 | 0x0001 => { | ||
| 117 | if size == 0xFFFFFFFF { | ||
| 118 | compressed_size = deserialize(&extra_fields[ep..ep + 8]).unwrap(); | ||
| 119 | ep += 8; | ||
| 120 | } | ||
| 121 | if compressed_size == 0xFFFFFFFF { | ||
| 122 | size = deserialize(&extra_fields[ep..ep + 8]).unwrap(); | ||
| 123 | ep += 8; | ||
| 124 | } | ||
| 125 | if header_pointer == 0xFFFFFFFF { | ||
| 126 | header_pointer = deserialize(&extra_fields[ep..ep + 8]).unwrap(); | ||
| 127 | ep += 8; | ||
| 128 | } | ||
| 129 | if cdr.disk == 0xFFFF { | ||
| 130 | ep += 4 | ||
| 131 | } | ||
| 132 | } | ||
| 133 | _ => ep += header.size as usize, | ||
| 134 | } | ||
| 135 | } | ||
| 136 | |||
| 108 | files.insert( | 137 | files.insert( |
| 109 | name.clone(), | 138 | name.clone(), |
| 110 | ZipFile::new( | 139 | ZipFile::new( |
| 140 | CompressionMethod::from_struct_id(cdr.compression_method)?, | ||
| 141 | NaiveDateTime::new( | ||
| 142 | NaiveDate::from_ymd_opt( | ||
| 143 | (cdr.dos_date as i32 >> 9 & 0x7F) + 1980, | ||
| 144 | cdr.dos_date as u32 >> 5 & 0xF, | ||
| 145 | cdr.dos_date as u32 & 0x1F, | ||
| 146 | ) | ||
| 147 | .ok_or(ZipError::InvalidDate)?, | ||
| 148 | NaiveTime::from_hms_opt( | ||
| 149 | (cdr.dos_time as u32 >> 11) & 0x1F, | ||
| 150 | (cdr.dos_time as u32 >> 5) & 0x3F, | ||
| 151 | (cdr.dos_time as u32 & 0x1F) * 2, | ||
| 152 | ) | ||
| 153 | .ok_or(ZipError::InvalidTime)?, | ||
| 154 | ) | ||
| 155 | .and_local_timezone(Local) | ||
| 156 | .unwrap(), | ||
| 157 | cdr.crc, | ||
| 158 | compressed_size, | ||
| 159 | size, | ||
| 160 | header_pointer, | ||
| 111 | name, | 161 | name, |
| 112 | cdr.dos_date, | ||
| 113 | cdr.dos_time, | ||
| 114 | cdr.compression_method, | ||
| 115 | cdr.compressed_size as u64, | ||
| 116 | cdr.size as u64, | ||
| 117 | comment, | 162 | comment, |
| 118 | ), | 163 | ), |
| 119 | ); | 164 | ); |
diff --git a/src/zip/error.rs b/src/zip/error.rs index 18bbb22..1c5527c 100644 --- a/src/zip/error.rs +++ b/src/zip/error.rs | |||
| @@ -7,15 +7,14 @@ pub type ZipResult<T> = ArchiveResult<T, ZipError>; | |||
| 7 | #[derive(Debug)] | 7 | #[derive(Debug)] |
| 8 | pub enum ZipError { | 8 | pub enum ZipError { |
| 9 | EOCDRNotFound, | 9 | EOCDRNotFound, |
| 10 | InvalidEOCDR, | ||
| 11 | InvalidArchiveComment, | ||
| 12 | |||
| 13 | InvalidEOCDR64Locator, | ||
| 14 | InvalidEOCDR64Signature, | 10 | InvalidEOCDR64Signature, |
| 15 | InvalidEOCDR64, | ||
| 16 | |||
| 17 | InvalidCDRSignature, | 11 | InvalidCDRSignature, |
| 18 | InvalidCDR, | 12 | |
| 13 | InvalidArchiveComment, | ||
| 14 | InvalidCompressionMethod, | ||
| 15 | UnsupportedCompressionMethod, | ||
| 16 | InvalidDate, | ||
| 17 | InvalidTime, | ||
| 19 | InvalidFileName, | 18 | InvalidFileName, |
| 20 | InvalidFileComment, | 19 | InvalidFileComment, |
| 21 | } | 20 | } |
| @@ -32,25 +31,24 @@ impl From<ZipError> for ArchiveError<ZipError> { | |||
| 32 | impl Display for ZipError { | 31 | impl Display for ZipError { |
| 33 | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { | 32 | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { |
| 34 | match self { | 33 | match self { |
| 35 | ZipError::EOCDRNotFound => write!(f, "End of central directory record not found"), | 34 | Self::EOCDRNotFound => write!(f, "End of central directory record not found"), |
| 36 | ZipError::InvalidEOCDR => write!(f, "Invalid end of central directory record"), | 35 | Self::InvalidEOCDR64Signature => { |
| 37 | ZipError::InvalidArchiveComment => write!(f, "Invalid archive comment"), | ||
| 38 | ZipError::InvalidEOCDR64Locator => { | ||
| 39 | write!(f, "Invalid zip64 end of central directory locator") | ||
| 40 | } | ||
| 41 | ZipError::InvalidEOCDR64Signature => { | ||
| 42 | write!( | 36 | write!( |
| 43 | f, | 37 | f, |
| 44 | "Invalid signature of zip64 end of central directory record" | 38 | "Invalid signature of zip64 end of central directory record" |
| 45 | ) | 39 | ) |
| 46 | } | 40 | } |
| 47 | ZipError::InvalidEOCDR64 => write!(f, "Invalid zip64 end of central directory record"), | 41 | Self::InvalidCDRSignature => { |
| 48 | ZipError::InvalidCDRSignature => { | ||
| 49 | write!(f, "Invalid signature of central directory record") | 42 | write!(f, "Invalid signature of central directory record") |
| 50 | } | 43 | } |
| 51 | ZipError::InvalidCDR => write!(f, "Invalid central directory record"), | 44 | |
| 52 | ZipError::InvalidFileName => write!(f, "Invalid file name"), | 45 | Self::InvalidArchiveComment => write!(f, "Invalid archive comment"), |
| 53 | ZipError::InvalidFileComment => write!(f, "Invalid file comment"), | 46 | Self::InvalidCompressionMethod => writeln!(f, "Invalid compression method"), |
| 47 | Self::UnsupportedCompressionMethod => writeln!(f, "Unsupported compression method"), | ||
| 48 | Self::InvalidDate => write!(f, "Invalid date"), | ||
| 49 | Self::InvalidTime => write!(f, "Invalid time"), | ||
| 50 | Self::InvalidFileName => write!(f, "Invalid file name"), | ||
| 51 | Self::InvalidFileComment => write!(f, "Invalid file comment"), | ||
| 54 | } | 52 | } |
| 55 | } | 53 | } |
| 56 | } | 54 | } |
diff --git a/src/zip/file.rs b/src/zip/file.rs index d5b3327..f735d65 100644 --- a/src/zip/file.rs +++ b/src/zip/file.rs | |||
| @@ -1,45 +1,66 @@ | |||
| 1 | use crate::driver::ArchiveFile; | 1 | use crate::driver::ArchiveFile; |
| 2 | use chrono::{NaiveDate, NaiveDateTime, NaiveTime}; | 2 | use crate::zip::{ZipError, ZipResult}; |
| 3 | use chrono::{DateTime, Local}; | ||
| 4 | |||
| 5 | pub enum CompressionMethod { | ||
| 6 | Store, | ||
| 7 | Deflate, | ||
| 8 | BZIP2, | ||
| 9 | LZMA, | ||
| 10 | ZStd, | ||
| 11 | XZ, | ||
| 12 | } | ||
| 13 | |||
| 14 | impl CompressionMethod { | ||
| 15 | pub(crate) fn from_struct_id(id: u16) -> ZipResult<Self> { | ||
| 16 | match id { | ||
| 17 | 0 => Ok(Self::Store), | ||
| 18 | 8 => Ok(Self::Deflate), | ||
| 19 | 12 => Ok(Self::BZIP2), | ||
| 20 | 14 => Ok(Self::LZMA), | ||
| 21 | 93 => Ok(Self::ZStd), | ||
| 22 | 95 => Ok(Self::XZ), | ||
| 23 | 1..=7 | 9..=11 | 13 | 15..=20 | 94 | 96..=99 => { | ||
| 24 | Err(ZipError::UnsupportedCompressionMethod.into()) | ||
| 25 | } | ||
| 26 | 21..=92 | 100.. => Err(ZipError::InvalidCompressionMethod.into()), | ||
| 27 | } | ||
| 28 | } | ||
| 29 | } | ||
| 3 | 30 | ||
| 4 | pub struct ZipFile { | 31 | pub struct ZipFile { |
| 5 | pub name: String, | 32 | pub compression_method: CompressionMethod, |
| 6 | pub datetime: NaiveDateTime, | 33 | pub datetime: DateTime<Local>, |
| 7 | pub compression_method: u16, | 34 | pub crc: u32, |
| 8 | pub compressed_size: u64, | 35 | pub compressed_size: u64, |
| 9 | pub size: u64, | 36 | pub size: u64, |
| 37 | pub header_pointer: u64, | ||
| 38 | pub name: String, | ||
| 10 | pub comment: String, | 39 | pub comment: String, |
| 11 | } | 40 | } |
| 12 | 41 | ||
| 13 | impl ArchiveFile for ZipFile {} | ||
| 14 | |||
| 15 | impl ZipFile { | 42 | impl ZipFile { |
| 16 | pub(crate) fn new( | 43 | pub fn new( |
| 17 | name: String, | 44 | compression_method: CompressionMethod, |
| 18 | dos_date: u16, | 45 | datetime: DateTime<Local>, |
| 19 | dos_time: u16, | 46 | crc: u32, |
| 20 | compression_method: u16, | ||
| 21 | compressed_size: u64, | 47 | compressed_size: u64, |
| 22 | size: u64, | 48 | size: u64, |
| 49 | header_pointer: u64, | ||
| 50 | name: String, | ||
| 23 | comment: String, | 51 | comment: String, |
| 24 | ) -> Self { | 52 | ) -> Self { |
| 25 | let year = (dos_date >> 9 & 0x7F) + 1980; | ||
| 26 | let month = dos_date >> 5 & 0xF; | ||
| 27 | let day = dos_date & 0x1F; | ||
| 28 | |||
| 29 | let hour = (dos_time >> 11) & 0x1F; | ||
| 30 | let minute = (dos_time >> 5) & 0x3F; | ||
| 31 | let seconds = (dos_time & 0x1F) * 2; | ||
| 32 | |||
| 33 | Self { | 53 | Self { |
| 34 | name, | ||
| 35 | datetime: NaiveDateTime::new( | ||
| 36 | NaiveDate::from_ymd_opt(year as i32, month as u32, day as u32).unwrap(), | ||
| 37 | NaiveTime::from_hms_opt(hour as u32, minute as u32, seconds as u32).unwrap(), | ||
| 38 | ), | ||
| 39 | compression_method, | 54 | compression_method, |
| 55 | datetime, | ||
| 56 | crc, | ||
| 40 | compressed_size, | 57 | compressed_size, |
| 41 | size, | 58 | size, |
| 59 | header_pointer, | ||
| 60 | name, | ||
| 42 | comment, | 61 | comment, |
| 43 | } | 62 | } |
| 44 | } | 63 | } |
| 45 | } | 64 | } |
| 65 | |||
| 66 | impl ArchiveFile for ZipFile {} | ||
diff --git a/src/zip/mod.rs b/src/zip/mod.rs index 5aeca97..8601526 100644 --- a/src/zip/mod.rs +++ b/src/zip/mod.rs | |||
| @@ -4,5 +4,5 @@ mod file; | |||
| 4 | mod structs; | 4 | mod structs; |
| 5 | 5 | ||
| 6 | pub use driver::Zip; | 6 | pub use driver::Zip; |
| 7 | pub use error::ZipError; | 7 | pub use error::{ZipError, ZipResult}; |
| 8 | pub use file::ZipFile; | 8 | pub use file::ZipFile; |
diff --git a/src/zip/structs.rs b/src/zip/structs.rs index 0f9579e..3a93c1b 100644 --- a/src/zip/structs.rs +++ b/src/zip/structs.rs | |||
| @@ -40,7 +40,7 @@ pub struct CDR { | |||
| 40 | pub compression_method: u16, | 40 | pub compression_method: u16, |
| 41 | pub dos_time: u16, | 41 | pub dos_time: u16, |
| 42 | pub dos_date: u16, | 42 | pub dos_date: u16, |
| 43 | pub crc32: u32, | 43 | pub crc: u32, |
| 44 | pub compressed_size: u32, | 44 | pub compressed_size: u32, |
| 45 | pub size: u32, | 45 | pub size: u32, |
| 46 | pub name_len: u16, | 46 | pub name_len: u16, |
| @@ -52,6 +52,12 @@ pub struct CDR { | |||
| 52 | pub header_pointer: u32, | 52 | pub header_pointer: u32, |
| 53 | } | 53 | } |
| 54 | 54 | ||
| 55 | #[derive(Serialize, Deserialize)] | ||
| 56 | pub struct ExtraHeader { | ||
| 57 | pub id: u16, | ||
| 58 | pub size: u16, | ||
| 59 | } | ||
| 60 | |||
| 55 | pub fn serialize<T: Serialize>(object: &mut T) -> StructResult<Vec<u8>> { | 61 | pub fn serialize<T: Serialize>(object: &mut T) -> StructResult<Vec<u8>> { |
| 56 | Settings::default().serialize(object) | 62 | Settings::default().serialize(object) |
| 57 | } | 63 | } |
