fastfibonacci/byte_decode/
faster.rs

1//! Fast fibonacci decoding using lookup tables.
2use std::collections::VecDeque;
3use std::io::Read;
4use std::marker::PhantomData;
5use std::time::Instant;
6use funty::Integral;
7use crate::byte_decode::partial::Partial;
8use crate::fastutils::State;
9use super::bytestream_transform::{IntoU16Transform, IntoU8Transform, U32BytesToU16, U32BytesToU8, U64BytesToU16, U64BytesToU8};
10use super::partial::number_plus_partial;
11// use super::u64_fibdecoder;
12use super::u64_fibdecoder_refactor;
13use once_cell::sync::Lazy;
14
15
16#[derive(Debug)]
17/// A lookup table for fast-fibonacci decoding. For a given segment of bits (represented as a u8/u16, depending in T),
18/// look up what numbers those bits encode and what de partial decoding looks like
19pub struct LookupVecNew<T> {
20    table_state0: Vec<(Vec<u64>, Partial)>,
21    table_state1: Vec<(Vec<u64>, Partial)>,
22    dummy: PhantomData<T>,
23}
24impl <T:Integral>LookupVecNew<T> {    /// Create a new Lookup table for fast fibonacci decoding using 16bit segments.
25    /// This implementation uses a vec.
26    pub fn new() -> Self {
27        let segment_size = T::BITS as usize;
28
29        let max = usize::pow(2, segment_size as u32);
30
31        let mut table_state0 = Vec::with_capacity(max);
32        let mut table_state1 = Vec::with_capacity(max);
33    
34        for lastbit in [true, false]{
35            for s in 0..max {
36
37                /* This whole conversion part is a bit hacky!! */
38                // we need to convert to the segment tye: u8, u16, depdingn on how wide the segement
39                let s_tmp: T = match s.try_into() {
40                    Ok(i) => i,
41                    Err(_) => panic!("cant convert segment to proper u8/u16.."),
42                };
43                // println!("integer {s_tmp}, binary {s_tmp:b}");
44                
45                // padding to the right
46                // let t = padding(s_tmp);
47                // println!("pad int {t}, binary {t:b}");
48                let t = s_tmp;
49                
50                // println!("Unpad {s:b}");
51                // println!("Pad   {t:b}");
52
53                // let mut dd = u64_fibdecoder::DirtyGenericSingle::new(t);
54                // let partial = Partial::new(0, 0, lastbit as u64); // it'll be overwritten by the match/err, just need to init here
55
56                // let (numbers, partial) = dd.decode_all_from_partial(partial);
57
58                // // insert result based on new state                 
59                // if lastbit {
60                //     table_state1.push((numbers, partial));
61                // }
62                // else{
63                //     table_state0.push((numbers, partial));
64                // }
65
66
67                // should probably be constructed outside the loop!
68                let mut dd = u64_fibdecoder_refactor::DirtyGenericSingle::new(t);
69                dd.partial = Partial::new(0, 0, lastbit as u64); // it'll be overwritten by the match/err, just need to init here
70                let numbers = dd.decode_all_from_partial(); //note: this updates dd.partial internally!
71
72                // insert result based on new state                 
73                if lastbit {
74                    table_state1.push((numbers, dd.partial));
75                }
76                else{
77                    table_state0.push((numbers, dd.partial));
78                }
79            }
80        }
81        LookupVecNew { table_state0, table_state1, dummy: PhantomData}
82    }
83}
84
85/// Fast Fibonacci decoding lookup table for u8/u16/... segment sizes.
86/// Note: u32 technically possible, but the table GETS HUGE (2**32 entries)
87/// and takes very long to generate.
88pub trait LookupTableNew<T> {
89    /// Given the state of the last decoding operation and the new segment, returns
90    /// the (precomputed) new state and decoding result.
91    fn lookup(&self, s: State, segment: T) -> (&[u64], &Partial);
92}
93
94impl <T:Integral> LookupTableNew<T> for LookupVecNew<T> {
95    // fn lookup(&self, s: State, segment: T) -> (Vec<u64>, Partial) {
96    fn lookup(&self, s: State, segment: T) -> (&[u64], &Partial) {
97            
98        // we're indexing into the vec, this needs to be usize
99        let idx:  usize = match segment.try_into(){
100            Ok(i) => i,
101            Err(_) => panic!("couldnt convert vec index to usize"),
102        };
103
104        let (numbers, partial) = match s {
105            State(false) => self.table_state0.get(idx).unwrap(),
106            State(true) => self.table_state1.get(idx).unwrap(),        
107        };
108        (numbers, partial)
109    }
110}
111
112#[cfg(test)]
113mod testing_lookups {
114    use bitvec::prelude::*;
115    use crate::utils::create_bitvector;
116    use super::*;
117    // use pretty_assertions::{assert_eq, assert_ne};
118
119    #[test]
120    fn test_vec8_lookup() {
121        // u8
122        let t: LookupVecNew<u8> = LookupVecNew::new();
123        let i = create_bitvector(vec![ 1,0,1,1,0,1,0,1]).load_be::<u8>();
124
125        assert_eq!(
126            t.lookup(State(false), i), 
127            (vec![4].as_slice(), &Partial { num:7, i_fibo: 4, last_bit: 1})
128        );
129
130        let i = create_bitvector(vec![ 1,0,1,1,0,1,0,1]).load_be::<u8>();
131        assert_eq!(
132            t.lookup(State(true), i), 
133            (vec![0,2].as_slice(), &Partial { num:7, i_fibo: 4, last_bit: 1})
134        );   
135
136        let i = create_bitvector(vec![ 0,1,1,1,0,0,1,0]).load_be::<u8>();
137        assert_eq!(
138            t.lookup(State(true), i), 
139            (vec![2].as_slice(), &Partial { num:6, i_fibo: 5, last_bit: 0})
140        );   
141        assert_eq!(
142            t.lookup(State(false), i), 
143            (vec![2].as_slice(), &Partial { num:6, i_fibo: 5, last_bit: 0})
144        ); 
145    }
146}
147
148
149/// Lazy LookupTable with u8 segment size.
150/// This table gets calculated once for the crate, can be reused many times for decoding.
151pub static FB_LOOKUP_NEW_U8: Lazy<LookupVecNew<u8>> = Lazy::new(|| {
152    println!("initializing fibonacci lookup");
153    let now = Instant::now();
154    let lookup = LookupVecNew::new();
155    let elapsed_time: std::time::Duration = now.elapsed();
156    println!("FB_LOOKUP_NEW_U8: done initializing fibonacci lookup in {}us", elapsed_time.as_micros());
157    lookup
158});
159
160/// Lazy LookupTable with u16 segment size.
161/// This table gets calculated once for the crate, can be reused many times for decoding.
162pub static FB_LOOKUP_NEW_U16: Lazy<LookupVecNew<u16>> = Lazy::new(|| {
163    println!("initializing fibonacci lookup");
164    let now = Instant::now();
165    let lookup = LookupVecNew::new();
166    let elapsed_time: std::time::Duration = now.elapsed();
167
168    println!("FB_LOOKUP_NEW_U16: done initializing fibonacci lookup in {}us", elapsed_time.as_micros());
169    lookup
170});
171
172/// Fast Fibonacci decoding of the entire bitstream using the precomputed lookup table.
173/// 
174/// Fibonacci decoding cannot handle zeros, and often during the encoding, every value is incremented by one (to encode zero as 1).
175/// If `shifted_by_one` is `true`, we decrement each decoded value by 1, assuming that the encoder artificially incremented each value before encoding. 
176pub fn fast_decode_new<T:Integral>(stream: &[T], shifted_by_one: bool, table: &impl LookupTableNew<T>) -> Vec<u64> {
177
178    let mut partial = Partial::new(0, 0, 0);
179    let mut decoded_numbers= Vec::new();
180
181    for &segment_int in stream {  // just go over the input bytes (or u16)
182
183        // println!("decoding integer {segment_int}, binary {segment_int:b}");
184
185        // need to pad
186        // actually dont!
187        // let segment_int_pad = padding(segment_int);
188        let segment_int_pad = segment_int;
189
190        let (numbers, p) = table.lookup(State(partial.last_bit == 1), segment_int_pad);
191        // println!("numbers {numbers:?}, partial {p:?}");
192
193        // now, we need to properly decode those numbers:
194        // if the previous segment left over something (see partial)
195        // we need to "add" this to numbers[0]
196        // if not, we need to merge p (the new partial decode from stream[i]) and partial (the old partial decode from stream(i-1))
197        if !numbers.is_empty() {
198            // println!("Combining {numbers:?} with {partial:?}");
199            // absorb `partial` (the old decoding) into the number
200            // and keep the new decoding status as is
201            let new_x = number_plus_partial(numbers[0], &partial);
202            // println!("newx {new_x}");
203            decoded_numbers.push(new_x);
204
205            decoded_numbers.extend(&numbers[1..]);
206
207
208            // numbers[0] = new_x;
209            partial = p.clone();
210        } else {
211            // "add" p and partial; ORDER is important
212            // partial = combine_partial(partial, p)
213            let mut newp = p.clone();
214            newp.combine_partial(&partial);
215            partial = newp;
216        }
217    }
218
219    // TODO: check that partial is empy!
220
221    if shifted_by_one{
222        decoded_numbers.iter().map(|x| x - 1).collect::<Vec<u64>>()
223    } else {
224        decoded_numbers
225    }
226}
227
228
229#[cfg(test)]
230mod test {
231    use crate::{byte_decode::byte_manipulation::bits_to_fibonacci_generic_array_u64, utils::create_bitvector};
232    use super::*;
233    #[test]
234    fn test_fast_decode() {
235
236        // the exampel from the paper, Fig 9.4
237        let bits = create_bitvector(vec![ 
238            1,0,1,1,0,1,0,1,
239            1,0,1,0,0,1,0,1,
240            0,1,1,1,0,0,1,0]).to_bitvec();
241
242        let bytes = bits_to_fibonacci_generic_array_u64(&bits);
243        let x_u8: Vec<u8> = U64BytesToU8::new(bytes.as_slice()).collect();
244        let x_u16: Vec<u16> = U64BytesToU16::new(bytes.as_slice()).collect();
245
246        let t: LookupVecNew<u8> = LookupVecNew::new();
247        let r = fast_decode_new(&x_u8,false, &t);
248        assert_eq!(r, vec![4,7, 86]);
249
250        let t: LookupVecNew<u16> = LookupVecNew::new();
251        let r = fast_decode_new(&x_u16,false, &t);
252        assert_eq!(r, vec![4,7, 86]);
253    }
254}
255
256
257/// Wether the byte stream originates from u64 or u32
258pub enum StreamType {
259    /// u64 
260    U64,
261    ///  u32
262    U32
263}
264/// Takes in a stream of bytes, decoding chunks of those using a lookup table.
265/// 
266/// Things are complicated: The stream of bytes usually is in groups of 8 (u64s),
267/// (but sometimes can be u32), and comes in **LittleEndian**, i.e. the 8th byte needs to be 
268/// decoded first, then the 7th...
269/// 
270pub struct FastFibonacciDecoderNewU8<'a, R:Read> {
271    //stream to decode, chunked into the right pieces to be fed into lookup table
272    stream: Box<dyn IntoU8Transform<R> +'a>, //U64BytesToU8<R>, 
273    lookup_table: &'a LookupVecNew<u8>,
274    // decoded numbers not yet emitted; once there's no new numbers, adds a `None` as terminator
275    current_buffer: VecDeque<Option<u64>>,
276    shifted_by_one: bool,
277    partial: Partial,
278}
279
280impl<'a, R:Read+'a>  FastFibonacciDecoderNewU8<'a, R> {
281    /// Creates a new decoder
282    pub fn new(stream: R, lookup_table: &'a LookupVecNew<u8>, shifted_by_one: bool, streamtype: StreamType) ->Self {
283        let chunked_u8_stream: Box<dyn IntoU8Transform<R>> = match streamtype {
284            StreamType::U64 => {
285                // things come in as 12345678|ABCDEFGH
286                // `8` is the byte that we need to look at first.
287                // we use the ChunksU64ToU8 to get the order of bytes right for decoding
288                Box::new(U64BytesToU8::new(stream))
289            },
290            StreamType::U32 => {
291                Box::new(U32BytesToU8::new(stream))
292            },
293        };
294        Self {
295            stream: chunked_u8_stream,
296            lookup_table,
297            current_buffer: VecDeque::with_capacity(8),
298            shifted_by_one,
299            partial: Default::default(),
300        }
301    }
302
303    /// pull another segment from the stream, decode
304    pub fn load_segment(&mut self) {
305
306        match self.stream.next_u8() {
307            Some(segment_int) => {
308                // decode the segment
309
310                // need to pad
311                // actually dont!
312                // let segment_int_pad = padding(segment_int);
313                let segment_int_pad = segment_int;
314                let (numbers, p) = self.lookup_table.lookup(State(self.partial.last_bit == 1), segment_int_pad);
315
316                // now, we need to properly decode those numbers:
317                // if the previous segment left over something (see partial)
318                // we need to "add" this to numbers[0]
319                // if not, we need to merge p (the new partial decode from stream[i]) and partial (the old partial decode from stream(i-1))
320
321                // this line does two things: 
322                // 1. if we got some returned numbers, we split it into numbers[0], numbers[1..] and 
323                //    update the first number with its prev partial decoding
324                // 2. if no new numbers (->None), just updated the partial
325                match numbers.split_first() {  
326                    Some((first, tail)) => {
327                        // println!("Combining {numbers:?} with {partial:?}");
328                        // absorb `partial` (the old decoding) into the number
329                        // and keep the new decoding status as is
330                        let new_x = number_plus_partial(*first, &self.partial);
331                        self.current_buffer.push_back(Some(new_x));
332                        self.current_buffer.extend(tail.iter().map(|&x| Some(x)));
333                        self.partial = p.clone();                        
334                    },
335                    None => {
336                        // "add" p and partial; ORDER is important
337                        let mut newp = p.clone();
338                        newp.combine_partial(&self.partial);
339                        self.partial = newp;                        
340                    },
341                }
342            }
343            None => {
344                // no more segments in stream
345                // assert that there's no leftovers in the current decoding
346                // and add None to buffer
347                assert!(self.partial.is_clean());
348                self.current_buffer.push_back(None);
349            }
350        }
351    }
352
353    /// number of bytes consumed from the stream
354    pub fn get_consumed_bytes(&self) -> usize {
355        self.stream.get_consumed_bytes()
356    }
357
358    /// IS the decoder in a clean state, i.e. no unemitted items and no more partial decoding
359    pub fn is_clean(&self) -> bool {
360        self.current_buffer.is_empty() && self.partial.is_clean()
361    }
362}
363
364impl<'a, R:Read+'a> Iterator for FastFibonacciDecoderNewU8<'a, R> {
365    type Item=u64;
366
367    fn next(&mut self) -> Option<Self::Item> {
368
369        // pull in new elements until we get something in the buffer to emit
370        while self.current_buffer.is_empty() {
371            self.load_segment()
372        }
373
374        let el = self.current_buffer.pop_front().unwrap(); // unwrap should be save, there HAS to be an element
375
376        if self.shifted_by_one {
377            el.map(|x| x - 1)
378        } else {
379            el
380        }
381    }
382}
383
384#[test]
385fn test_fixed_(){
386    // this corresponds to a single entry [7]
387    // 01011000_000...
388    let bytes =vec![0,0,0,0,0,0,0,88]; 
389    let t: LookupVecNew<u8> = LookupVecNew::new();
390    let mut dd = FastFibonacciDecoderNewU8::new(bytes.as_slice(), &t, false, StreamType::U64);
391    assert_eq!(dd.next(), Some(7));
392    assert_eq!(dd.next(), None);
393
394    let bytes =vec![0,0,0,0,0,0,192,90]; 
395    let t: LookupVecNew<u8> = LookupVecNew::new();
396    let mut dd = FastFibonacciDecoderNewU8::new(bytes.as_slice(), &t, false, StreamType::U64);
397    let x = dd.next();
398    assert_eq!(x, Some(7));
399    let x = dd.next();
400    assert_eq!(x, Some(7));
401    let x = dd.next();
402    assert_eq!(x, None);
403
404    // interpreting it as u32
405    let bytes =vec![0,0,0,88,0,0,0,0]; 
406    let t: LookupVecNew<u8> = LookupVecNew::new();
407    let mut dd = FastFibonacciDecoderNewU8::new(bytes.as_slice(), &t, false, StreamType::U32);
408    assert_eq!(dd.next(), Some(7));
409    assert_eq!(dd.next(), None);
410
411    // interpreting it as u32
412    let bytes =vec![0,0,192,90,0,0,0,0]; 
413    let t: LookupVecNew<u8> = LookupVecNew::new();
414    let mut dd = FastFibonacciDecoderNewU8::new(bytes.as_slice(), &t, false, StreamType::U32);
415    assert_eq!(dd.next(), Some(7));
416    assert_eq!(dd.next(), Some(7));
417    assert_eq!(dd.next(), None);
418}
419
420#[test]
421fn test_bytes_consumed_u8() {
422    // this corresponds to a single entry [7]
423    // 01011000_000...
424    let bytes =vec![0,0,0,0,0,0,0,88]; 
425    let t: LookupVecNew<u8> = LookupVecNew::new();
426    let mut dd = FastFibonacciDecoderNewU8::new(bytes.as_slice(), &t, false, StreamType::U64);
427    let x = dd.next();
428    assert_eq!(x, Some(7));
429    assert_eq!(dd.get_consumed_bytes(), 8);
430
431    let bytes =vec![0,0,0,0,0,0,0,88, 0,0,0,0,0,0,0,88]; 
432    let mut dd = FastFibonacciDecoderNewU8::new(bytes.as_slice(), &t, false, StreamType::U64);
433
434    assert_eq!(dd.next(), Some(7));
435    assert_eq!(dd.get_consumed_bytes(), 8);
436
437    // assert_eq!(dd.next(), Some(7));
438    dd.next();
439    assert_eq!(dd.get_consumed_bytes(), 16);
440
441    dd.next();
442    assert_eq!(dd.get_consumed_bytes(), 16);
443
444    assert_eq!(dd.next(), None);
445
446
447    let bytes =vec![0,0,0,88,0,0,0,88, 0,0,0,0, 0,0,0,88]; 
448
449    let mut dd = FastFibonacciDecoderNewU8::new(bytes.as_slice(), &t, false, StreamType::U32);
450    let x = dd.next();
451    assert_eq!(x, Some(7));
452    assert_eq!(dd.get_consumed_bytes(), 4);
453    dd.next();
454    assert_eq!(x, Some(7));
455    assert_eq!(dd.get_consumed_bytes(), 8);
456    dd.next();
457    // assert_eq!(x, Some(7));
458    assert_eq!(dd.get_consumed_bytes(), 16);
459
460
461}
462
463/// A Fast decoder for the bytestream, using a u16-lookup table. See [`FastFibonacciDecoderNewU8`].
464pub struct FastFibonacciDecoderNewU16<'a, R:Read> {
465    //stream to decode, chunked into the right pieces to be fed into lookup table
466    stream: Box<dyn IntoU16Transform<R> +'a>, //U64BytesToU16<R>, 
467    lookup_table: &'a LookupVecNew<u16>,
468    // decoded numbers not yet emitted; once there's no new numbers, adds a `None` as terminator
469    current_buffer: VecDeque<Option<u64>>,
470    shifted_by_one: bool,
471    partial: Partial,
472}
473
474impl<'a, R:Read+'a>  FastFibonacciDecoderNewU16<'a, R> {
475    /// Create a new FastDecoder
476    pub fn new(stream: R, lookup_table: &'a LookupVecNew<u16>, shifted_by_one: bool, streamtype: StreamType) ->Self {
477        let chunked_u16_stream: Box<dyn IntoU16Transform<R>> = match streamtype {
478            StreamType::U64 => {
479                // things come in as 12345678|ABCDEFGH
480                // `8` is the byte that we need to look at first.
481                // we use the ChunksU64ToU8 to get the order of bytes right for decoding
482                Box::new(U64BytesToU16::new(stream))
483            },
484            StreamType::U32 => {
485                Box::new(U32BytesToU16::new(stream))
486            },
487        };
488        Self {
489            stream: chunked_u16_stream,
490            lookup_table,
491            current_buffer: VecDeque::with_capacity(8), // the maximum number of elements decocded at once is 8: 11111111_11111111
492            shifted_by_one,
493            partial: Default::default(),
494        }
495    }
496
497    /// pull another segment from the stream, decode
498    pub fn load_segment(&mut self) {
499
500        // as load_Segment only gets called when the buffer is empty
501        // assert_eq!(self.current_buffer.len(), 0);
502
503        match self.stream.next_u16() {
504            Some(segment_int) => {
505                // decode the segment
506
507                // need to pad
508                // actually dont!
509                // let segment_int_pad = padding(segment_int);
510                let segment_int_pad = segment_int;
511                let (numbers, p) = self.lookup_table.lookup(State(self.partial.last_bit ==1), segment_int_pad);
512
513                // now, we need to properly decode those numbers:
514                // if the previous segment left over something (see partial)
515                // we need to "add" this to numbers[0]
516                // if not, we need to merge p (the new partial decode from stream[i]) and partial (the old partial decode from stream(i-1))
517                
518                // this line does two things: 
519                // 1. if we got some returned numbers, we split it into numbers[0], numbers[1..] and 
520                //    update the first number with its prev partial decoding
521                // 2. if no new numbers (->None), just updated the partial
522                match numbers.split_first() {  
523                    Some((first, tail)) => {
524                        // println!("Combining {numbers:?} with {partial:?}");
525                        // absorb `partial` (the old decoding) into the number
526                        // and keep the new decoding status as is
527                        let new_x = number_plus_partial(*first, &self.partial);
528                        self.current_buffer.push_back(Some(new_x));
529                        self.current_buffer.extend(tail.iter().map(|&x| Some(x)));
530                        self.partial = p.clone();                        
531                    },
532                    None => {
533                        // "add" p and partial; ORDER is important
534                        let mut newp = p.clone();
535                        newp.combine_partial(&self.partial);
536                        self.partial = newp;                        
537                    },
538                }
539            }
540            None => {
541                // no more segments in stream
542                // assert that there's no leftovers in the current decoding
543                // and add None to buffer
544                assert!(self.partial.is_clean());
545                self.current_buffer.push_back(None);
546            }
547        }
548    }
549
550    /// number of bytes consumed out of the stream
551    pub fn get_consumed_bytes(&self) -> usize {
552        self.stream.get_consumed_bytes()
553    }
554    
555    /// IS the decoder in a clean state, i.e. no unemitted items and no more partial decoding
556    pub fn is_clean(&self) -> bool {
557        self.current_buffer.is_empty() && self.partial.is_clean()
558    }
559}
560
561
562impl<'a, R:Read+'a> Iterator for FastFibonacciDecoderNewU16<'a, R> {
563    type Item=u64;
564
565    fn next(&mut self) -> Option<Self::Item> {
566
567
568        // pull in new elements until we get something in the buffer to emit
569        while self.current_buffer.is_empty() {
570            self.load_segment()
571        }
572
573        let el = self.current_buffer.pop_front().unwrap(); // unwrap should be save, there HAS to be an element
574
575        if self.shifted_by_one {
576            el.map(|x| x - 1)
577        } else {
578            el
579        }
580    }
581}
582
583#[test]
584fn test_fixed_u16(){
585    // this corresponds to a single entry [7]
586    // 01011000_000...
587    let bytes =vec![0,0,0,0,0,0,0,88]; 
588    let t: LookupVecNew<u16> = LookupVecNew::new();
589    let mut dd = FastFibonacciDecoderNewU16::new(bytes.as_slice(), &t, false, StreamType::U64);
590    let x = dd.next();
591    
592    assert_eq!(x, Some(7));
593
594
595    let bytes =vec![0,0,0,0,0,0,192,90]; 
596    let t: LookupVecNew<u16> = LookupVecNew::new();
597    let mut dd = FastFibonacciDecoderNewU16::new(bytes.as_slice(), &t, false, StreamType::U64);
598    let x = dd.next();
599    
600    assert_eq!(x, Some(7));
601    let x = dd.next();
602    assert_eq!(x, Some(7));
603
604    let x = dd.next();
605    assert_eq!(x, None);
606}
607
608#[test]
609fn test_bytes_consumed_u16() {
610    // this corresponds to a single entry [7]
611    // 01011000_000...
612    let bytes =vec![0,0,0,0,0,0,0,88]; 
613    let t: LookupVecNew<u16> = LookupVecNew::new();
614    let mut dd = FastFibonacciDecoderNewU16::new(bytes.as_slice(), &t, false, StreamType::U64);
615    assert_eq!(dd.next(), Some(7));
616    assert_eq!(dd.get_consumed_bytes(), 8);
617
618    let bytes =vec![0,0,0,0,0,0,0,88, 0,0,0,0,0,0,0,88]; 
619    let mut dd = FastFibonacciDecoderNewU16::new(bytes.as_slice(), &t, false, StreamType::U64);
620
621    assert_eq!(dd.next(), Some(7));
622    assert_eq!(dd.get_consumed_bytes(), 8);
623
624    // assert_eq!(dd.next(), Some(7));
625    dd.next();
626    assert_eq!(dd.get_consumed_bytes(), 16);
627
628    dd.next();
629    assert_eq!(dd.get_consumed_bytes(), 16);
630
631    assert_eq!(dd.next(), None);
632
633    let bytes =vec![0,0,0,88,0,0,0,88, 0,0,0,0,0,0,0,88]; 
634    let mut dd = FastFibonacciDecoderNewU16::new(bytes.as_slice(), &t, false, StreamType::U32);
635    assert_eq!(dd.next(), Some(7));
636    assert_eq!(dd.get_consumed_bytes(), 4);
637    dd.next();
638    assert_eq!(dd.get_consumed_bytes(), 8);
639    dd.next();
640    assert_eq!(dd.get_consumed_bytes(), 16);
641
642}