zstd_rs/encode/
dictionary.rs1use super::entropy::DictCTables;
5use super::matchers::{hash, read64};
6use super::params::{adjust, lookup, CParams, Strategy};
7use crate::dict::Dictionary;
8use crate::error::{Error, Result};
9use alloc::vec;
10use alloc::vec::Vec;
11
12pub struct DictMatchState {
14 pub content: Vec<u8>,
15 pub hash: Vec<u32>,
16 pub hash2: Vec<u32>,
17 pub chain: Vec<u32>,
18 pub params: CParams,
19}
20
21impl DictMatchState {
22 fn build(content: &[u8], p: CParams) -> DictMatchState {
23 let n = content.len();
24 let mls = p.min_match.clamp(4, 7);
25 let mut hash_t = vec![0u32; 1 << p.hash_log];
26 let mut hash2_t = Vec::new();
27 let mut chain_t = Vec::new();
28 let last = n.saturating_sub(8);
29 match p.strategy {
30 Strategy::Fast => {
31 for i in 0..last {
32 hash_t[hash(read64(content, i), mls, p.hash_log)] = i as u32 + 1;
33 }
34 }
35 Strategy::DFast => {
36 hash2_t = vec![0u32; 1 << p.chain_log];
37 for i in 0..last {
38 let v = read64(content, i);
39 hash_t[hash(v, 8, p.hash_log)] = i as u32 + 1;
40 hash2_t[hash(v, mls, p.chain_log)] = i as u32 + 1;
41 }
42 }
43 _ => {
44 chain_t = vec![0u32; 1 << p.chain_log];
45 let mask = (1usize << p.chain_log) - 1;
46 let hmls = super::matchers::hc::chain_mls(&p);
47 for i in 0..last {
48 let h = hash(read64(content, i), hmls, p.hash_log);
49 chain_t[i & mask] = hash_t[h];
50 hash_t[h] = i as u32 + 1;
51 }
52 }
53 }
54 DictMatchState { content: content.to_vec(), hash: hash_t, hash2: hash2_t, chain: chain_t, params: p }
55 }
56}
57
58pub struct EncoderDictionary {
60 pub(crate) id: u32,
61 pub(crate) reps: [u32; 3],
62 pub(crate) level: i32,
63 pub(crate) matcher: DictMatchState,
64 pub(crate) tables: Option<DictCTables>,
65}
66
67impl EncoderDictionary {
68 pub fn new(dict: &Dictionary, level: i32) -> Result<EncoderDictionary> {
71 if !(super::params::MIN_LEVEL..=super::params::MAX_LEVEL).contains(&level) || level == 0 {
72 return Err(Error::Parameter("compression level out of range"));
73 }
74 let size = dict.content.len() as u64;
75 let p = adjust(lookup(level, size + 500), 513, size);
76 let tables = match &dict.tables {
77 Some(t) => Some(DictCTables::new(t)?),
78 None => None,
79 };
80 Ok(EncoderDictionary { id: dict.id, reps: dict.reps, level, matcher: DictMatchState::build(&dict.content, p), tables })
81 }
82
83 pub fn level(&self) -> i32 {
85 self.level
86 }
87
88 pub fn id(&self) -> u32 {
90 self.id
91 }
92}