Skip to main content

bpack/unpack/
table.rs

1use std::collections::HashMap;
2
3pub struct Table {
4    // the length of the smallest code
5    smallest: u8,
6
7    // table itself
8    map: HashMap<u16, (u8, u8)>,
9
10    masks: Vec<u8>,
11
12    need_to_read: u8,
13
14    rest: u16,
15    bits_occupies: u8,
16}
17
18impl Table {
19    pub fn new() -> Self {
20        let masks = vec![
21            0b0000_0000, // placeholder
22            0b1000_0000, // 1
23            0b1100_0000, // 2
24            0b1110_0000, // 3
25            0b1111_0000, // 4
26            0b1111_1000, // 5
27            0b1111_1100, // 6
28            0b1111_1110, // 7
29            0b1111_1111, // 8
30        ];
31
32        // let rev_masks = vec![
33        //     0b1111_1111,
34        //     0b0111_1111,
35        //     0b0011_1111,
36        //     0b0001_1111,
37        //     0b0000_1111,
38        //     0b0000_0111,
39        //     0b0000_0011,
40        //     0b0000_0001,
41        // ];
42
43        Table {
44            smallest: u8::MAX,
45            map: HashMap::with_capacity(95),
46            masks,
47            need_to_read: u8::MAX,
48            rest: 0u16,
49            bits_occupies: 0,
50        }
51    }
52
53    pub fn set(&mut self, code: u8, bits: u16, counter: i8) {
54        if (counter as u8) < self.smallest {
55            self.smallest = counter as u8;
56            self.need_to_read = self.smallest;
57        }
58
59        // println!("bits -> {:b}, code -> {}", bits, code);
60        // assert_eq!(self.map.contains_key(&bits), false);
61        self.map.insert(bits, (code + 32, counter as u8));
62    }
63
64
65    pub fn handle(&mut self, byte: u8, v: &mut Vec<u8>, v_idx: &mut usize, o_size: usize) {
66        if *v_idx < o_size {
67            if self.bits_occupies == 0 {
68                for i in self.smallest..9 {
69                    let c = ((byte & self.masks[i as usize]) as u16) << 8;
70                    if let Some((code, length)) = self.map.get(&c) {
71                        // verify length of the bits of the code
72                        // with bits we took from current byte
73                        if i != *length {
74                            continue;
75                        }
76                        // println!("code found -> {}", code);
77                        if *v_idx < o_size {
78                            v[*v_idx] = *code;
79                            *v_idx += 1;
80                        }
81
82                        // at this point we know that rest is empty
83                        // we need to take rest of the bits
84                        // and make them first bits of the rest
85                        let bits_left = 8 - i;
86                        if bits_left >= self.smallest {
87                            panic!("bits_left >= self.smallest");
88                        }
89                        if bits_left == 0 {
90                            // nothing is left
91                            self.bits_occupies = 0;
92                            self.rest = 0u16;
93                        } else {
94                            // somethin is left
95                            // so take rest bits and make them first bits
96                            // of the rest
97                            // assert!(bits_left > 0);
98                            self.rest = (((byte & (0xff >> i)) << i) as u16) << 8;
99                            self.bits_occupies = bits_left;
100                            self.need_to_read = self.smallest - bits_left;
101                        }
102                        return;
103                    }
104                }
105                // at this point we have not found anything
106                // so bits_occupies is 0
107                // means that rest is empty
108                // take all bits of the byte
109                // and make them rest
110                self.rest = (byte as u16) << 8;
111                self.bits_occupies = 8;
112                self.need_to_read = 1;
113                println!("0 bits occupied and we got here");
114            } else {
115                // we have somthing in the rest in this case
116                for i in self.need_to_read..9 {
117                    // we have something in the rest and it
118                    // occupies some bits
119                    // say 0b(000) 0_0000_0000_0000 it takes 3 bits
120                    let mut c = ((byte & self.masks[i as usize]) as u16) << 8;
121                    c >>= self.bits_occupies;
122                    c |= self.rest;
123                    if let Some((code, length)) = self.map.get(&c) {
124                        // verify length
125                        // we had 3 bits and we also took some bits
126                        // from current byte
127                        // so 3 + some bits should be the same length
128                        // as a key we are looking for
129                        if (self.bits_occupies + i) != *length {
130                            continue;
131                        }
132                        // println!("code found -> {}", code);
133                        if *v_idx < o_size {
134                            v[*v_idx] = *code;
135                            *v_idx += 1;
136                        }
137                        // at this point we found a code
138                        // how many bits left?
139                        let bits_left = 8 - i;
140                        if bits_left >= self.smallest {
141                            // panic!("bits_left >= self.smallest");
142                            // we got to the point when more bits left
143                            // then the smallest possible
144                            // if we found a key at idx = 1
145                            // so bits left = 7
146                            // 0b(0) 000_0000
147                            // if we found a key at idx = 2
148                            // bits left = 6
149                            // 0b(00) 00_0000
150                            // 0b0000_00 (00) <- we don't need them
151                            // 0b0000_000 (0) <- this also garbage
152                            // updated byte, without bits we already took
153                            let b = (byte & (0xff >> i)) << i;
154                            for j in self.smallest..bits_left + 1 {
155                                let c = ((b & self.masks[j as usize]) as u16) << 8;
156                                if let Some((code, length)) = self.map.get(&c) {
157                                    if j != *length {
158                                        continue;
159                                    }
160                                    // println!("code found -> {}", code);
161                                    if *v_idx < o_size {
162                                        v[*v_idx] = *code;
163                                        *v_idx += 1;
164                                    }
165                                    let b_l = bits_left - j;
166                                    if b_l >= self.smallest {
167                                        panic!("bits_left >= self.smallest");
168                                    }
169                                    if b_l == 0 {
170                                        // nothing is left
171                                        self.bits_occupies = 0;
172                                        self.rest = 0u16;
173                                        self.need_to_read = self.smallest;
174                                    } else {
175                                        // somthin is left
176                                        // if previously we found at i=1
177                                        // 0b(0) 000_0000
178                                        // 7 bits left
179                                        // we shifted them
180                                        // so we added a 0 to the end
181                                        // 0b(0000_000) 0
182                                        self.rest = (((b & (0xff >> j)) << j) as u16) << 8;
183                                        self.bits_occupies = b_l;
184                                        self.need_to_read = self.smallest - b_l;
185                                    }
186                                    return;
187                                }
188                            }
189                            // at this point we have not found anything
190                            // need to set everything
191                            self.rest = (b as u16) << 8;
192                            self.bits_occupies = bits_left;
193                            self.need_to_read = 1;
194                            return;
195                        }
196                        if bits_left == 0 {
197                            // nothing is left
198                            self.bits_occupies = 0;
199                            self.rest = 0u16;
200                            self.need_to_read = self.smallest;
201                        } else {
202                            // assert!(bits_left > 0);
203                            self.rest = (((byte & (0xff >> i)) << i) as u16) << 8;
204                            self.bits_occupies = bits_left;
205                            self.need_to_read = self.smallest - bits_left;
206                        }
207                        return;
208                    }
209                }
210                // at this point we have not found anything
211                // so bits_occupies is not 0
212                // means that rest is not empty
213                // take all bits and add them to the rest
214                // update bits_occupies += 8
215
216                self.rest |= ((byte as u16) << 8) >> self.bits_occupies;
217                self.bits_occupies += 8;
218                self.need_to_read = 1;
219            }
220        }
221    }
222
223}