diff options
Diffstat (limited to 'rust/vendor/brotli/src/enc/interface.rs')
-rw-r--r-- | rust/vendor/brotli/src/enc/interface.rs | 791 |
1 files changed, 791 insertions, 0 deletions
diff --git a/rust/vendor/brotli/src/enc/interface.rs b/rust/vendor/brotli/src/enc/interface.rs new file mode 100644 index 0000000..3c7e666 --- /dev/null +++ b/rust/vendor/brotli/src/enc/interface.rs @@ -0,0 +1,791 @@ +#[allow(unused_imports)] // right now just used in feature flag +use core; +use alloc::{SliceWrapper, Allocator, SliceWrapperMut}; +pub use super::input_pair::{InputPair,InputReference, InputReferenceMut}; +use super::histogram; +#[derive(Debug,Copy,Clone,Default)] +pub struct BlockSwitch(pub u8); +// Commands that can instantiate as a no-op should implement this. +pub trait Nop<T> { + fn nop() -> T; +} + +impl BlockSwitch { + #[inline(always)] + pub fn new(block_type: u8) -> Self { + BlockSwitch(block_type) + } + #[inline(always)] + pub fn block_type(&self) -> u8 { + self.0 + } +} + +#[derive(Debug,Copy,Clone,Default)] +pub struct LiteralBlockSwitch(pub BlockSwitch, pub u8); + +impl LiteralBlockSwitch { + pub fn new(block_type: u8, stride: u8) -> Self { + LiteralBlockSwitch(BlockSwitch::new(block_type), stride) + } + #[inline(always)] + pub fn block_type(&self) -> u8 { + self.0.block_type() + } + #[inline(always)] + pub fn stride(&self) -> u8 { + self.1 + } + #[inline(always)] + pub fn update_stride(&mut self, new_stride: u8) { + self.1 = new_stride; + } +} + +pub const LITERAL_PREDICTION_MODE_SIGN: u8 = 3; +pub const LITERAL_PREDICTION_MODE_UTF8: u8 = 2; +pub const LITERAL_PREDICTION_MODE_MSB6: u8 = 1; +pub const LITERAL_PREDICTION_MODE_LSB6: u8 = 0; + +#[derive(Default, Copy, Clone, Debug, PartialEq, Eq, Hash)] +pub struct LiteralPredictionModeNibble(pub u8); + +impl LiteralPredictionModeNibble { + #[inline(always)] + pub fn new(prediction_mode: u8) -> Result<Self, ()> { + if prediction_mode < 16 { + return Ok(LiteralPredictionModeNibble(prediction_mode)); + } + return Err(()); + } + #[inline(always)] + pub fn prediction_mode(&self) -> u8 { + self.0 + } + #[inline(always)] + pub fn signed() -> Self { + LiteralPredictionModeNibble(LITERAL_PREDICTION_MODE_SIGN) + } + #[inline(always)] + pub fn utf8() -> Self { + LiteralPredictionModeNibble(LITERAL_PREDICTION_MODE_UTF8) + } + #[inline(always)] + pub fn msb6() -> Self { + LiteralPredictionModeNibble(LITERAL_PREDICTION_MODE_MSB6) + } + #[inline(always)] + pub fn lsb6() -> Self { + LiteralPredictionModeNibble(LITERAL_PREDICTION_MODE_LSB6) + } + #[inline(always)] + pub fn to_context_enum(&self) -> Result<histogram::ContextType, ()>{ + match self.0 { + LITERAL_PREDICTION_MODE_LSB6 => Ok(histogram::ContextType::CONTEXT_LSB6), + LITERAL_PREDICTION_MODE_MSB6 => Ok(histogram::ContextType::CONTEXT_MSB6), + LITERAL_PREDICTION_MODE_UTF8 => Ok(histogram::ContextType::CONTEXT_UTF8), + LITERAL_PREDICTION_MODE_SIGN => Ok(histogram::ContextType::CONTEXT_SIGNED), + _ => Err(()), + } + } +} +pub const NUM_SPEED_VALUES: usize = 12; +pub const NUM_MIXING_VALUES: usize = 16 * 256 + 16 * 256; +pub const NUM_PREDMODE_SETUP_VALUES: usize = 4; +pub const RESERVED_OFFSET: usize = 3; +pub const ADV_CONTEXT_MAP_OFFSET: usize = 2; +pub const MIXING_MATH_OFFSET: usize = 1; +pub const PREDMODE_OFFSET: usize = 0; +pub const MIXING_OFFSET:usize = NUM_PREDMODE_SETUP_VALUES + PREDMODE_OFFSET; +pub const SPEED_OFFSET: usize = MIXING_OFFSET + NUM_MIXING_VALUES; +pub const DISTANCE_CONTEXT_MAP_OFFSET: usize = SPEED_OFFSET + NUM_SPEED_VALUES; +pub const MAX_PREDMODE_SPEED_AND_DISTANCE_CONTEXT_MAP_SIZE: usize = DISTANCE_CONTEXT_MAP_OFFSET + 256 * 4; +pub const MAX_LITERAL_CONTEXT_MAP_SIZE: usize = 256 * 64; +pub const MAX_ADV_LITERAL_CONTEXT_MAP_SIZE: usize = 256 * 64 * 2; +#[derive(Debug)] +pub struct PredictionModeContextMap<SliceType:SliceWrapper<u8>> { + pub literal_context_map: SliceType, + pub predmode_speed_and_distance_context_map: SliceType, +} +impl<SliceType:SliceWrapper<u8>+SliceWrapperMut<u8>> PredictionModeContextMap<SliceType> { + #[inline] + pub fn distance_context_map_mut(&mut self) -> &mut [u8] { + self.predmode_speed_and_distance_context_map.slice_mut().split_at_mut(DISTANCE_CONTEXT_MAP_OFFSET).1 + } + #[inline] + pub fn set_stride_context_speed(&mut self, speed_max: [(u16, u16);2]) { + let cm_slice = self.predmode_speed_and_distance_context_map.slice_mut(); + for high in 0..2 { + cm_slice[Self::stride_context_speed_offset()+high] = Self::u16_to_f8(speed_max[high].0); + cm_slice[Self::stride_context_speed_max_offset()+high] = Self::u16_to_f8(speed_max[high].1); + } + } + #[inline] + pub fn set_context_map_speed(&mut self, speed_max: [(u16, u16);2]) { + let cm_slice = self.predmode_speed_and_distance_context_map.slice_mut(); + for high in 0..2 { + cm_slice[Self::context_map_speed_offset()+high] = Self::u16_to_f8(speed_max[high].0); + cm_slice[Self::context_map_speed_max_offset()+high] = Self::u16_to_f8(speed_max[high].1); + } + } + pub fn set_mixing_math(&mut self, math_enum: u8) { + let cm_slice = self.predmode_speed_and_distance_context_map.slice_mut(); + cm_slice[MIXING_MATH_OFFSET] = math_enum; + } + pub fn set_adv_context_map(&mut self, is_adv: u8) { + let cm_slice = self.predmode_speed_and_distance_context_map.slice_mut(); + cm_slice[ADV_CONTEXT_MAP_OFFSET] = is_adv; + } + #[inline] + pub fn set_mixing_values(&mut self, mixing_mask: &[u8; NUM_MIXING_VALUES]) { + let cm_slice = self.predmode_speed_and_distance_context_map.slice_mut(); + cm_slice[MIXING_OFFSET..(MIXING_OFFSET + NUM_MIXING_VALUES)].clone_from_slice(&mixing_mask[..]); + } + #[inline] + pub fn get_mixing_values_mut(&mut self) -> &mut [u8] { + let cm_slice = self.predmode_speed_and_distance_context_map.slice_mut(); + &mut cm_slice[MIXING_OFFSET..(MIXING_OFFSET + NUM_MIXING_VALUES)] + } + #[inline] + pub fn set_combined_stride_context_speed(&mut self, speed_max: [(u16, u16);2]) { + let cm_slice = self.predmode_speed_and_distance_context_map.slice_mut(); + for high in 0..2 { + cm_slice[Self::combined_stride_context_speed_offset()+high] = Self::u16_to_f8(speed_max[high].0); + cm_slice[Self::combined_stride_context_speed_max_offset()+high] = Self::u16_to_f8(speed_max[high].1); + } + } + pub fn set_literal_prediction_mode(&mut self, val: LiteralPredictionModeNibble) { + let cm_slice = self.predmode_speed_and_distance_context_map.slice_mut(); + cm_slice[PREDMODE_OFFSET] = val.0; + } +} +impl<SliceType:SliceWrapper<u8>> PredictionModeContextMap<SliceType> { + #[inline] + pub fn from_mut<Other:SliceWrapper<u8>>(other: PredictionModeContextMap<Other>) -> PredictionModeContextMap<SliceType> where SliceType: From<Other>{ + PredictionModeContextMap::<SliceType>{ + literal_context_map:SliceType::from(other.literal_context_map), + predmode_speed_and_distance_context_map: SliceType::from(other.predmode_speed_and_distance_context_map), + } + } + #[inline] + pub fn get_mixing_values(&self) -> &[u8] { + let cm_slice = self.predmode_speed_and_distance_context_map.slice(); + &cm_slice[MIXING_OFFSET..(MIXING_OFFSET + NUM_MIXING_VALUES)] + } + #[inline] + pub fn get_mixing_math(&self) ->u8 { + let cm_slice = self.predmode_speed_and_distance_context_map.slice(); + if cm_slice.len() <= MIXING_MATH_OFFSET { + return 1; + } + cm_slice[MIXING_MATH_OFFSET] + } + #[inline] + pub fn get_is_adv_context_map(&self) -> u8 { + let cm_slice = self.predmode_speed_and_distance_context_map.slice(); + if cm_slice.len() <= ADV_CONTEXT_MAP_OFFSET { + return 0; + } + cm_slice[ADV_CONTEXT_MAP_OFFSET] + } + #[inline] + pub fn has_context_speeds(&self) -> bool { + self.predmode_speed_and_distance_context_map.slice().len() >= DISTANCE_CONTEXT_MAP_OFFSET + } + #[inline] + pub fn size_of_combined_array(distance_context_map_size: usize) -> usize { + distance_context_map_size + DISTANCE_CONTEXT_MAP_OFFSET + } + #[inline] + pub fn context_speeds_standard_len(&self) -> usize { + NUM_SPEED_VALUES + } + #[inline] + pub fn context_speeds_f8(&self) -> &[u8] { + &self.predmode_speed_and_distance_context_map.slice()[SPEED_OFFSET..DISTANCE_CONTEXT_MAP_OFFSET] + } + #[inline] + pub fn distance_context_map(&self) -> &[u8] { + self.predmode_speed_and_distance_context_map.slice().split_at(DISTANCE_CONTEXT_MAP_OFFSET).1 + } + #[inline] + pub fn f8_to_u16(data: u8) -> u16 { + self::u8_to_speed(data) + } + #[inline] + pub fn u16_to_f8(data: u16) -> u8 { + self::speed_to_u8(data) + } + #[inline] + pub fn stride_context_speed_offset() -> usize { + SPEED_OFFSET + } + #[inline] + pub fn stride_context_speed_max_offset() -> usize { + SPEED_OFFSET + 2 + } + #[inline] + pub fn context_map_speed_offset() -> usize { + SPEED_OFFSET + 4 + } + #[inline] + pub fn context_map_speed_max_offset() -> usize { + SPEED_OFFSET + 6 + } + #[inline] + pub fn combined_stride_context_speed_offset() -> usize { + SPEED_OFFSET + 8 + } + #[inline] + pub fn combined_stride_context_speed_max_offset() -> usize { + SPEED_OFFSET + 10 + } + #[inline] + pub fn literal_prediction_mode(&self) -> LiteralPredictionModeNibble { + let cm_slice = self.predmode_speed_and_distance_context_map.slice(); + if PREDMODE_OFFSET < cm_slice.len() { + LiteralPredictionModeNibble(cm_slice[PREDMODE_OFFSET]) + } else { + LiteralPredictionModeNibble::default() + } + } + pub fn stride_context_speed(&self) -> [(u16, u16);2] { + let v = self.stride_context_speed_f8(); + [(self::u8_to_speed(v[0].0), self::u8_to_speed(v[0].1)), + (self::u8_to_speed(v[1].0), self::u8_to_speed(v[1].1))] + } + pub fn context_map_speed(&self) -> [(u16, u16);2] { + let v = self.context_map_speed_f8(); + [(self::u8_to_speed(v[0].0), self::u8_to_speed(v[0].1)), + (self::u8_to_speed(v[1].0), self::u8_to_speed(v[1].1))] + } + pub fn combined_stride_context_speed(&self) -> [(u16, u16);2] { + let v = self.combined_stride_context_speed_f8(); + [(self::u8_to_speed(v[0].0), self::u8_to_speed(v[0].1)), + (self::u8_to_speed(v[1].0), self::u8_to_speed(v[1].1))] + } + #[inline] + pub fn stride_context_speed_f8(&self) -> [(u8, u8);2] { + let cm_slice = self.predmode_speed_and_distance_context_map.slice(); + let low_speed = cm_slice[Self::stride_context_speed_offset()]; + let high_speed = cm_slice[Self::stride_context_speed_offset() + 1]; + let low_max = cm_slice[Self::stride_context_speed_max_offset()]; + let high_max = cm_slice[Self::stride_context_speed_max_offset() + 1]; + [(low_speed, low_max), (high_speed, high_max)] + } + #[inline] + pub fn combined_stride_context_speed_f8(&self) -> [(u8, u8);2] { + let cm_slice = self.predmode_speed_and_distance_context_map.slice(); + let low_speed = cm_slice[Self::combined_stride_context_speed_offset()]; + let high_speed = cm_slice[Self::combined_stride_context_speed_offset() + 1]; + let low_max = cm_slice[Self::combined_stride_context_speed_max_offset()]; + let high_max = cm_slice[Self::combined_stride_context_speed_max_offset() + 1]; + [(low_speed, low_max), (high_speed, high_max)] + } + #[inline] + pub fn context_map_speed_f8(&self) -> [(u8, u8);2] { + let cm_slice = self.predmode_speed_and_distance_context_map.slice(); + let low_speed = cm_slice[Self::context_map_speed_offset()]; + let high_speed = cm_slice[Self::context_map_speed_offset() + 1]; + let low_max = cm_slice[Self::context_map_speed_max_offset()]; + let high_max = cm_slice[Self::context_map_speed_max_offset() + 1]; + [(low_speed, low_max), (high_speed, high_max)] + } +} + +impl<SliceType:SliceWrapper<u8>+Clone> Clone for PredictionModeContextMap<SliceType> { + #[inline(always)] + fn clone(&self) -> Self { + PredictionModeContextMap::<SliceType> { + literal_context_map:self.literal_context_map.clone(), + predmode_speed_and_distance_context_map:self.predmode_speed_and_distance_context_map.clone(), + } + } +} +impl<SliceType:SliceWrapper<u8>+Clone+Copy> Copy for PredictionModeContextMap<SliceType> { +} + + +#[derive(Debug,Clone,Copy)] +pub struct CopyCommand { + pub distance: u32, + pub num_bytes: u32, +} + +impl Nop<CopyCommand> for CopyCommand { + #[inline(always)] + fn nop() -> Self { + CopyCommand { + distance: 1, + num_bytes: 0 + } + } +} + +#[derive(Debug,Clone,Copy)] +pub struct DictCommand { + pub word_size: u8, + pub transform: u8, + pub final_size: u8, + pub empty: u8, + pub word_id: u32, +} + +impl Nop<DictCommand> for DictCommand { + #[inline(always)] + fn nop() -> Self { + DictCommand { + word_size: 0, + transform: 0, + final_size: 0, + empty: 1, + word_id: 0 + } + } +} + +#[derive(Debug)] +#[cfg(not(feature="external-literal-probability"))] +pub struct FeatureFlagSliceType<SliceType:SliceWrapper<u8> >(core::marker::PhantomData<SliceType>); + +#[cfg(not(feature="external-literal-probability"))] +impl<SliceType:SliceWrapper<u8>> SliceWrapper<u8> for FeatureFlagSliceType<SliceType> { + fn slice(&self) -> &[u8] { + &[] + } +} + +#[cfg(not(feature="external-literal-probability"))] +impl<SliceType:SliceWrapper<u8>+Default> Default for FeatureFlagSliceType<SliceType> { + fn default() -> Self { + FeatureFlagSliceType::<SliceType>(core::marker::PhantomData::<SliceType>::default()) + } +} + + + +#[derive(Debug)] +#[cfg(feature="external-literal-probability")] +pub struct FeatureFlagSliceType<SliceType:SliceWrapper<u8> >(pub SliceType); + +#[cfg(feature="external-literal-probability")] +impl<SliceType:SliceWrapper<u8>> SliceWrapper<u8> for FeatureFlagSliceType<SliceType> { + #[inline(always)] + fn slice(&self) -> &[u8] { + self.0.slice() + } +} + +#[cfg(feature="external-literal-probability")] +impl<SliceType:SliceWrapper<u8>+Default> Default for FeatureFlagSliceType<SliceType> { + #[inline(always)] + fn default() -> Self { + FeatureFlagSliceType::<SliceType>(SliceType::default()) + } +} + + + +impl<SliceType:SliceWrapper<u8>+Clone> Clone for FeatureFlagSliceType<SliceType> { + #[inline(always)] + fn clone(&self) -> Self { + FeatureFlagSliceType::<SliceType>(self.0.clone()) + } +} +impl<SliceType:SliceWrapper<u8>+Clone+Copy> Copy for FeatureFlagSliceType<SliceType> { +} + + +#[derive(Debug)] +pub struct LiteralCommand<SliceType:SliceWrapper<u8>> { + pub data: SliceType, + pub prob: FeatureFlagSliceType<SliceType>, + pub high_entropy: bool, // this block of bytes is high entropy with a few patterns never seen again; adapt slower +} +impl<SliceType:SliceWrapper<u8>> SliceWrapper<u8> for LiteralCommand<SliceType> { + #[inline(always)] + fn slice(&self) -> &[u8] { + self.data.slice() + } +} +impl<SliceType:SliceWrapper<u8>+SliceWrapperMut<u8>> SliceWrapperMut<u8> for LiteralCommand<SliceType> { + #[inline(always)] + fn slice_mut(&mut self) -> &mut [u8] { + self.data.slice_mut() + } +} + +impl<SliceType:SliceWrapper<u8>+Default> Nop<LiteralCommand<SliceType>> for LiteralCommand<SliceType> { + #[inline(always)] + fn nop() -> Self { + LiteralCommand { + data: SliceType::default(), + prob: FeatureFlagSliceType::<SliceType>::default(), + high_entropy: false, + } + } +} +impl<SliceType:SliceWrapper<u8>+Clone> Clone for LiteralCommand<SliceType> { + #[inline(always)] + fn clone(&self) -> LiteralCommand<SliceType>{ + LiteralCommand::<SliceType>{data:self.data.clone(), prob:self.prob.clone(),high_entropy: self.high_entropy.clone(),} + } +} +impl<SliceType:SliceWrapper<u8>+Clone+Copy> Copy for LiteralCommand<SliceType> { +} + + +#[derive(Debug)] +pub enum Command<SliceType:SliceWrapper<u8> > { + Copy(CopyCommand), + Dict(DictCommand), + Literal(LiteralCommand<SliceType>), + BlockSwitchCommand(BlockSwitch), + BlockSwitchLiteral(LiteralBlockSwitch), + BlockSwitchDistance(BlockSwitch), + PredictionMode(PredictionModeContextMap<SliceType>), +} +impl<SliceType:SliceWrapper<u8>+Default> Command<SliceType> { + #[inline] + pub fn free_array<F>(&mut self, apply_func: &mut F) where F: FnMut(SliceType) { + match self { + &mut Command::Literal(ref mut lit) => { + apply_func(core::mem::replace(&mut lit.data, SliceType::default())) + }, + &mut Command::PredictionMode(ref mut pm) => { + apply_func(core::mem::replace(&mut pm.literal_context_map, SliceType::default())); + apply_func(core::mem::replace(&mut pm.predmode_speed_and_distance_context_map, SliceType::default())); + }, + _ => {}, + } + } +} + + +impl<SliceType:SliceWrapper<u8>> Default for Command<SliceType> { + #[inline(always)] + fn default() -> Self { + Command::<SliceType>::nop() + } +} + +impl<SliceType:SliceWrapper<u8>> Nop<Command<SliceType>> for Command<SliceType> { + #[inline(always)] + fn nop() -> Command<SliceType> { + Command::Copy(CopyCommand::nop()) + } +} + +impl<SliceType:SliceWrapper<u8>+Clone> Clone for Command<SliceType> { + #[inline] + fn clone(&self) -> Command<SliceType>{ + match self { + &Command::Copy(ref copy) => Command::Copy(copy.clone()), + &Command::Dict(ref dict) => Command::Dict(dict.clone()), + &Command::Literal(ref literal) => Command::Literal(literal.clone()), + &Command::BlockSwitchCommand(ref switch) => Command::BlockSwitchCommand(switch.clone()), + &Command::BlockSwitchLiteral(ref switch) => Command::BlockSwitchLiteral(switch.clone()), + &Command::BlockSwitchDistance(ref switch) => Command::BlockSwitchDistance(switch.clone()), + &Command::PredictionMode(ref pm) => Command::PredictionMode(pm.clone()), + } + } +} + +impl<SliceType:SliceWrapper<u8>+Clone+Copy> Copy for Command<SliceType> { +} + + + +#[inline(always)] +pub fn free_cmd_inline<SliceTypeAllocator:Allocator<u8>> (xself: &mut Command<SliceTypeAllocator::AllocatedMemory>, m8: &mut SliceTypeAllocator) { + match *xself { + Command::Literal(ref mut lit) => { + m8.free_cell(core::mem::replace(&mut lit.data, SliceTypeAllocator::AllocatedMemory::default())) + }, + Command::PredictionMode(ref mut pm) => { + m8.free_cell(core::mem::replace(&mut pm.literal_context_map, SliceTypeAllocator::AllocatedMemory::default())); + m8.free_cell(core::mem::replace(&mut pm.predmode_speed_and_distance_context_map, SliceTypeAllocator::AllocatedMemory::default())); + }, + Command::Dict(_) | + Command::Copy(_) | + Command::BlockSwitchCommand(_) | + Command::BlockSwitchLiteral(_) | + Command::BlockSwitchDistance(_) => {}, + } +} + +#[inline(never)] +pub fn free_cmd<SliceTypeAllocator:Allocator<u8>> (xself: &mut Command<SliceTypeAllocator::AllocatedMemory>, m8: &mut SliceTypeAllocator) { + free_cmd_inline(xself, m8) +} + +#[derive(Clone, Copy, Default, Debug)] +pub struct SliceOffset(pub usize, pub u32); +impl SliceWrapper<u8> for SliceOffset { + fn slice(&self) -> &[u8] { + // not perfect--shouldn't be calling this without thawing the wrapper + &[] + } +} + +pub trait Freezable { + fn freeze(&self) -> SliceOffset; +} + +pub trait Unfreezable { + fn thaw<'a>(&self, data: &'a [u8]) -> InputReference<'a>; + fn thaw_mut<'a>(&self, data: &'a mut [u8]) -> InputReferenceMut<'a>; + fn thaw_pair<'a>(&self, pair: &InputPair<'a>) -> Result<InputReference<'a>, ()>; +} + +impl<'a> From<InputReference<'a>> for SliceOffset { + fn from(f: InputReference<'a>) -> Self { + debug_assert!(f.data.len() <= 0xffffffff); + SliceOffset(f.orig_offset, f.data.len() as u32) + } +} +impl Unfreezable for SliceOffset { + fn thaw<'a>(&self, data: &'a [u8]) -> InputReference<'a> { + InputReference{ + data: data.split_at(self.0).1.split_at(self.1 as usize).0, + orig_offset: self.0, + } + } + fn thaw_mut<'a>(&self, data: &'a mut [u8]) -> InputReferenceMut<'a> { + InputReferenceMut{ + data: data.split_at_mut(self.0).1.split_at_mut(self.1 as usize).0, + orig_offset: self.0, + } + } + fn thaw_pair<'a>(&self, pair: &InputPair<'a>) -> Result<InputReference<'a>, ()> { + if self.0 >= pair.1.orig_offset { + return Ok(InputReference{ + data: pair.1.data.split_at(self.0 - pair.1.orig_offset).1.split_at(self.1 as usize).0, + orig_offset: self.0, + }); + } + let offset = self.0 - pair.0.orig_offset; + if offset + self.1 as usize <= pair.0.data.len() { // overlap + Ok(InputReference{ + data: pair.0.data.split_at(offset).1.split_at(self.1 as usize).0, + orig_offset: self.0, + }) + } else { + Err(()) + } + } +} +impl SliceOffset { + pub fn offset(&self) -> usize { + self.0 + } + pub fn len(&self) -> usize { + self.1 as usize + } + pub fn len32(&self) -> u32 { + self.1 + } +} + + + +pub type StaticCommand = Command<SliceOffset>; + + +pub trait CommandProcessor<'a> { + fn push(&mut self, + val: Command<InputReference<'a> >); + fn push_literals(&mut self, data:&InputPair<'a>) { + if data.0.len() != 0 { + self.push(Command::Literal(LiteralCommand{ + data: data.0, + prob:FeatureFlagSliceType::<InputReference>::default(), + high_entropy: false, + })); + } + if data.1.len() != 0 { + self.push(Command::Literal(LiteralCommand{ + data: data.1, + prob:FeatureFlagSliceType::<InputReference>::default(), + high_entropy: false, + })); + } + } + fn push_rand_literals(&mut self, data:&InputPair<'a>) { + if data.0.len() != 0 { + self.push(Command::Literal(LiteralCommand{ + data:data.0, + prob:FeatureFlagSliceType::<InputReference>::default(), + high_entropy: true, + })); + } + if data.1.len() != 0 { + self.push(Command::Literal(LiteralCommand{ + data:data.1, + prob:FeatureFlagSliceType::<InputReference>::default(), + high_entropy: true, + })); + } + } + fn push_block_switch_literal(&mut self, block_type: u8) { + self.push(Command::BlockSwitchLiteral(LiteralBlockSwitch::new(block_type, 0))) + } +} + + +pub fn thaw_pair<'a, SliceType: Unfreezable + SliceWrapper<u8>>(xself: &Command<SliceType>, data: &InputPair<'a>) -> Command<InputReference<'a>> { + match *xself { + Command::Literal(ref lit) => { + Command::Literal(LiteralCommand{ + data:lit.data.thaw_pair(data).unwrap(), + prob:FeatureFlagSliceType::default(), + high_entropy: lit.high_entropy, + }) + }, + Command::PredictionMode(ref pm) => { + Command::PredictionMode(PredictionModeContextMap{ + literal_context_map:pm.literal_context_map.thaw_pair(data).unwrap(), + predmode_speed_and_distance_context_map:pm.predmode_speed_and_distance_context_map.thaw_pair(data).unwrap(), + }) + }, + Command::Dict(ref d) => { + Command::Dict(d.clone()) + }, + Command::Copy(ref c) => { + Command::Copy(c.clone()) + }, + Command::BlockSwitchCommand(ref c) => { + Command::BlockSwitchCommand(c.clone()) + }, + Command::BlockSwitchLiteral(ref c) => { + Command::BlockSwitchLiteral(c.clone()) + }, + Command::BlockSwitchDistance(ref c) => { + Command::BlockSwitchDistance(c.clone()) + }, + } +} + +pub fn thaw<'a, SliceType: Unfreezable + SliceWrapper<u8>>(xself: &Command<SliceType>, data: &'a[u8]) -> Command<InputReference<'a>> { + match *xself { + Command::Literal(ref lit) => { + Command::Literal(LiteralCommand{ + data:lit.data.thaw(data), + prob:FeatureFlagSliceType::default(), + high_entropy: lit.high_entropy, + }) + }, + Command::PredictionMode(ref pm) => { + Command::PredictionMode(PredictionModeContextMap{ + literal_context_map:pm.literal_context_map.thaw(data), + predmode_speed_and_distance_context_map:pm.predmode_speed_and_distance_context_map.thaw(data), + }) + }, + Command::Dict(ref d) => { + Command::Dict(d.clone()) + }, + Command::Copy(ref c) => { + Command::Copy(c.clone()) + }, + Command::BlockSwitchCommand(ref c) => { + Command::BlockSwitchCommand(c.clone()) + }, + Command::BlockSwitchLiteral(ref c) => { + Command::BlockSwitchLiteral(c.clone()) + }, + Command::BlockSwitchDistance(ref c) => { + Command::BlockSwitchDistance(c.clone()) + }, + } +} + +impl <SliceType:SliceWrapper<u8>+Freezable> Command<SliceType> { + pub fn freeze(&self) -> Command<SliceOffset> { + match *self { + Command::Literal(ref lit) => { + Command::Literal(LiteralCommand{ + data:lit.data.freeze(), + prob:FeatureFlagSliceType::default(), + high_entropy: lit.high_entropy, + }) + }, + Command::PredictionMode(ref pm) => { + Command::PredictionMode(PredictionModeContextMap{ + literal_context_map:pm.literal_context_map.freeze(), + predmode_speed_and_distance_context_map:pm.predmode_speed_and_distance_context_map.freeze(), + }) + }, + Command::Dict(ref d) => { + Command::Dict(d.clone()) + }, + Command::Copy(ref c) => { + Command::Copy(c.clone()) + }, + Command::BlockSwitchCommand(ref c) => { + Command::BlockSwitchCommand(c.clone()) + }, + Command::BlockSwitchLiteral(ref c) => { + Command::BlockSwitchLiteral(c.clone()) + }, + Command::BlockSwitchDistance(ref c) => { + Command::BlockSwitchDistance(c.clone()) + }, + } + } +} + + +#[inline(always)] +pub fn speed_to_u8(data: u16) -> u8 { + let length = 16 - data.leading_zeros() as u8; + let mantissa = if data != 0 { + let rem = data - (1 << (length - 1)); + (rem << 3) >> (length - 1) + } else { + 0 + }; + (length << 3) | mantissa as u8 +} + +#[inline(always)] +pub fn u8_to_speed(data: u8) -> u16 { + if data < 8 { + 0 + } else { + let log_val = (data >> 3) - 1; + let rem = (u16::from(data) & 0x7) << log_val; + (1u16 << log_val) | (rem >> 3) + } +} +#[cfg(test)] +mod test { + use super::speed_to_u8; + use super::u8_to_speed; + fn tst_u8_to_speed(data: u16) { + assert_eq!(u8_to_speed(speed_to_u8(data)), data); + } + #[test] + fn test_u8_to_speed() { + tst_u8_to_speed(0); + tst_u8_to_speed(1); + tst_u8_to_speed(2); + tst_u8_to_speed(3); + tst_u8_to_speed(4); + tst_u8_to_speed(5); + tst_u8_to_speed(6); + tst_u8_to_speed(7); + tst_u8_to_speed(8); + tst_u8_to_speed(10); + tst_u8_to_speed(12); + tst_u8_to_speed(16); + tst_u8_to_speed(24); + tst_u8_to_speed(32); + tst_u8_to_speed(48); + tst_u8_to_speed(64); + tst_u8_to_speed(96); + tst_u8_to_speed(768); + tst_u8_to_speed(1280); + tst_u8_to_speed(1536); + tst_u8_to_speed(1664); + } +} |