1use super::histogram;
2pub use super::input_pair::{InputPair, InputReference, InputReferenceMut};
3use alloc::{Allocator, SliceWrapper, SliceWrapperMut};
4#[allow(unused_imports)] use core;
6#[derive(Debug, Copy, Clone, Default)]
7pub struct BlockSwitch(pub u8);
8pub trait Nop<T> {
10 fn nop() -> T;
11}
12
13impl BlockSwitch {
14 #[inline(always)]
15 pub fn new(block_type: u8) -> Self {
16 BlockSwitch(block_type)
17 }
18 #[inline(always)]
19 pub fn block_type(&self) -> u8 {
20 self.0
21 }
22}
23
24#[derive(Debug, Copy, Clone, Default)]
25pub struct LiteralBlockSwitch(pub BlockSwitch, pub u8);
26
27impl LiteralBlockSwitch {
28 pub fn new(block_type: u8, stride: u8) -> Self {
29 LiteralBlockSwitch(BlockSwitch::new(block_type), stride)
30 }
31 #[inline(always)]
32 pub fn block_type(&self) -> u8 {
33 self.0.block_type()
34 }
35 #[inline(always)]
36 pub fn stride(&self) -> u8 {
37 self.1
38 }
39 #[inline(always)]
40 pub fn update_stride(&mut self, new_stride: u8) {
41 self.1 = new_stride;
42 }
43}
44
45pub const LITERAL_PREDICTION_MODE_SIGN: u8 = 3;
46pub const LITERAL_PREDICTION_MODE_UTF8: u8 = 2;
47pub const LITERAL_PREDICTION_MODE_MSB6: u8 = 1;
48pub const LITERAL_PREDICTION_MODE_LSB6: u8 = 0;
49
50#[derive(Default, Copy, Clone, Debug, PartialEq, Eq, Hash)]
51pub struct LiteralPredictionModeNibble(pub u8);
52
53impl LiteralPredictionModeNibble {
54 #[inline(always)]
55 pub fn new(prediction_mode: u8) -> Result<Self, ()> {
56 if prediction_mode < 16 {
57 return Ok(LiteralPredictionModeNibble(prediction_mode));
58 }
59 Err(())
60 }
61 #[inline(always)]
62 pub fn prediction_mode(&self) -> u8 {
63 self.0
64 }
65 #[inline(always)]
66 pub fn signed() -> Self {
67 LiteralPredictionModeNibble(LITERAL_PREDICTION_MODE_SIGN)
68 }
69 #[inline(always)]
70 pub fn utf8() -> Self {
71 LiteralPredictionModeNibble(LITERAL_PREDICTION_MODE_UTF8)
72 }
73 #[inline(always)]
74 pub fn msb6() -> Self {
75 LiteralPredictionModeNibble(LITERAL_PREDICTION_MODE_MSB6)
76 }
77 #[inline(always)]
78 pub fn lsb6() -> Self {
79 LiteralPredictionModeNibble(LITERAL_PREDICTION_MODE_LSB6)
80 }
81 #[inline(always)]
82 pub fn to_context_enum(&self) -> Result<histogram::ContextType, ()> {
83 match self.0 {
84 LITERAL_PREDICTION_MODE_LSB6 => Ok(histogram::ContextType::CONTEXT_LSB6),
85 LITERAL_PREDICTION_MODE_MSB6 => Ok(histogram::ContextType::CONTEXT_MSB6),
86 LITERAL_PREDICTION_MODE_UTF8 => Ok(histogram::ContextType::CONTEXT_UTF8),
87 LITERAL_PREDICTION_MODE_SIGN => Ok(histogram::ContextType::CONTEXT_SIGNED),
88 _ => Err(()),
89 }
90 }
91}
92pub const NUM_SPEED_VALUES: usize = 12;
93pub const NUM_MIXING_VALUES: usize = 16 * 256 + 16 * 256;
94pub const NUM_PREDMODE_SETUP_VALUES: usize = 4;
95pub const RESERVED_OFFSET: usize = 3;
96pub const ADV_CONTEXT_MAP_OFFSET: usize = 2;
97pub const MIXING_MATH_OFFSET: usize = 1;
98pub const PREDMODE_OFFSET: usize = 0;
99pub const MIXING_OFFSET: usize = NUM_PREDMODE_SETUP_VALUES + PREDMODE_OFFSET;
100pub const SPEED_OFFSET: usize = MIXING_OFFSET + NUM_MIXING_VALUES;
101pub const DISTANCE_CONTEXT_MAP_OFFSET: usize = SPEED_OFFSET + NUM_SPEED_VALUES;
102pub const MAX_PREDMODE_SPEED_AND_DISTANCE_CONTEXT_MAP_SIZE: usize =
103 DISTANCE_CONTEXT_MAP_OFFSET + 256 * 4;
104pub const MAX_LITERAL_CONTEXT_MAP_SIZE: usize = 256 * 64;
105pub const MAX_ADV_LITERAL_CONTEXT_MAP_SIZE: usize = 256 * 64 * 2;
106#[derive(Debug)]
107pub struct PredictionModeContextMap<SliceType: SliceWrapper<u8>> {
108 pub literal_context_map: SliceType,
109 pub predmode_speed_and_distance_context_map: SliceType,
110}
111impl<SliceType: SliceWrapper<u8> + SliceWrapperMut<u8>> PredictionModeContextMap<SliceType> {
112 #[inline]
113 pub fn distance_context_map_mut(&mut self) -> &mut [u8] {
114 self.predmode_speed_and_distance_context_map
115 .slice_mut()
116 .split_at_mut(DISTANCE_CONTEXT_MAP_OFFSET)
117 .1
118 }
119 #[inline]
120 pub fn set_stride_context_speed(&mut self, speed_max: [(u16, u16); 2]) {
121 let cm_slice = self.predmode_speed_and_distance_context_map.slice_mut();
122 for high in 0..2 {
123 cm_slice[Self::stride_context_speed_offset() + high] =
124 Self::u16_to_f8(speed_max[high].0);
125 cm_slice[Self::stride_context_speed_max_offset() + high] =
126 Self::u16_to_f8(speed_max[high].1);
127 }
128 }
129 #[inline]
130 pub fn set_context_map_speed(&mut self, speed_max: [(u16, u16); 2]) {
131 let cm_slice = self.predmode_speed_and_distance_context_map.slice_mut();
132 for high in 0..2 {
133 cm_slice[Self::context_map_speed_offset() + high] = Self::u16_to_f8(speed_max[high].0);
134 cm_slice[Self::context_map_speed_max_offset() + high] =
135 Self::u16_to_f8(speed_max[high].1);
136 }
137 }
138 pub fn set_mixing_math(&mut self, math_enum: u8) {
139 let cm_slice = self.predmode_speed_and_distance_context_map.slice_mut();
140 cm_slice[MIXING_MATH_OFFSET] = math_enum;
141 }
142 pub fn set_adv_context_map(&mut self, is_adv: u8) {
143 let cm_slice = self.predmode_speed_and_distance_context_map.slice_mut();
144 cm_slice[ADV_CONTEXT_MAP_OFFSET] = is_adv;
145 }
146 #[inline]
147 pub fn set_mixing_values(&mut self, mixing_mask: &[u8; NUM_MIXING_VALUES]) {
148 let cm_slice = self.predmode_speed_and_distance_context_map.slice_mut();
149 cm_slice[MIXING_OFFSET..(MIXING_OFFSET + NUM_MIXING_VALUES)]
150 .clone_from_slice(&mixing_mask[..]);
151 }
152 #[inline]
153 pub fn get_mixing_values_mut(&mut self) -> &mut [u8] {
154 let cm_slice = self.predmode_speed_and_distance_context_map.slice_mut();
155 &mut cm_slice[MIXING_OFFSET..(MIXING_OFFSET + NUM_MIXING_VALUES)]
156 }
157 #[inline]
158 pub fn set_combined_stride_context_speed(&mut self, speed_max: [(u16, u16); 2]) {
159 let cm_slice = self.predmode_speed_and_distance_context_map.slice_mut();
160 for high in 0..2 {
161 cm_slice[Self::combined_stride_context_speed_offset() + high] =
162 Self::u16_to_f8(speed_max[high].0);
163 cm_slice[Self::combined_stride_context_speed_max_offset() + high] =
164 Self::u16_to_f8(speed_max[high].1);
165 }
166 }
167 pub fn set_literal_prediction_mode(&mut self, val: LiteralPredictionModeNibble) {
168 let cm_slice = self.predmode_speed_and_distance_context_map.slice_mut();
169 cm_slice[PREDMODE_OFFSET] = val.0;
170 }
171}
172impl<SliceType: SliceWrapper<u8>> PredictionModeContextMap<SliceType> {
173 #[inline]
174 pub fn from_mut<Other: SliceWrapper<u8>>(
175 other: PredictionModeContextMap<Other>,
176 ) -> PredictionModeContextMap<SliceType>
177 where
178 SliceType: From<Other>,
179 {
180 PredictionModeContextMap::<SliceType> {
181 literal_context_map: SliceType::from(other.literal_context_map),
182 predmode_speed_and_distance_context_map: SliceType::from(
183 other.predmode_speed_and_distance_context_map,
184 ),
185 }
186 }
187 #[inline]
188 pub fn get_mixing_values(&self) -> &[u8] {
189 let cm_slice = self.predmode_speed_and_distance_context_map.slice();
190 &cm_slice[MIXING_OFFSET..(MIXING_OFFSET + NUM_MIXING_VALUES)]
191 }
192 #[inline]
193 pub fn get_mixing_math(&self) -> u8 {
194 let cm_slice = self.predmode_speed_and_distance_context_map.slice();
195 if cm_slice.len() <= MIXING_MATH_OFFSET {
196 return 1;
197 }
198 cm_slice[MIXING_MATH_OFFSET]
199 }
200 #[inline]
201 pub fn get_is_adv_context_map(&self) -> u8 {
202 let cm_slice = self.predmode_speed_and_distance_context_map.slice();
203 if cm_slice.len() <= ADV_CONTEXT_MAP_OFFSET {
204 return 0;
205 }
206 cm_slice[ADV_CONTEXT_MAP_OFFSET]
207 }
208 #[inline]
209 pub fn has_context_speeds(&self) -> bool {
210 self.predmode_speed_and_distance_context_map.slice().len() >= DISTANCE_CONTEXT_MAP_OFFSET
211 }
212 #[inline]
213 pub fn size_of_combined_array(distance_context_map_size: usize) -> usize {
214 distance_context_map_size + DISTANCE_CONTEXT_MAP_OFFSET
215 }
216 #[inline]
217 pub fn context_speeds_standard_len(&self) -> usize {
218 NUM_SPEED_VALUES
219 }
220 #[inline]
221 pub fn context_speeds_f8(&self) -> &[u8] {
222 &self.predmode_speed_and_distance_context_map.slice()
223 [SPEED_OFFSET..DISTANCE_CONTEXT_MAP_OFFSET]
224 }
225 #[inline]
226 pub fn distance_context_map(&self) -> &[u8] {
227 self.predmode_speed_and_distance_context_map
228 .slice()
229 .split_at(DISTANCE_CONTEXT_MAP_OFFSET)
230 .1
231 }
232 #[inline]
233 pub fn f8_to_u16(data: u8) -> u16 {
234 self::u8_to_speed(data)
235 }
236 #[inline]
237 pub fn u16_to_f8(data: u16) -> u8 {
238 self::speed_to_u8(data)
239 }
240 #[inline]
241 pub fn stride_context_speed_offset() -> usize {
242 SPEED_OFFSET
243 }
244 #[inline]
245 pub fn stride_context_speed_max_offset() -> usize {
246 SPEED_OFFSET + 2
247 }
248 #[inline]
249 pub fn context_map_speed_offset() -> usize {
250 SPEED_OFFSET + 4
251 }
252 #[inline]
253 pub fn context_map_speed_max_offset() -> usize {
254 SPEED_OFFSET + 6
255 }
256 #[inline]
257 pub fn combined_stride_context_speed_offset() -> usize {
258 SPEED_OFFSET + 8
259 }
260 #[inline]
261 pub fn combined_stride_context_speed_max_offset() -> usize {
262 SPEED_OFFSET + 10
263 }
264 #[inline]
265 pub fn literal_prediction_mode(&self) -> LiteralPredictionModeNibble {
266 let cm_slice = self.predmode_speed_and_distance_context_map.slice();
267 if PREDMODE_OFFSET < cm_slice.len() {
268 LiteralPredictionModeNibble(cm_slice[PREDMODE_OFFSET])
269 } else {
270 LiteralPredictionModeNibble::default()
271 }
272 }
273 pub fn stride_context_speed(&self) -> [(u16, u16); 2] {
274 let v = self.stride_context_speed_f8();
275 [
276 (self::u8_to_speed(v[0].0), self::u8_to_speed(v[0].1)),
277 (self::u8_to_speed(v[1].0), self::u8_to_speed(v[1].1)),
278 ]
279 }
280 pub fn context_map_speed(&self) -> [(u16, u16); 2] {
281 let v = self.context_map_speed_f8();
282 [
283 (self::u8_to_speed(v[0].0), self::u8_to_speed(v[0].1)),
284 (self::u8_to_speed(v[1].0), self::u8_to_speed(v[1].1)),
285 ]
286 }
287 pub fn combined_stride_context_speed(&self) -> [(u16, u16); 2] {
288 let v = self.combined_stride_context_speed_f8();
289 [
290 (self::u8_to_speed(v[0].0), self::u8_to_speed(v[0].1)),
291 (self::u8_to_speed(v[1].0), self::u8_to_speed(v[1].1)),
292 ]
293 }
294 #[inline]
295 pub fn stride_context_speed_f8(&self) -> [(u8, u8); 2] {
296 let cm_slice = self.predmode_speed_and_distance_context_map.slice();
297 let low_speed = cm_slice[Self::stride_context_speed_offset()];
298 let high_speed = cm_slice[Self::stride_context_speed_offset() + 1];
299 let low_max = cm_slice[Self::stride_context_speed_max_offset()];
300 let high_max = cm_slice[Self::stride_context_speed_max_offset() + 1];
301 [(low_speed, low_max), (high_speed, high_max)]
302 }
303 #[inline]
304 pub fn combined_stride_context_speed_f8(&self) -> [(u8, u8); 2] {
305 let cm_slice = self.predmode_speed_and_distance_context_map.slice();
306 let low_speed = cm_slice[Self::combined_stride_context_speed_offset()];
307 let high_speed = cm_slice[Self::combined_stride_context_speed_offset() + 1];
308 let low_max = cm_slice[Self::combined_stride_context_speed_max_offset()];
309 let high_max = cm_slice[Self::combined_stride_context_speed_max_offset() + 1];
310 [(low_speed, low_max), (high_speed, high_max)]
311 }
312 #[inline]
313 pub fn context_map_speed_f8(&self) -> [(u8, u8); 2] {
314 let cm_slice = self.predmode_speed_and_distance_context_map.slice();
315 let low_speed = cm_slice[Self::context_map_speed_offset()];
316 let high_speed = cm_slice[Self::context_map_speed_offset() + 1];
317 let low_max = cm_slice[Self::context_map_speed_max_offset()];
318 let high_max = cm_slice[Self::context_map_speed_max_offset() + 1];
319 [(low_speed, low_max), (high_speed, high_max)]
320 }
321}
322
323impl<SliceType: SliceWrapper<u8> + Clone> Clone for PredictionModeContextMap<SliceType> {
324 #[inline(always)]
325 fn clone(&self) -> Self {
326 PredictionModeContextMap::<SliceType> {
327 literal_context_map: self.literal_context_map.clone(),
328 predmode_speed_and_distance_context_map: self
329 .predmode_speed_and_distance_context_map
330 .clone(),
331 }
332 }
333}
334impl<SliceType: SliceWrapper<u8> + Clone + Copy> Copy for PredictionModeContextMap<SliceType> {}
335
336#[derive(Debug, Clone, Copy)]
337pub struct CopyCommand {
338 pub distance: u32,
339 pub num_bytes: u32,
340}
341
342impl Nop<CopyCommand> for CopyCommand {
343 #[inline(always)]
344 fn nop() -> Self {
345 CopyCommand {
346 distance: 1,
347 num_bytes: 0,
348 }
349 }
350}
351
352#[derive(Debug, Clone, Copy)]
353pub struct DictCommand {
354 pub word_size: u8,
355 pub transform: u8,
356 pub final_size: u8,
357 pub empty: u8,
358 pub word_id: u32,
359}
360
361impl Nop<DictCommand> for DictCommand {
362 #[inline(always)]
363 fn nop() -> Self {
364 DictCommand {
365 word_size: 0,
366 transform: 0,
367 final_size: 0,
368 empty: 1,
369 word_id: 0,
370 }
371 }
372}
373
374#[derive(Debug)]
375#[cfg(not(feature = "external-literal-probability"))]
376pub struct FeatureFlagSliceType<SliceType: SliceWrapper<u8>>(core::marker::PhantomData<SliceType>);
377
378#[cfg(not(feature = "external-literal-probability"))]
379impl<SliceType: SliceWrapper<u8>> SliceWrapper<u8> for FeatureFlagSliceType<SliceType> {
380 fn slice(&self) -> &[u8] {
381 &[]
382 }
383}
384
385#[cfg(not(feature = "external-literal-probability"))]
386impl<SliceType: SliceWrapper<u8> + Default> Default for FeatureFlagSliceType<SliceType> {
387 fn default() -> Self {
388 FeatureFlagSliceType::<SliceType>(core::marker::PhantomData::<SliceType>)
389 }
390}
391
392#[derive(Debug)]
393#[cfg(feature = "external-literal-probability")]
394pub struct FeatureFlagSliceType<SliceType: SliceWrapper<u8>>(pub SliceType);
395
396#[cfg(feature = "external-literal-probability")]
397impl<SliceType: SliceWrapper<u8>> SliceWrapper<u8> for FeatureFlagSliceType<SliceType> {
398 #[inline(always)]
399 fn slice(&self) -> &[u8] {
400 self.0.slice()
401 }
402}
403
404#[cfg(feature = "external-literal-probability")]
405impl<SliceType: SliceWrapper<u8> + Default> Default for FeatureFlagSliceType<SliceType> {
406 #[inline(always)]
407 fn default() -> Self {
408 FeatureFlagSliceType::<SliceType>(SliceType::default())
409 }
410}
411
412impl<SliceType: SliceWrapper<u8> + Clone> Clone for FeatureFlagSliceType<SliceType> {
413 #[inline(always)]
414 fn clone(&self) -> Self {
415 FeatureFlagSliceType::<SliceType>(self.0)
416 }
417}
418impl<SliceType: SliceWrapper<u8> + Clone + Copy> Copy for FeatureFlagSliceType<SliceType> {}
419
420#[derive(Debug)]
421pub struct LiteralCommand<SliceType: SliceWrapper<u8>> {
422 pub data: SliceType,
423 pub prob: FeatureFlagSliceType<SliceType>,
424 pub high_entropy: bool, }
426impl<SliceType: SliceWrapper<u8>> SliceWrapper<u8> for LiteralCommand<SliceType> {
427 #[inline(always)]
428 fn slice(&self) -> &[u8] {
429 self.data.slice()
430 }
431}
432impl<SliceType: SliceWrapper<u8> + SliceWrapperMut<u8>> SliceWrapperMut<u8>
433 for LiteralCommand<SliceType>
434{
435 #[inline(always)]
436 fn slice_mut(&mut self) -> &mut [u8] {
437 self.data.slice_mut()
438 }
439}
440
441impl<SliceType: SliceWrapper<u8> + Default> Nop<LiteralCommand<SliceType>>
442 for LiteralCommand<SliceType>
443{
444 #[inline(always)]
445 fn nop() -> Self {
446 LiteralCommand {
447 data: SliceType::default(),
448 prob: FeatureFlagSliceType::<SliceType>::default(),
449 high_entropy: false,
450 }
451 }
452}
453impl<SliceType: SliceWrapper<u8> + Clone> Clone for LiteralCommand<SliceType> {
454 #[inline(always)]
455 fn clone(&self) -> LiteralCommand<SliceType> {
456 LiteralCommand::<SliceType> {
457 data: self.data.clone(),
458 prob: self.prob.clone(),
459 high_entropy: self.high_entropy,
460 }
461 }
462}
463impl<SliceType: SliceWrapper<u8> + Clone + Copy> Copy for LiteralCommand<SliceType> {}
464
465#[derive(Debug)]
466pub enum Command<SliceType: SliceWrapper<u8>> {
467 Copy(CopyCommand),
468 Dict(DictCommand),
469 Literal(LiteralCommand<SliceType>),
470 BlockSwitchCommand(BlockSwitch),
471 BlockSwitchLiteral(LiteralBlockSwitch),
472 BlockSwitchDistance(BlockSwitch),
473 PredictionMode(PredictionModeContextMap<SliceType>),
474}
475impl<SliceType: SliceWrapper<u8> + Default> Command<SliceType> {
476 #[inline]
477 pub fn free_array<F>(&mut self, apply_func: &mut F)
478 where
479 F: FnMut(SliceType),
480 {
481 match self {
482 &mut Command::Literal(ref mut lit) => apply_func(core::mem::take(&mut lit.data)),
483 &mut Command::PredictionMode(ref mut pm) => {
484 apply_func(core::mem::take(&mut pm.literal_context_map));
485 apply_func(core::mem::take(
486 &mut pm.predmode_speed_and_distance_context_map,
487 ));
488 }
489 _ => {}
490 }
491 }
492}
493
494impl<SliceType: SliceWrapper<u8>> Default for Command<SliceType> {
495 #[inline(always)]
496 fn default() -> Self {
497 Command::<SliceType>::nop()
498 }
499}
500
501impl<SliceType: SliceWrapper<u8>> Nop<Command<SliceType>> for Command<SliceType> {
502 #[inline(always)]
503 fn nop() -> Command<SliceType> {
504 Command::Copy(CopyCommand::nop())
505 }
506}
507
508impl<SliceType: SliceWrapper<u8> + Clone> Clone for Command<SliceType> {
509 #[inline]
510 fn clone(&self) -> Command<SliceType> {
511 match self {
512 Command::Copy(copy) => Command::Copy(*copy),
513 Command::Dict(dict) => Command::Dict(*dict),
514 Command::Literal(literal) => Command::Literal(literal.clone()),
515 Command::BlockSwitchCommand(switch) => Command::BlockSwitchCommand(*switch),
516 Command::BlockSwitchLiteral(switch) => Command::BlockSwitchLiteral(*switch),
517 Command::BlockSwitchDistance(switch) => Command::BlockSwitchDistance(*switch),
518 Command::PredictionMode(pm) => Command::PredictionMode(pm.clone()),
519 }
520 }
521}
522
523impl<SliceType: SliceWrapper<u8> + Clone + Copy> Copy for Command<SliceType> {}
524
525#[inline(always)]
526pub fn free_cmd_inline<SliceTypeAllocator: Allocator<u8>>(
527 xself: &mut Command<SliceTypeAllocator::AllocatedMemory>,
528 m8: &mut SliceTypeAllocator,
529) {
530 match *xself {
531 Command::Literal(ref mut lit) => m8.free_cell(core::mem::take(&mut lit.data)),
532 Command::PredictionMode(ref mut pm) => {
533 m8.free_cell(core::mem::take(&mut pm.literal_context_map));
534 m8.free_cell(core::mem::take(
535 &mut pm.predmode_speed_and_distance_context_map,
536 ));
537 }
538 Command::Dict(_)
539 | Command::Copy(_)
540 | Command::BlockSwitchCommand(_)
541 | Command::BlockSwitchLiteral(_)
542 | Command::BlockSwitchDistance(_) => {}
543 }
544}
545
546#[inline(never)]
547pub fn free_cmd<SliceTypeAllocator: Allocator<u8>>(
548 xself: &mut Command<SliceTypeAllocator::AllocatedMemory>,
549 m8: &mut SliceTypeAllocator,
550) {
551 free_cmd_inline(xself, m8)
552}
553
554#[derive(Clone, Copy, Default, Debug)]
555pub struct SliceOffset(pub usize, pub u32);
556impl SliceWrapper<u8> for SliceOffset {
557 fn slice(&self) -> &[u8] {
558 &[]
560 }
561}
562
563pub trait Freezable {
564 fn freeze(&self) -> SliceOffset;
565}
566
567pub trait Unfreezable {
568 fn thaw<'a>(&self, data: &'a [u8]) -> InputReference<'a>;
569 fn thaw_mut<'a>(&self, data: &'a mut [u8]) -> InputReferenceMut<'a>;
570 fn thaw_pair<'a>(&self, pair: &InputPair<'a>) -> Result<InputReference<'a>, ()>;
571}
572
573impl<'a> From<InputReference<'a>> for SliceOffset {
574 fn from(f: InputReference<'a>) -> Self {
575 debug_assert!(f.data.len() <= 0xffffffff);
576 SliceOffset(f.orig_offset, f.data.len() as u32)
577 }
578}
579impl Unfreezable for SliceOffset {
580 fn thaw<'a>(&self, data: &'a [u8]) -> InputReference<'a> {
581 InputReference {
582 data: data.split_at(self.0).1.split_at(self.1 as usize).0,
583 orig_offset: self.0,
584 }
585 }
586 fn thaw_mut<'a>(&self, data: &'a mut [u8]) -> InputReferenceMut<'a> {
587 InputReferenceMut {
588 data: data.split_at_mut(self.0).1.split_at_mut(self.1 as usize).0,
589 orig_offset: self.0,
590 }
591 }
592 fn thaw_pair<'a>(&self, pair: &InputPair<'a>) -> Result<InputReference<'a>, ()> {
593 if self.0 >= pair.1.orig_offset {
594 return Ok(InputReference {
595 data: pair
596 .1
597 .data
598 .split_at(self.0 - pair.1.orig_offset)
599 .1
600 .split_at(self.1 as usize)
601 .0,
602 orig_offset: self.0,
603 });
604 }
605 let offset = self.0 - pair.0.orig_offset;
606 if offset + self.1 as usize <= pair.0.data.len() {
607 Ok(InputReference {
609 data: pair.0.data.split_at(offset).1.split_at(self.1 as usize).0,
610 orig_offset: self.0,
611 })
612 } else {
613 Err(())
614 }
615 }
616}
617impl SliceOffset {
618 pub fn offset(&self) -> usize {
619 self.0
620 }
621 pub fn len(&self) -> usize {
622 self.1 as usize
623 }
624 pub fn len32(&self) -> u32 {
625 self.1
626 }
627}
628
629pub type StaticCommand = Command<SliceOffset>;
630
631pub trait CommandProcessor<'a> {
632 fn push(&mut self, val: Command<InputReference<'a>>);
633 fn push_literals(&mut self, data: &InputPair<'a>) {
634 if data.0.len() != 0 {
635 self.push(Command::Literal(LiteralCommand {
636 data: data.0,
637 prob: FeatureFlagSliceType::<InputReference>::default(),
638 high_entropy: false,
639 }));
640 }
641 if data.1.len() != 0 {
642 self.push(Command::Literal(LiteralCommand {
643 data: data.1,
644 prob: FeatureFlagSliceType::<InputReference>::default(),
645 high_entropy: false,
646 }));
647 }
648 }
649 fn push_rand_literals(&mut self, data: &InputPair<'a>) {
650 if data.0.len() != 0 {
651 self.push(Command::Literal(LiteralCommand {
652 data: data.0,
653 prob: FeatureFlagSliceType::<InputReference>::default(),
654 high_entropy: true,
655 }));
656 }
657 if data.1.len() != 0 {
658 self.push(Command::Literal(LiteralCommand {
659 data: data.1,
660 prob: FeatureFlagSliceType::<InputReference>::default(),
661 high_entropy: true,
662 }));
663 }
664 }
665 fn push_block_switch_literal(&mut self, block_type: u8) {
666 self.push(Command::BlockSwitchLiteral(LiteralBlockSwitch::new(
667 block_type, 0,
668 )))
669 }
670}
671
672pub fn thaw_pair<'a, SliceType: Unfreezable + SliceWrapper<u8>>(
673 xself: &Command<SliceType>,
674 data: &InputPair<'a>,
675) -> Command<InputReference<'a>> {
676 match *xself {
677 Command::Literal(ref lit) => Command::Literal(LiteralCommand {
678 data: lit.data.thaw_pair(data).unwrap(),
679 prob: FeatureFlagSliceType::default(),
680 high_entropy: lit.high_entropy,
681 }),
682 Command::PredictionMode(ref pm) => Command::PredictionMode(PredictionModeContextMap {
683 literal_context_map: pm.literal_context_map.thaw_pair(data).unwrap(),
684 predmode_speed_and_distance_context_map: pm
685 .predmode_speed_and_distance_context_map
686 .thaw_pair(data)
687 .unwrap(),
688 }),
689 Command::Dict(ref d) => Command::Dict(*d),
690 Command::Copy(ref c) => Command::Copy(*c),
691 Command::BlockSwitchCommand(ref c) => Command::BlockSwitchCommand(*c),
692 Command::BlockSwitchLiteral(ref c) => Command::BlockSwitchLiteral(*c),
693 Command::BlockSwitchDistance(ref c) => Command::BlockSwitchDistance(*c),
694 }
695}
696
697pub fn thaw<'a, SliceType: Unfreezable + SliceWrapper<u8>>(
698 xself: &Command<SliceType>,
699 data: &'a [u8],
700) -> Command<InputReference<'a>> {
701 match *xself {
702 Command::Literal(ref lit) => Command::Literal(LiteralCommand {
703 data: lit.data.thaw(data),
704 prob: FeatureFlagSliceType::default(),
705 high_entropy: lit.high_entropy,
706 }),
707 Command::PredictionMode(ref pm) => Command::PredictionMode(PredictionModeContextMap {
708 literal_context_map: pm.literal_context_map.thaw(data),
709 predmode_speed_and_distance_context_map: pm
710 .predmode_speed_and_distance_context_map
711 .thaw(data),
712 }),
713 Command::Dict(ref d) => Command::Dict(*d),
714 Command::Copy(ref c) => Command::Copy(*c),
715 Command::BlockSwitchCommand(ref c) => Command::BlockSwitchCommand(*c),
716 Command::BlockSwitchLiteral(ref c) => Command::BlockSwitchLiteral(*c),
717 Command::BlockSwitchDistance(ref c) => Command::BlockSwitchDistance(*c),
718 }
719}
720
721impl<SliceType: SliceWrapper<u8> + Freezable> Command<SliceType> {
722 pub fn freeze(&self) -> Command<SliceOffset> {
723 match *self {
724 Command::Literal(ref lit) => Command::Literal(LiteralCommand {
725 data: lit.data.freeze(),
726 prob: FeatureFlagSliceType::default(),
727 high_entropy: lit.high_entropy,
728 }),
729 Command::PredictionMode(ref pm) => Command::PredictionMode(PredictionModeContextMap {
730 literal_context_map: pm.literal_context_map.freeze(),
731 predmode_speed_and_distance_context_map: pm
732 .predmode_speed_and_distance_context_map
733 .freeze(),
734 }),
735 Command::Dict(ref d) => Command::Dict(*d),
736 Command::Copy(ref c) => Command::Copy(*c),
737 Command::BlockSwitchCommand(ref c) => Command::BlockSwitchCommand(*c),
738 Command::BlockSwitchLiteral(ref c) => Command::BlockSwitchLiteral(*c),
739 Command::BlockSwitchDistance(ref c) => Command::BlockSwitchDistance(*c),
740 }
741 }
742}
743
744#[inline(always)]
745pub fn speed_to_u8(data: u16) -> u8 {
746 let length = 16 - data.leading_zeros() as u8;
747 let mantissa = if data != 0 {
748 let rem = data - (1 << (length - 1));
749 (rem << 3) >> (length - 1)
750 } else {
751 0
752 };
753 (length << 3) | mantissa as u8
754}
755
756#[inline(always)]
757pub fn u8_to_speed(data: u8) -> u16 {
758 if data < 8 {
759 0
760 } else {
761 let log_val = (data >> 3) - 1;
762 let rem = (u16::from(data) & 0x7) << log_val;
763 (1u16 << log_val) | (rem >> 3)
764 }
765}
766#[cfg(test)]
767mod test {
768 use super::speed_to_u8;
769 use super::u8_to_speed;
770 fn tst_u8_to_speed(data: u16) {
771 assert_eq!(u8_to_speed(speed_to_u8(data)), data);
772 }
773 #[test]
774 fn test_u8_to_speed() {
775 tst_u8_to_speed(0);
776 tst_u8_to_speed(1);
777 tst_u8_to_speed(2);
778 tst_u8_to_speed(3);
779 tst_u8_to_speed(4);
780 tst_u8_to_speed(5);
781 tst_u8_to_speed(6);
782 tst_u8_to_speed(7);
783 tst_u8_to_speed(8);
784 tst_u8_to_speed(10);
785 tst_u8_to_speed(12);
786 tst_u8_to_speed(16);
787 tst_u8_to_speed(24);
788 tst_u8_to_speed(32);
789 tst_u8_to_speed(48);
790 tst_u8_to_speed(64);
791 tst_u8_to_speed(96);
792 tst_u8_to_speed(768);
793 tst_u8_to_speed(1280);
794 tst_u8_to_speed(1536);
795 tst_u8_to_speed(1664);
796 }
797}