sevenz_rust2/
block.rs

1/// Represents a compression block.
2///
3/// A block contains one or more coders (compression/filter methods) that are chained
4/// together to process data.
5#[derive(Debug, Default, Clone)]
6pub struct Block {
7    /// Coders (compression/filter methods) in this block.
8    pub coders: Vec<Coder>,
9    /// Whether this block has a CRC checksum.
10    pub has_crc: bool,
11    /// CRC32 checksum of the block data.
12    pub crc: u64,
13    pub(crate) total_input_streams: usize,
14    pub(crate) total_output_streams: usize,
15    pub(crate) bind_pairs: Vec<BindPair>,
16    pub(crate) packed_streams: Vec<u64>,
17    pub(crate) unpack_sizes: Vec<u64>,
18    pub(crate) num_unpack_sub_streams: usize,
19}
20
21impl Block {
22    pub(crate) fn find_bind_pair_for_in_stream(&self, index: u64) -> Option<&BindPair> {
23        self.bind_pairs.iter().find(|bp| bp.in_index == index)
24    }
25
26    pub(crate) fn find_bind_pair_for_out_stream(&self, index: u64) -> Option<&BindPair> {
27        self.bind_pairs.iter().find(|bp| bp.out_index == index)
28    }
29
30    /// Returns the total uncompressed size of data in this block.
31    pub fn get_unpack_size(&self) -> u64 {
32        if self.total_output_streams == 0 {
33            return 0;
34        }
35        for i in (0..self.total_output_streams).rev() {
36            if self.find_bind_pair_for_out_stream(i as u64).is_none() {
37                return self.unpack_sizes[i];
38            }
39        }
40        0
41    }
42
43    /// Returns the uncompressed size for a specific coder within this block.
44    ///
45    /// # Arguments
46    /// * `coder` - The coder to get the unpack size for
47    pub fn get_unpack_size_for_coder(&self, coder: &Coder) -> u64 {
48        for i in 0..self.coders.len() {
49            if std::ptr::eq(&self.coders[i], coder) {
50                return self.unpack_sizes[i];
51            }
52        }
53        0
54    }
55
56    /// Returns the uncompressed size for the coder at the specified index.
57    ///
58    /// # Arguments
59    /// * `index` - The index of the coder to get the unpack size for
60    pub fn get_unpack_size_at_index(&self, index: usize) -> u64 {
61        self.unpack_sizes.get(index).cloned().unwrap_or_default()
62    }
63
64    /// Returns an iterator over the coders in their processing order.
65    ///
66    /// Coders are chained together in blocks, and this iterator follows the chain
67    /// from the first coder to the last in their proper execution order.
68    pub fn ordered_coder_iter(&self) -> OrderedCoderIter<'_> {
69        OrderedCoderIter::new(self)
70    }
71}
72
73/// Represents a single coder within a compression block.
74///
75/// A coder defines a specific compression method, filter, or encryption method
76/// used to process data within a block.
77#[derive(Debug, Default, Clone, PartialEq, Eq)]
78pub struct Coder {
79    encoder_method_id: [u8; 0xF],
80    pub(crate) id_size: usize,
81    pub(crate) num_in_streams: u64,
82    pub(crate) num_out_streams: u64,
83    pub(crate) properties: Vec<u8>,
84}
85
86impl Coder {
87    /// Returns the encoder method ID for this coder.
88    ///
89    /// This ID identifies the specific compression method, filter, or encryption
90    /// method used by this coder.
91    pub fn encoder_method_id(&self) -> &[u8] {
92        &self.encoder_method_id[0..self.id_size]
93    }
94
95    pub(crate) fn decompression_method_id_mut(&mut self) -> &mut [u8] {
96        &mut self.encoder_method_id[0..self.id_size]
97    }
98}
99
100#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
101pub(crate) struct BindPair {
102    pub(crate) in_index: u64,
103    pub(crate) out_index: u64,
104}
105
106/// Iterator that yields coders in their processing order within a block.
107///
108/// Coders are chained together in blocks, and this iterator follows the chain
109/// from the first coder to the last in their proper execution order.
110pub struct OrderedCoderIter<'a> {
111    block: &'a Block,
112    current: Option<u64>,
113}
114
115impl<'a> OrderedCoderIter<'a> {
116    fn new(block: &'a Block) -> Self {
117        let current = block.packed_streams.first().copied();
118        Self { block, current }
119    }
120}
121
122impl<'a> Iterator for OrderedCoderIter<'a> {
123    type Item = (usize, &'a Coder);
124
125    fn next(&mut self) -> Option<Self::Item> {
126        let i = self.current?;
127        self.current = self
128            .block
129            .find_bind_pair_for_out_stream(i)
130            .map(|bp| bp.in_index);
131        self.block
132            .coders
133            .get(i as usize)
134            .map(|item| (i as usize, item))
135    }
136}