diff options
Diffstat (limited to 'vendor/ruzstd/src/decoding/dictionary.rs')
-rw-r--r-- | vendor/ruzstd/src/decoding/dictionary.rs | 93 |
1 files changed, 93 insertions, 0 deletions
diff --git a/vendor/ruzstd/src/decoding/dictionary.rs b/vendor/ruzstd/src/decoding/dictionary.rs new file mode 100644 index 000000000..51fbcdf0b --- /dev/null +++ b/vendor/ruzstd/src/decoding/dictionary.rs @@ -0,0 +1,93 @@ +use std::convert::TryInto; + +use crate::decoding::scratch::FSEScratch; +use crate::decoding::scratch::HuffmanScratch; +use crate::fse::FSETableError; +use crate::huff0::HuffmanTableError; + +pub struct Dictionary { + pub id: u32, + pub fse: FSEScratch, + pub huf: HuffmanScratch, + pub dict_content: Vec<u8>, + pub offset_hist: [u32; 3], +} + +#[derive(Debug, thiserror::Error)] +#[non_exhaustive] +pub enum DictionaryDecodeError { + #[error( + "Bad magic_num at start of the dictionary; Got: {got:#04X?}, Expected: {MAGIC_NUM:#04x?}" + )] + BadMagicNum { got: [u8; 4] }, + #[error(transparent)] + FSETableError(#[from] FSETableError), + #[error(transparent)] + HuffmanTableError(#[from] HuffmanTableError), +} + +pub const MAGIC_NUM: [u8; 4] = [0x37, 0xA4, 0x30, 0xEC]; + +impl Dictionary { + /// parses the dictionary and set the tables + /// it returns the dict_id for checking with the frame's dict_id + pub fn decode_dict(raw: &[u8]) -> Result<Dictionary, DictionaryDecodeError> { + let mut new_dict = Dictionary { + id: 0, + fse: FSEScratch::new(), + huf: HuffmanScratch::new(), + dict_content: Vec::new(), + offset_hist: [2, 4, 8], + }; + + let magic_num: [u8; 4] = raw[..4].try_into().expect("optimized away"); + if magic_num != MAGIC_NUM { + return Err(DictionaryDecodeError::BadMagicNum { got: magic_num }); + } + + let dict_id = raw[4..8].try_into().expect("optimized away"); + let dict_id = u32::from_le_bytes(dict_id); + new_dict.id = dict_id; + + let raw_tables = &raw[8..]; + + let huf_size = new_dict.huf.table.build_decoder(raw_tables)?; + let raw_tables = &raw_tables[huf_size as usize..]; + + let of_size = new_dict.fse.offsets.build_decoder( + raw_tables, + crate::decoding::sequence_section_decoder::OF_MAX_LOG, + )?; + let raw_tables = &raw_tables[of_size..]; + + let ml_size = new_dict.fse.match_lengths.build_decoder( + raw_tables, + crate::decoding::sequence_section_decoder::ML_MAX_LOG, + )?; + let raw_tables = &raw_tables[ml_size..]; + + let ll_size = new_dict.fse.literal_lengths.build_decoder( + raw_tables, + crate::decoding::sequence_section_decoder::LL_MAX_LOG, + )?; + let raw_tables = &raw_tables[ll_size..]; + + let offset1 = raw_tables[0..4].try_into().expect("optimized away"); + let offset1 = u32::from_le_bytes(offset1); + + let offset2 = raw_tables[4..8].try_into().expect("optimized away"); + let offset2 = u32::from_le_bytes(offset2); + + let offset3 = raw_tables[8..12].try_into().expect("optimized away"); + let offset3 = u32::from_le_bytes(offset3); + + new_dict.offset_hist[0] = offset1; + new_dict.offset_hist[1] = offset2; + new_dict.offset_hist[2] = offset3; + + let raw_content = &raw_tables[12..]; + new_dict.dict_content.extend(raw_content); + + Ok(new_dict) + } +} |