1use crate::format::magic::Magic;
4use core::mem;
5use std::io::{self, Write};
6
7#[derive(Debug, Copy, Clone, PartialEq)]
9pub enum ZipDataDescriptor {
10 ZipDataDescriptorBlock(ZipDataDescriptorBlock),
12 Zip64DataDescriptorBlock(Zip64DataDescriptorBlock),
14}
15
16#[derive(Copy, Clone, Debug, PartialEq)]
18pub struct ZipDataDescriptorBlock {
19 pub crc32: u32,
21 pub compressed_size: u32,
23 pub uncompressed_size: u32,
25}
26
27impl ZipDataDescriptorBlock {
28 pub const SIZE: usize = mem::size_of::<u32>()
30 + mem::size_of::<u32>()
31 + mem::size_of::<u32>()
32 + mem::size_of::<u32>();
33 pub const MAGIC: Magic = Magic::DATA_DESCRIPTOR_SIGNATURE;
35
36 pub fn parse(buff: &[u8; Self::SIZE]) -> Result<Self, &'static str> {
38 let magic = Magic::from_le_bytes([buff[0], buff[1], buff[2], buff[3]]);
39 if magic != Self::MAGIC {
40 return Err("Invalid data descriptor header");
41 }
42 let crc32 = u32::from_le_bytes([buff[4], buff[5], buff[6], buff[7]]);
43 let compressed_size = u32::from_le_bytes([buff[8], buff[9], buff[10], buff[11]]);
44 let uncompressed_size = u32::from_le_bytes([buff[12], buff[13], buff[14], buff[15]]);
45
46 Ok(Self {
47 crc32,
48 compressed_size,
49 uncompressed_size,
50 })
51 }
52
53 pub fn write<W: Write>(&self, w: &mut W) -> io::Result<()> {
55 w.write_all(&Self::MAGIC.to_le_bytes())?;
56 w.write_all(&self.crc32.to_le_bytes())?;
57 w.write_all(&self.compressed_size.to_le_bytes())?;
58 w.write_all(&self.uncompressed_size.to_le_bytes())?;
59 Ok(())
60 }
61}
62
63#[derive(Copy, Clone, Debug, PartialEq)]
65pub struct Zip64DataDescriptorBlock {
66 pub crc32: u32,
68 pub compressed_size: u64,
70 pub uncompressed_size: u64,
72}
73impl Zip64DataDescriptorBlock {
74 pub const SIZE: usize = mem::size_of::<u32>()
76 + mem::size_of::<u32>()
77 + mem::size_of::<u64>()
78 + mem::size_of::<u64>();
79 pub const MAGIC: Magic = Magic::DATA_DESCRIPTOR_SIGNATURE;
81
82 pub fn parse(buff: &[u8; Self::SIZE]) -> Result<Self, &'static str> {
84 let magic = Magic::from_le_bytes([buff[0], buff[1], buff[2], buff[3]]);
85 if magic != Self::MAGIC {
86 return Err("Invalid zip64 data descriptor header");
87 }
88 let crc32 = u32::from_le_bytes([buff[4], buff[5], buff[6], buff[7]]);
89 let compressed_size = u64::from_le_bytes([
90 buff[8], buff[9], buff[10], buff[11], buff[12], buff[13], buff[14], buff[15],
91 ]);
92 let uncompressed_size = u64::from_le_bytes([
93 buff[16], buff[17], buff[18], buff[19], buff[20], buff[21], buff[22], buff[23],
94 ]);
95
96 Ok(Self {
97 crc32,
98 compressed_size,
99 uncompressed_size,
100 })
101 }
102
103 pub fn write<W: Write>(&self, w: &mut W) -> io::Result<()> {
105 w.write_all(&Self::MAGIC.to_le_bytes())?;
106 w.write_all(&self.crc32.to_le_bytes())?;
107 w.write_all(&self.compressed_size.to_le_bytes())?;
108 w.write_all(&self.uncompressed_size.to_le_bytes())?;
109 Ok(())
110 }
111}
112
113#[cfg(test)]
114mod tests {
115 use crate::format::data_descriptor::Zip64DataDescriptorBlock;
116 use crate::format::data_descriptor::ZipDataDescriptorBlock;
117
118 #[test]
119 fn test_data_descriptor_wrong_sig() {
120 assert_eq!(
121 ZipDataDescriptorBlock::MAGIC.to_le_bytes(),
122 [0x50, 0x4b, 0x07, 0x08]
123 );
124 let data_desc =
125 ZipDataDescriptorBlock::parse(&[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]);
126 assert!(data_desc.is_err(),);
127
128 assert_eq!(
130 Zip64DataDescriptorBlock::MAGIC.to_le_bytes(),
131 [0x50, 0x4b, 0x07, 0x08]
132 );
133 let data_desc = Zip64DataDescriptorBlock::parse(&[
134 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,
135 ]);
136 assert!(data_desc.is_err(),);
137 }
138
139 #[test]
140 fn test_data_descriptor_parsing() {
141 let raw = [
142 0x50, 0x4b, 0x07, 0x08, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
143 ];
144 let data_desc = ZipDataDescriptorBlock::parse(&raw).unwrap();
145 assert_eq!(
146 data_desc,
147 ZipDataDescriptorBlock {
148 crc32: u32::from_le_bytes(raw[4..8].try_into().unwrap()),
149 compressed_size: u32::from_le_bytes(raw[8..12].try_into().unwrap()),
150 uncompressed_size: u32::from_le_bytes(raw[12..16].try_into().unwrap()),
151 }
152 );
153 let raw = [
154 0x50, 0x4b, 0x07, 0x08, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
155 21, 22, 23,
156 ];
157 let data_desc = Zip64DataDescriptorBlock::parse(&raw).unwrap();
158 assert_eq!(
159 data_desc,
160 Zip64DataDescriptorBlock {
161 crc32: u32::from_le_bytes(raw[4..8].try_into().unwrap()),
162 compressed_size: u64::from_le_bytes(raw[8..16].try_into().unwrap()),
163 uncompressed_size: u64::from_le_bytes(raw[16..24].try_into().unwrap()),
164 }
165 );
166 }
167}