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