1 use super::interface;
2 use super::super::alloc::SliceWrapper;
3 use super::histogram::ContextType;
4 use super::input_pair::InputReference;
5 use super::constants::{kSigned3BitContextLookup, kUTF8ContextLookup};
6 use super::interface::LiteralPredictionModeNibble;
7 pub trait IRInterpreter {
inc_local_byte_offset(&mut self, inc:usize)8     fn inc_local_byte_offset(&mut self, inc:usize);
local_byte_offset(&self) -> usize9     fn local_byte_offset(&self) -> usize;
update_block_type(&mut self, new_type: u8, new_stride: u8)10     fn update_block_type(&mut self, new_type: u8, new_stride: u8);
block_type(&self) -> u811     fn block_type(&self) -> u8;
literal_data_at_offset(&self, index: usize) -> u812     fn literal_data_at_offset(&self, index: usize) -> u8;
literal_context_map(&self) -> &[u8]13     fn literal_context_map(&self) -> &[u8];
prediction_mode(&self) -> ::interface::LiteralPredictionModeNibble14     fn prediction_mode(&self) -> ::interface::LiteralPredictionModeNibble;
update_cost(&mut self, stride_prior: [u8;8], stride_byte_offset: usize, selected_bits:u8, cm_prior: usize, literal: u8)15     fn update_cost(&mut self, stride_prior: [u8;8], stride_byte_offset: usize, selected_bits:u8, cm_prior: usize, literal: u8);
16 }
17 
18 
push_base<'a, Interpreter: IRInterpreter>(xself: &mut Interpreter, val: interface::Command<InputReference<'a>>)19 pub fn push_base<'a,
20                  Interpreter: IRInterpreter>(xself: &mut Interpreter,
21                                              val: interface::Command<InputReference<'a>>) {
22         match val {
23            interface::Command::BlockSwitchCommand(_) |
24            interface::Command::BlockSwitchDistance(_) |
25            interface::Command::PredictionMode(_) => {}
26            interface::Command::Copy(ref copy) => {
27                xself.inc_local_byte_offset(copy.num_bytes as usize);
28            },
29            interface::Command::Dict(ref dict) => {
30                xself.inc_local_byte_offset(dict.final_size as usize);
31            },
32             interface::Command::BlockSwitchLiteral(block_type) => xself.update_block_type(block_type.block_type(),
33                                                                                           block_type.stride()),
34            interface::Command::Literal(ref lit) => {
35                //let stride = xself.get_stride(xself.local_byte_offset()) as usize;
36                let mut priors= [0u8; 8];
37                for poffset in 0..8 {
38                    if xself.local_byte_offset() > poffset {
39                        let input_offset = xself.local_byte_offset() - poffset -  1;
40                        priors[7 - poffset] = xself.literal_data_at_offset(input_offset);
41                    }
42                }
43                let mut cur = 0usize;
44                for literal in lit.data.slice().iter() {
45                    let (huffman_table_index, selected_bits) = compute_huffman_table_index_for_context_map(priors[(cur + 7)&7], priors[(cur + 6) &7], xself.literal_context_map(), xself.prediction_mode(), xself.block_type());
46                    xself.update_cost(priors, (cur + 7) & 7, selected_bits, huffman_table_index, *literal);
47                    priors[cur & 7] = *literal;
48                    cur += 1;
49                    cur &= 7;
50                }
51                xself.inc_local_byte_offset(lit.data.slice().len());
52            }
53         }
54     }
55 
56 
57 // not sure why this fails
58 //impl<'a> interface::CommandProcessor<'a> for IRInterpreter {
59 //    fn push<Cb: FnMut(&[interface::Command<InputReference>])>(&mut self,
60 //                                                              val: interface::Command<InputReference<'a>>,
61 //                                                              callback: &mut Cb) {
62 //        push_base(self, val, callback)
63 //    }
64 //}
65 
66 
67 
compute_huffman_table_index_for_context_map( prev_byte: u8, prev_prev_byte: u8, literal_context_map: &[u8], prediction_mode: LiteralPredictionModeNibble, block_type: u8, ) -> (usize, u8)68 fn compute_huffman_table_index_for_context_map (
69     prev_byte: u8,
70     prev_prev_byte: u8,
71     literal_context_map: &[u8],//interface::PredictionModeContextMap<SliceType>,
72     prediction_mode: LiteralPredictionModeNibble,
73     block_type: u8,
74 ) -> (usize, u8) {
75     let prior = Context(prev_byte, prev_prev_byte, prediction_mode.to_context_enum().unwrap());
76     assert!(prior < 64);
77     let context_map_index = ((block_type as usize)<< 6) | prior as usize;
78     if context_map_index < literal_context_map.len() {
79         (literal_context_map[context_map_index] as usize, prior)
80     } else {
81         (prior as usize, prior)
82     }
83 }
84 
Context(p1: u8, p2: u8, mode: ContextType) -> u885 pub fn Context(p1: u8, p2: u8, mode: ContextType) -> u8 {
86   match mode {
87     ContextType::CONTEXT_LSB6 => {
88       return (p1 as (i32) & 0x3fi32) as (u8);
89     }
90     ContextType::CONTEXT_MSB6 => {
91       return (p1 as (i32) >> 2i32) as (u8);
92     }
93     ContextType::CONTEXT_UTF8 => {
94       return (kUTF8ContextLookup[p1 as (usize)] as (i32) |
95               kUTF8ContextLookup[(p2 as (i32) + 256i32) as (usize)] as (i32)) as (u8);
96     }
97     ContextType::CONTEXT_SIGNED => {
98       return ((kSigned3BitContextLookup[p1 as (usize)] as (i32) << 3i32) +
99               kSigned3BitContextLookup[p2 as (usize)] as (i32)) as (u8);
100     }
101   }
102   //  0i32 as (u8)
103 }
104