Skip to main content

zrip_encode/
strategy.rs

1#![forbid(unsafe_code)]
2
3/// Match-finding strategy.
4#[derive(Debug, Clone, Copy, PartialEq, Eq)]
5pub enum Strategy {
6    /// Single hash table (levels -7 through 2).
7    Fast,
8    /// Short + long hash tables (levels 3-4).
9    DFast,
10}
11
12/// Compression parameters for a specific level.
13///
14/// Obtain via [`level_params`] or construct directly for custom tuning.
15/// Pass to [`compress_with_params`](crate::compress_with_params).
16#[derive(Debug, Clone, Copy)]
17pub struct LevelParams {
18    pub strategy: Strategy,
19    pub window_log: u32,
20    pub hash_log: u32,
21    /// DFast short table log. Same as hashLog for Fast strategy.
22    pub chain_log: u32,
23    pub search_log: u32,
24    pub min_match: u32,
25    pub target_length: u32,
26    pub search_strength: u32,
27    pub force_raw_literals: bool,
28}
29
30/// Default compression level used when level 0 is requested.
31pub const DEFAULT_LEVEL: i32 = 1;
32
33/// Returns the compression parameters for a given level, or `None` if out of range.
34///
35/// Level 0 is treated as "library default" and maps to level 1.
36/// Uses the large-input (>256 KB) parameter tier.
37pub fn level_params(level: i32) -> Option<LevelParams> {
38    level_params_for_size(level, usize::MAX)
39}
40
41/// Returns the compression parameters for a given level, sized for `src_len`.
42///
43/// Uses fixed parameters per level with log values clamped down for small inputs.
44///
45/// Level 0 is treated as "library default" and maps to level 1.
46pub fn level_params_for_size(level: i32, src_len: usize) -> Option<LevelParams> {
47    let mut params = level_params_inner(level)?;
48    if (2..usize::MAX).contains(&src_len) {
49        let src_log = 32 - ((src_len as u32) - 1).leading_zeros();
50        params.hash_log = params.hash_log.min(src_log);
51        params.chain_log = params.chain_log.min(src_log);
52        params.window_log = params.window_log.min(src_log);
53    }
54    Some(params)
55}
56
57/// Returns the maximum hash_log for a given level.
58/// Used by CompressContext to pre-allocate hash tables.
59pub fn max_hash_log(level: i32) -> Option<u32> {
60    let p = level_params_inner(level)?;
61    Some(p.hash_log.max(p.chain_log))
62}
63
64fn level_params_inner(level: i32) -> Option<LevelParams> {
65    Some(match level {
66        0 => return level_params_inner(DEFAULT_LEVEL),
67        -7 => LevelParams {
68            strategy: Strategy::Fast,
69            window_log: 19,
70            hash_log: 13,
71            chain_log: 13,
72            search_log: 0,
73            min_match: 5,
74            target_length: 7,
75            search_strength: 7,
76            force_raw_literals: true,
77        },
78        -6 => LevelParams {
79            strategy: Strategy::Fast,
80            window_log: 19,
81            hash_log: 13,
82            chain_log: 13,
83            search_log: 0,
84            min_match: 5,
85            target_length: 7,
86            search_strength: 7,
87            force_raw_literals: false,
88        },
89        -5 => LevelParams {
90            strategy: Strategy::Fast,
91            window_log: 19,
92            hash_log: 13,
93            chain_log: 13,
94            search_log: 0,
95            min_match: 5,
96            target_length: 6,
97            search_strength: 7,
98            force_raw_literals: false,
99        },
100        -4 => LevelParams {
101            strategy: Strategy::Fast,
102            window_log: 19,
103            hash_log: 13,
104            chain_log: 13,
105            search_log: 0,
106            min_match: 5,
107            target_length: 5,
108            search_strength: 7,
109            force_raw_literals: false,
110        },
111        -3 => LevelParams {
112            strategy: Strategy::Fast,
113            window_log: 19,
114            hash_log: 13,
115            chain_log: 13,
116            search_log: 0,
117            min_match: 5,
118            target_length: 4,
119            search_strength: 7,
120            force_raw_literals: false,
121        },
122        -2 => LevelParams {
123            strategy: Strategy::Fast,
124            window_log: 19,
125            hash_log: 13,
126            chain_log: 13,
127            search_log: 0,
128            min_match: 5,
129            target_length: 3,
130            search_strength: 7,
131            force_raw_literals: false,
132        },
133        -1 => LevelParams {
134            strategy: Strategy::Fast,
135            window_log: 19,
136            hash_log: 13,
137            chain_log: 13,
138            search_log: 0,
139            min_match: 5,
140            target_length: 2,
141            search_strength: 7,
142            force_raw_literals: false,
143        },
144        1 => LevelParams {
145            strategy: Strategy::Fast,
146            window_log: 19,
147            hash_log: 14,
148            chain_log: 14,
149            search_log: 0,
150            min_match: 4,
151            target_length: 1,
152            search_strength: 8,
153            force_raw_literals: false,
154        },
155        2 => LevelParams {
156            strategy: Strategy::Fast,
157            window_log: 20,
158            hash_log: 16,
159            chain_log: 16,
160            search_log: 0,
161            min_match: 4,
162            target_length: 1,
163            search_strength: 8,
164            force_raw_literals: false,
165        },
166        3 => LevelParams {
167            strategy: Strategy::DFast,
168            window_log: 21,
169            hash_log: 18,
170            chain_log: 18,
171            search_log: 1,
172            min_match: 4,
173            target_length: 1,
174            search_strength: 5,
175            force_raw_literals: false,
176        },
177        4 => LevelParams {
178            strategy: Strategy::DFast,
179            window_log: 23,
180            hash_log: 19,
181            chain_log: 19,
182            search_log: 1,
183            min_match: 4,
184            target_length: 1,
185            search_strength: 6,
186            force_raw_literals: false,
187        },
188        _ => return None,
189    })
190}