1#![forbid(unsafe_code)]
2
3#[derive(Debug, Clone, Copy, PartialEq, Eq)]
5pub enum Strategy {
6 Fast,
8 DFast,
10}
11
12#[derive(Debug, Clone, Copy)]
14pub struct LdmParams {
15 pub hash_log: u32,
16 pub bucket_size_log: u32,
17 pub min_match_length: u32,
18 pub hash_rate_log: u32,
19}
20
21impl LdmParams {
22 pub fn default_for_window_log(window_log: u32) -> Self {
23 let hash_log = 20u32.min(window_log.saturating_sub(1));
24 let hash_rate_log = window_log.saturating_sub(hash_log).max(7);
25 Self {
26 hash_log,
27 bucket_size_log: 4,
28 min_match_length: 64,
29 hash_rate_log,
30 }
31 }
32}
33
34#[derive(Debug, Clone, Copy)]
39pub struct LevelParams {
40 pub strategy: Strategy,
41 pub window_log: u32,
42 pub hash_log: u32,
43 pub chain_log: u32,
45 pub search_log: u32,
46 pub min_match: u32,
47 pub target_length: u32,
48 pub search_strength: u32,
49 pub force_raw_literals: bool,
50 #[cfg(feature = "ldm")]
51 pub ldm_params: Option<LdmParams>,
52}
53
54impl LevelParams {
55 #[must_use]
56 pub fn with_window_log(mut self, window_log: u32) -> Self {
57 self.window_log = window_log;
58 self
59 }
60
61 #[cfg(feature = "ldm")]
62 #[must_use]
63 pub fn with_ldm(mut self, params: LdmParams) -> Self {
64 self.ldm_params = Some(params);
65 self
66 }
67}
68
69pub const DEFAULT_LEVEL: i32 = 1;
71
72pub fn level_params(level: i32) -> Option<LevelParams> {
77 level_params_for_size(level, usize::MAX)
78}
79
80pub fn level_params_for_size(level: i32, src_len: usize) -> Option<LevelParams> {
86 let mut params = level_params_inner(level)?;
87 if (2..usize::MAX).contains(&src_len) {
88 let src_log = 32 - ((src_len as u32) - 1).leading_zeros();
89 params.hash_log = params.hash_log.min(src_log);
90 params.chain_log = params.chain_log.min(src_log);
91 params.window_log = params.window_log.min(src_log);
92 }
93 Some(params)
94}
95
96pub fn max_hash_log(level: i32) -> Option<u32> {
99 let p = level_params_inner(level)?;
100 Some(p.hash_log.max(p.chain_log))
101}
102
103fn level_params_inner(level: i32) -> Option<LevelParams> {
104 Some(match level {
105 0 => return level_params_inner(DEFAULT_LEVEL),
106 -7 => LevelParams {
107 strategy: Strategy::Fast,
108 window_log: 19,
109 hash_log: 13,
110 chain_log: 13,
111 search_log: 0,
112 min_match: 5,
113 target_length: 7,
114 search_strength: 7,
115 force_raw_literals: true,
116 #[cfg(feature = "ldm")]
117 ldm_params: None,
118 },
119 -6 => LevelParams {
120 strategy: Strategy::Fast,
121 window_log: 19,
122 hash_log: 13,
123 chain_log: 13,
124 search_log: 0,
125 min_match: 5,
126 target_length: 7,
127 search_strength: 7,
128 force_raw_literals: false,
129 #[cfg(feature = "ldm")]
130 ldm_params: None,
131 },
132 -5 => LevelParams {
133 strategy: Strategy::Fast,
134 window_log: 19,
135 hash_log: 13,
136 chain_log: 13,
137 search_log: 0,
138 min_match: 5,
139 target_length: 6,
140 search_strength: 7,
141 force_raw_literals: false,
142 #[cfg(feature = "ldm")]
143 ldm_params: None,
144 },
145 -4 => LevelParams {
146 strategy: Strategy::Fast,
147 window_log: 19,
148 hash_log: 13,
149 chain_log: 13,
150 search_log: 0,
151 min_match: 5,
152 target_length: 5,
153 search_strength: 7,
154 force_raw_literals: false,
155 #[cfg(feature = "ldm")]
156 ldm_params: None,
157 },
158 -3 => LevelParams {
159 strategy: Strategy::Fast,
160 window_log: 19,
161 hash_log: 13,
162 chain_log: 13,
163 search_log: 0,
164 min_match: 5,
165 target_length: 4,
166 search_strength: 7,
167 force_raw_literals: false,
168 #[cfg(feature = "ldm")]
169 ldm_params: None,
170 },
171 -2 => LevelParams {
172 strategy: Strategy::Fast,
173 window_log: 19,
174 hash_log: 13,
175 chain_log: 13,
176 search_log: 0,
177 min_match: 5,
178 target_length: 3,
179 search_strength: 7,
180 force_raw_literals: false,
181 #[cfg(feature = "ldm")]
182 ldm_params: None,
183 },
184 -1 => LevelParams {
185 strategy: Strategy::Fast,
186 window_log: 19,
187 hash_log: 13,
188 chain_log: 13,
189 search_log: 0,
190 min_match: 5,
191 target_length: 2,
192 search_strength: 7,
193 force_raw_literals: false,
194 #[cfg(feature = "ldm")]
195 ldm_params: None,
196 },
197 1 => LevelParams {
198 strategy: Strategy::Fast,
199 window_log: 19,
200 hash_log: 14,
201 chain_log: 14,
202 search_log: 0,
203 min_match: 4,
204 target_length: 1,
205 search_strength: 8,
206 force_raw_literals: false,
207 #[cfg(feature = "ldm")]
208 ldm_params: None,
209 },
210 2 => LevelParams {
211 strategy: Strategy::Fast,
212 window_log: 20,
213 hash_log: 16,
214 chain_log: 16,
215 search_log: 0,
216 min_match: 4,
217 target_length: 1,
218 search_strength: 8,
219 force_raw_literals: false,
220 #[cfg(feature = "ldm")]
221 ldm_params: None,
222 },
223 3 => LevelParams {
224 strategy: Strategy::DFast,
225 window_log: 21,
226 hash_log: 18,
227 chain_log: 18,
228 search_log: 1,
229 min_match: 4,
230 target_length: 1,
231 search_strength: 5,
232 force_raw_literals: false,
233 #[cfg(feature = "ldm")]
234 ldm_params: None,
235 },
236 4 => LevelParams {
237 strategy: Strategy::DFast,
238 window_log: 23,
239 hash_log: 19,
240 chain_log: 19,
241 search_log: 1,
242 min_match: 4,
243 target_length: 1,
244 search_strength: 6,
245 force_raw_literals: false,
246 #[cfg(feature = "ldm")]
247 ldm_params: None,
248 },
249 _ => return None,
250 })
251}
252
253#[derive(Debug, Clone, Default)]
258pub struct Options {
259 pub(crate) window_log: Option<u32>,
260 #[cfg_attr(not(feature = "ldm"), allow(dead_code))]
261 pub(crate) ldm: bool,
262}
263
264impl Options {
265 #[must_use]
266 pub fn window_log(mut self, log: u32) -> Self {
267 self.window_log = Some(log);
268 self
269 }
270
271 #[cfg(feature = "ldm")]
272 #[must_use]
273 pub fn ldm(mut self, enable: bool) -> Self {
274 self.ldm = enable;
275 self
276 }
277}
278
279pub fn apply_options(params: &mut LevelParams, opts: &Options) {
280 if let Some(wl) = opts.window_log {
281 params.window_log = wl;
282 }
283 #[cfg(feature = "ldm")]
284 if opts.ldm {
285 params.ldm_params = Some(LdmParams::default_for_window_log(params.window_log));
286 }
287}