lzma_rust2/
lib.rs

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