lzma_rust2/
lib.rs

1// TODO: There is a lot of code left that only the "encode" feature uses.
2#![allow(dead_code)]
3
4mod decoder;
5mod lz;
6mod lzma2_reader;
7mod lzma_reader;
8mod range_dec;
9mod state;
10
11#[cfg(feature = "encoder")]
12mod enc;
13
14#[cfg(feature = "encoder")]
15pub use enc::*;
16pub use lzma2_reader::get_memory_usage as lzma2_get_memory_usage;
17pub use lzma2_reader::LZMA2Reader;
18pub use lzma_reader::get_memory_usage as lzma_get_memory_usage;
19pub use lzma_reader::get_memory_usage_by_props as lzma_get_memory_usage_by_props;
20pub use lzma_reader::LZMAReader;
21
22use state::*;
23
24pub const DICT_SIZE_MIN: u32 = 4096;
25pub const DICT_SIZE_MAX: u32 = u32::MAX & !15_u32;
26
27const LOW_SYMBOLS: usize = 1 << 3;
28const MID_SYMBOLS: usize = 1 << 3;
29const HIGH_SYMBOLS: usize = 1 << 8;
30
31const POS_STATES_MAX: usize = 1 << 4;
32const MATCH_LEN_MIN: usize = 2;
33const MATCH_LEN_MAX: usize = MATCH_LEN_MIN + LOW_SYMBOLS + MID_SYMBOLS + HIGH_SYMBOLS - 1;
34
35const DIST_STATES: usize = 4;
36const DIST_SLOTS: usize = 1 << 6;
37const DIST_MODEL_START: usize = 4;
38const DIST_MODEL_END: usize = 14;
39const FULL_DISTANCES: usize = 1 << (DIST_MODEL_END / 2);
40
41const ALIGN_BITS: usize = 4;
42const ALIGN_SIZE: usize = 1 << ALIGN_BITS;
43const ALIGN_MASK: usize = ALIGN_SIZE - 1;
44
45const REPS: usize = 4;
46
47const SHIFT_BITS: u32 = 8;
48const TOP_MASK: u32 = 0xFF000000;
49const BIT_MODEL_TOTAL_BITS: u32 = 11;
50const BIT_MODEL_TOTAL: u32 = 1 << BIT_MODEL_TOTAL_BITS;
51const PROB_INIT: u16 = (BIT_MODEL_TOTAL / 2) as u16;
52const MOVE_BITS: u32 = 5;
53const DIST_SPECIAL_INDEX: [usize; 10] = [0, 2, 4, 8, 12, 20, 28, 44, 60, 92];
54const DIST_SPECIAL_END: [usize; 10] = [2, 4, 8, 12, 20, 28, 44, 60, 92, 124];
55
56pub struct LZMACoder {
57    pub(crate) pos_mask: u32,
58    pub(crate) reps: [i32; REPS],
59    pub(crate) state: State,
60    pub(crate) is_match: [[u16; POS_STATES_MAX]; STATES],
61    pub(crate) is_rep: [u16; STATES],
62    pub(crate) is_rep0: [u16; STATES],
63    pub(crate) is_rep1: [u16; STATES],
64    pub(crate) is_rep2: [u16; STATES],
65    pub(crate) is_rep0_long: [[u16; POS_STATES_MAX]; STATES],
66    pub(crate) dist_slots: [[u16; DIST_SLOTS]; DIST_STATES],
67    dist_special: [u16; 124],
68    dist_align: [u16; ALIGN_SIZE],
69}
70
71pub(crate) fn coder_get_dict_size(len: usize) -> usize {
72    if len < DIST_STATES + MATCH_LEN_MIN {
73        len - MATCH_LEN_MIN
74    } else {
75        DIST_STATES - 1
76    }
77}
78
79pub(crate) fn get_dist_state(len: u32) -> u32 {
80    (if (len as usize) < DIST_STATES + MATCH_LEN_MIN {
81        len as usize - MATCH_LEN_MIN
82    } else {
83        DIST_STATES - 1
84    }) as u32
85}
86
87impl LZMACoder {
88    pub fn new(pb: usize) -> Self {
89        let mut c = Self {
90            pos_mask: (1 << pb) - 1,
91            reps: Default::default(),
92            state: Default::default(),
93            is_match: Default::default(),
94            is_rep: Default::default(),
95            is_rep0: Default::default(),
96            is_rep1: Default::default(),
97            is_rep2: Default::default(),
98            is_rep0_long: Default::default(),
99            dist_slots: [[Default::default(); DIST_SLOTS]; DIST_STATES],
100            dist_special: [Default::default(); 124],
101            dist_align: Default::default(),
102        };
103        c.reset();
104        c
105    }
106
107    pub fn reset(&mut self) {
108        self.reps = [0; REPS];
109        self.state.reset();
110        for ele in self.is_match.iter_mut() {
111            init_probs(ele);
112        }
113        init_probs(&mut self.is_rep);
114        init_probs(&mut self.is_rep0);
115        init_probs(&mut self.is_rep1);
116        init_probs(&mut self.is_rep2);
117
118        for ele in self.is_rep0_long.iter_mut() {
119            init_probs(ele);
120        }
121        for ele in self.dist_slots.iter_mut() {
122            init_probs(ele);
123        }
124        init_probs(&mut self.dist_special);
125        init_probs(&mut self.dist_align);
126    }
127
128    #[inline(always)]
129    pub fn get_dist_special(&mut self, i: usize) -> &mut [u16] {
130        &mut self.dist_special[DIST_SPECIAL_INDEX[i]..DIST_SPECIAL_END[i]]
131    }
132}
133
134#[inline(always)]
135pub(crate) fn init_probs(probs: &mut [u16]) {
136    probs.fill(PROB_INIT);
137}
138
139pub(crate) struct LiteralCoder {
140    lc: u32,
141    literal_pos_mask: u32,
142}
143
144#[derive(Debug, Clone, Copy)]
145pub(crate) struct LiteralSubcoder {
146    probs: [u16; 0x300],
147}
148
149impl LiteralSubcoder {
150    pub fn new() -> Self {
151        let probs = [PROB_INIT; 0x300];
152        Self { probs }
153    }
154
155    pub fn reset(&mut self) {
156        self.probs = [PROB_INIT; 0x300];
157    }
158}
159
160impl LiteralCoder {
161    pub fn new(lc: u32, lp: u32) -> Self {
162        Self {
163            lc,
164            literal_pos_mask: (1 << lp) - 1,
165        }
166    }
167
168    pub(crate) fn get_sub_coder_index(&self, prev_byte: u32, pos: u32) -> u32 {
169        let low = prev_byte >> (8 - self.lc);
170        let high = (pos & self.literal_pos_mask) << self.lc;
171        low + high
172    }
173}
174
175pub(crate) struct LengthCoder {
176    choice: [u16; 2],
177    low: [[u16; LOW_SYMBOLS]; POS_STATES_MAX],
178    mid: [[u16; MID_SYMBOLS]; POS_STATES_MAX],
179    high: [u16; HIGH_SYMBOLS],
180}
181
182impl LengthCoder {
183    pub fn new() -> Self {
184        Self {
185            choice: Default::default(),
186            low: Default::default(),
187            mid: Default::default(),
188            high: [0; HIGH_SYMBOLS],
189        }
190    }
191
192    pub fn reset(&mut self) {
193        init_probs(&mut self.choice);
194        for ele in self.low.iter_mut() {
195            init_probs(ele);
196        }
197        for ele in self.mid.iter_mut() {
198            init_probs(ele);
199        }
200        init_probs(&mut self.high);
201    }
202}