1 | use super::*; |
2 | use std::collections::hash_map::*; |
3 | |
4 | pub struct Blobs { |
5 | map: HashMap<Vec<u8>, u32>, |
6 | stream: Vec<u8>, |
7 | } |
8 | |
9 | impl Default for Blobs { |
10 | fn default() -> Self { |
11 | Self { map: Default::default(), stream: vec![0] } |
12 | } |
13 | } |
14 | |
15 | impl Blobs { |
16 | pub fn insert(&mut self, value: &[u8]) -> u32 { |
17 | if value.is_empty() { |
18 | return 0; |
19 | } |
20 | |
21 | match self.map.entry(value.to_vec()) { |
22 | Entry::Vacant(entry) => { |
23 | let offset = *entry.insert(self.stream.len() as u32); |
24 | let len = value.len(); |
25 | match len { |
26 | 0..=0x7F => self.stream.push(len as u8), |
27 | 0x80..=0x3FFF => { |
28 | self.stream.push((0x80 | len >> 8) as u8); |
29 | self.stream.push((0xFF & len) as u8); |
30 | } |
31 | _ => { |
32 | self.stream.push((0xC0 | len >> 24) as u8); |
33 | self.stream.push((0xFF & len >> 16) as u8); |
34 | self.stream.push((0xFF & len >> 8) as u8); |
35 | self.stream.push((0xFF & len) as u8); |
36 | } |
37 | } |
38 | self.stream.extend_from_slice(value); |
39 | offset |
40 | } |
41 | Entry::Occupied(entry) => *entry.get(), |
42 | } |
43 | } |
44 | |
45 | pub fn into_stream(self) -> Vec<u8> { |
46 | self.stream.into_stream() |
47 | } |
48 | } |
49 | |