gpg_inspector_lib/packet/
compressed_data.rs1use crate::error::Result;
9use crate::lookup::lookup_compression_algorithm;
10use crate::stream::ByteStream;
11
12use super::Field;
13
14#[derive(Debug, Clone)]
16pub struct CompressedDataPacket {
17 pub algorithm: u8,
19 pub compressed_data: Vec<u8>,
21}
22
23pub fn parse_compressed_data(
25 stream: &mut ByteStream,
26 fields: &mut Vec<Field>,
27 body_offset: usize,
28) -> Result<CompressedDataPacket> {
29 let algo_start = body_offset + stream.pos();
30 let algorithm = stream.octet()?;
31 let algo_lookup = lookup_compression_algorithm(algorithm);
32 fields.push(Field::field(
33 "Algorithm",
34 algo_lookup.display(),
35 (algo_start, algo_start + 1),
36 ));
37
38 let data_start = body_offset + stream.pos();
39 let compressed_data = stream.rest();
40 let data_end = body_offset + stream.pos();
41
42 if !compressed_data.is_empty() {
43 fields.push(Field::field(
44 "Compressed Data",
45 format!("{} bytes", compressed_data.len()),
46 (data_start, data_end),
47 ));
48 }
49
50 Ok(CompressedDataPacket {
51 algorithm,
52 compressed_data,
53 })
54}
55
56#[cfg(feature = "decompress")]
58pub const MAX_DECOMPRESSED: u64 = 64 * 1024 * 1024;
59
60#[cfg(feature = "decompress")]
69pub fn decompress(algorithm: u8, data: &[u8]) -> std::result::Result<Vec<u8>, String> {
70 use std::io::Read;
71
72 let mut out = Vec::new();
73 let limit = MAX_DECOMPRESSED + 1;
74 let read_result = match algorithm {
75 0 => {
76 out.extend_from_slice(data);
77 Ok(data.len())
78 }
79 1 => flate2::read::DeflateDecoder::new(data)
80 .take(limit)
81 .read_to_end(&mut out),
82 2 => flate2::read::ZlibDecoder::new(data)
83 .take(limit)
84 .read_to_end(&mut out),
85 3 => bzip2::read::BzDecoder::new(data)
86 .take(limit)
87 .read_to_end(&mut out),
88 n => return Err(format!("unsupported compression algorithm {}", n)),
89 };
90
91 match read_result {
92 Ok(_) if out.len() as u64 > MAX_DECOMPRESSED => Err(format!(
93 "decompressed data exceeds {} MiB cap; not expanded",
94 MAX_DECOMPRESSED / (1024 * 1024)
95 )),
96 Ok(_) => Ok(out),
97 Err(e) => Err(format!("decompression failed: {}", e)),
98 }
99}