sevenz_rust2/
block.rs

1// In the 7zip specification this is called "folder". But since in the UI of 7zip they are called
2// "block" we chose to also call them under that name.
3#[derive(Debug, Default, Clone)]
4pub struct Block {
5    pub coders: Vec<Coder>,
6    pub has_crc: bool,
7    pub crc: u64,
8    pub(crate) total_input_streams: usize,
9    pub(crate) total_output_streams: usize,
10    pub(crate) bind_pairs: Vec<BindPair>,
11    pub(crate) packed_streams: Vec<u64>,
12    pub(crate) unpack_sizes: Vec<u64>,
13    pub(crate) num_unpack_sub_streams: usize,
14}
15
16impl Block {
17    pub(crate) fn find_bind_pair_for_in_stream(&self, index: usize) -> Option<usize> {
18        let index = index as u64;
19        (0..self.bind_pairs.len()).find(|&i| self.bind_pairs[i].in_index == index)
20    }
21
22    pub(crate) fn find_bind_pair_for_out_stream(&self, index: usize) -> Option<usize> {
23        let index = index as u64;
24        (0..self.bind_pairs.len()).find(|&i| self.bind_pairs[i].out_index == index)
25    }
26
27    pub fn get_unpack_size(&self) -> u64 {
28        if self.total_output_streams == 0 {
29            return 0;
30        }
31        for i in (0..self.total_output_streams).rev() {
32            if self.find_bind_pair_for_out_stream(i).is_none() {
33                return self.unpack_sizes[i];
34            }
35        }
36        0
37    }
38
39    pub fn get_unpack_size_for_coder(&self, coder: &Coder) -> u64 {
40        for i in 0..self.coders.len() {
41            if std::ptr::eq(&self.coders[i], coder) {
42                return self.unpack_sizes[i];
43            }
44        }
45        0
46    }
47
48    pub fn get_unpack_size_at_index(&self, index: usize) -> u64 {
49        self.unpack_sizes.get(index).cloned().unwrap_or_default()
50    }
51
52    pub fn ordered_coder_iter(&self) -> OrderedCoderIter {
53        OrderedCoderIter::new(self)
54    }
55}
56
57#[derive(Debug, Default, Clone, PartialEq, Eq)]
58pub struct Coder {
59    encoder_method_id: [u8; 0xF],
60    pub(crate) id_size: usize,
61    pub(crate) num_in_streams: u64,
62    pub(crate) num_out_streams: u64,
63    pub(crate) properties: Vec<u8>,
64}
65
66impl Coder {
67    pub fn encoder_method_id(&self) -> &[u8] {
68        &self.encoder_method_id[0..self.id_size]
69    }
70
71    pub(crate) fn decompression_method_id_mut(&mut self) -> &mut [u8] {
72        &mut self.encoder_method_id[0..self.id_size]
73    }
74}
75
76#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
77pub(crate) struct BindPair {
78    pub(crate) in_index: u64,
79    pub(crate) out_index: u64,
80}
81
82pub struct OrderedCoderIter<'a> {
83    block: &'a Block,
84    current: Option<u64>,
85}
86
87impl<'a> OrderedCoderIter<'a> {
88    fn new(block: &'a Block) -> Self {
89        let current = block.packed_streams.first().copied();
90        Self { block, current }
91    }
92}
93
94impl<'a> Iterator for OrderedCoderIter<'a> {
95    type Item = (usize, &'a Coder);
96
97    fn next(&mut self) -> Option<Self::Item> {
98        if let Some(i) = self.current {
99            self.current = if let Some(pair) = self.block.find_bind_pair_for_out_stream(i as usize)
100            {
101                Some(self.block.bind_pairs[pair].in_index)
102            } else {
103                None
104            };
105            self.block
106                .coders
107                .get(i as usize)
108                .map(|item| (i as usize, item))
109        } else {
110            None
111        }
112    }
113}