pacenotes_installer\zip/
entry_data.rs1const LOCAL_HEADER_LENGTH: usize = 30;
2const METHOD_STORED: u16 = 0;
3const METHOD_DEFLATED: u16 = 8;
4
5pub fn read(
8 zip: &[u8],
9 entry: &super::central_directory::Entry,
10) -> Result<Vec<u8>, super::ZipError> {
11 let data = compressed_bytes(zip, entry)?;
12 let content = match entry.method {
13 METHOD_STORED => data.to_vec(),
14 METHOD_DEFLATED => {
15 miniz_oxide::inflate::decompress_to_vec_with_limit(data, entry.uncompressed).map_err(
16 |e| {
17 super::ZipError::new(format!(
18 "{} could not be decompressed ({:?})",
19 entry.path, e.status
20 ))
21 },
22 )?
23 }
24 other => {
25 return Err(super::ZipError::new(format!(
26 "{} uses compression method {other}, which the installer cannot read",
27 entry.path
28 )))
29 }
30 };
31
32 if content.len() != entry.uncompressed {
33 return Err(super::ZipError::new(format!(
34 "{} is {} bytes but the package says {}",
35 entry.path,
36 content.len(),
37 entry.uncompressed
38 )));
39 }
40 if super::crc32::crc32(&content) != entry.crc32 {
41 return Err(super::ZipError::new(format!(
42 "{} is damaged (checksum mismatch); delete it from the cache and \
43 download it again",
44 entry.path
45 )));
46 }
47 Ok(content)
48}
49
50fn compressed_bytes<'a>(
53 zip: &'a [u8],
54 entry: &super::central_directory::Entry,
55) -> Result<&'a [u8], super::ZipError> {
56 let at = entry.local_offset;
57 if super::central_directory::u32_at(zip, at)
58 != Some(super::central_directory::SIGNATURE_LOCAL_HEADER)
59 {
60 return Err(super::ZipError::new(format!(
61 "{} is not where this package says it is",
62 entry.path
63 )));
64 }
65 let name_length = super::central_directory::u16_at(zip, at + 26)
66 .ok_or_else(super::ZipError::truncated)? as usize;
67 let extra_length = super::central_directory::u16_at(zip, at + 28)
68 .ok_or_else(super::ZipError::truncated)? as usize;
69 let start = at + LOCAL_HEADER_LENGTH + name_length + extra_length;
70 zip.get(start..start + entry.compressed)
71 .ok_or_else(super::ZipError::truncated)
72}