1use alloc::vec::Vec;
2use core::convert::TryInto;
3
4use crate::decoding::scratch::FSEScratch;
5use crate::decoding::scratch::HuffmanScratch;
6use crate::fse::FSETableError;
7use crate::huff0::HuffmanTableError;
8
9pub struct Dictionary {
10 pub id: u32,
11 pub fse: FSEScratch,
12 pub huf: HuffmanScratch,
13 pub dict_content: Vec<u8>,
14 pub offset_hist: [u32; 3],
15}
16
17#[derive(Debug, derive_more::Display, derive_more::From)]
18#[cfg_attr(feature = "std", derive(derive_more::Error))]
19#[non_exhaustive]
20pub enum DictionaryDecodeError {
21 #[display(
22 fmt = "Bad magic_num at start of the dictionary; Got: {got:#04X?}, Expected: {MAGIC_NUM:#04x?}"
23 )]
24 BadMagicNum { got: [u8; 4] },
25 #[display(fmt = "{_0:?}")]
26 #[from]
27 FSETableError(FSETableError),
28 #[display(fmt = "{_0:?}")]
29 #[from]
30 HuffmanTableError(HuffmanTableError),
31}
32
33pub const MAGIC_NUM: [u8; 4] = [0x37, 0xA4, 0x30, 0xEC];
34
35impl Dictionary {
36 /// parses the dictionary and set the tables
37 /// it returns the dict_id for checking with the frame's dict_id
38 pub fn decode_dict(raw: &[u8]) -> Result<Dictionary, DictionaryDecodeError> {
39 let mut new_dict = Dictionary {
40 id: 0,
41 fse: FSEScratch::new(),
42 huf: HuffmanScratch::new(),
43 dict_content: Vec::new(),
44 offset_hist: [2, 4, 8],
45 };
46
47 let magic_num: [u8; 4] = raw[..4].try_into().expect("optimized away");
48 if magic_num != MAGIC_NUM {
49 return Err(DictionaryDecodeError::BadMagicNum { got: magic_num });
50 }
51
52 let dict_id = raw[4..8].try_into().expect("optimized away");
53 let dict_id = u32::from_le_bytes(dict_id);
54 new_dict.id = dict_id;
55
56 let raw_tables = &raw[8..];
57
58 let huf_size = new_dict.huf.table.build_decoder(raw_tables)?;
59 let raw_tables = &raw_tables[huf_size as usize..];
60
61 let of_size = new_dict.fse.offsets.build_decoder(
62 raw_tables,
63 crate::decoding::sequence_section_decoder::OF_MAX_LOG,
64 )?;
65 let raw_tables = &raw_tables[of_size..];
66
67 let ml_size = new_dict.fse.match_lengths.build_decoder(
68 raw_tables,
69 crate::decoding::sequence_section_decoder::ML_MAX_LOG,
70 )?;
71 let raw_tables = &raw_tables[ml_size..];
72
73 let ll_size = new_dict.fse.literal_lengths.build_decoder(
74 raw_tables,
75 crate::decoding::sequence_section_decoder::LL_MAX_LOG,
76 )?;
77 let raw_tables = &raw_tables[ll_size..];
78
79 let offset1 = raw_tables[0..4].try_into().expect("optimized away");
80 let offset1 = u32::from_le_bytes(offset1);
81
82 let offset2 = raw_tables[4..8].try_into().expect("optimized away");
83 let offset2 = u32::from_le_bytes(offset2);
84
85 let offset3 = raw_tables[8..12].try_into().expect("optimized away");
86 let offset3 = u32::from_le_bytes(offset3);
87
88 new_dict.offset_hist[0] = offset1;
89 new_dict.offset_hist[1] = offset2;
90 new_dict.offset_hist[2] = offset3;
91
92 let raw_content = &raw_tables[12..];
93 new_dict.dict_content.extend(raw_content);
94
95 Ok(new_dict)
96 }
97}
98