zstd_complete/encoding/match_generator/
driver.rs1use super::*;
2
3pub struct MatchGeneratorDriver {
5 pub(super) vec_pool: Vec<Vec<u8>>,
6 pub(super) suffix_pool: Vec<SuffixStore>,
7 pub(super) match_generator: MatchGenerator,
8 pub(super) slice_size: usize,
9 pub(super) suffix_store_capacity: usize,
10 pub(super) adaptive_binary_no_match_probe: bool,
11 pub(super) use_fast_small_dense_binary_probe: bool,
12 pub(super) prefer_binary_next_position_repeat_lookahead: bool,
13 pub(super) prefer_fast_binary_next_position_repeat_lookahead: bool,
14 pub(super) prefer_binary_next_position_lookahead: bool,
15 pub(super) prefer_oldest_first_window_probe: bool,
16 pub(super) use_complementary_end_insertion: bool,
17 pub(super) use_second_newest_probe: bool,
18 pub(super) use_fast_binary_small_second_newest: bool,
19 pub(super) use_text_repeat_pipeline: bool,
20 pub(super) file_type_hint: CompressionFileType,
21 pub(super) file_profile_hint: CompressionFileProfile,
22}
23
24impl MatchGeneratorDriver {
25 pub(crate) fn new(slice_size: usize, max_slices_in_window: usize) -> Self {
28 Self {
29 vec_pool: Vec::new(),
30 suffix_pool: Vec::new(),
31 match_generator: MatchGenerator::new(max_slices_in_window * slice_size),
32 slice_size,
33 suffix_store_capacity: slice_size / SUFFIX_STORE_CAPACITY_DIVISOR,
34 adaptive_binary_no_match_probe: false,
35 use_fast_small_dense_binary_probe: false,
36 prefer_binary_next_position_repeat_lookahead: false,
37 prefer_fast_binary_next_position_repeat_lookahead: false,
38 prefer_binary_next_position_lookahead: false,
39 prefer_oldest_first_window_probe: false,
40 use_complementary_end_insertion: false,
41 use_second_newest_probe: false,
42 use_fast_binary_small_second_newest: false,
43 use_text_repeat_pipeline: false,
44 file_type_hint: CompressionFileType::Unknown,
45 file_profile_hint: CompressionFileProfile::None,
46 }
47 }
48
49 #[cfg(test)]
50 pub(crate) fn repeat_offsets(&self) -> (u32, u32, u32) {
51 self.match_generator.offset_history.as_offsets()
52 }
53
54 #[cfg(all(test, feature = "std"))]
55 pub(crate) fn diagnostics(&self) -> Ref<'_, MatcherDiagnostics> {
56 self.match_generator.diagnostics.borrow()
57 }
58}
59
60impl Matcher for MatchGeneratorDriver {
61 fn set_file_type_hint(&mut self, file_type: CompressionFileType) {
62 self.file_type_hint = file_type;
63 self.match_generator.file_type_hint = file_type;
64 }
65
66 fn set_internal_file_profile_hint(&mut self, file_profile_code: u8) {
67 let file_profile = CompressionFileProfile::from_internal_hint_code(file_profile_code);
68 self.file_profile_hint = file_profile;
69 self.match_generator.file_profile_hint = file_profile;
70 }
71
72 fn reset(&mut self, level: CompressionLevel) {
73 let vec_pool = &mut self.vec_pool;
74 let suffix_pool = &mut self.suffix_pool;
75 let fast_window_size = self.slice_size * FASTEST_WINDOW_BLOCKS;
76 self.suffix_store_capacity = Self::suffix_store_capacity(self.slice_size, level);
77 self.adaptive_binary_no_match_probe = Self::adaptive_binary_no_match_probe(level);
78 self.use_fast_small_dense_binary_probe = Self::use_fast_small_dense_binary_probe(level);
79 self.prefer_binary_next_position_repeat_lookahead =
80 Self::prefer_binary_next_position_repeat_lookahead(level);
81 self.prefer_fast_binary_next_position_repeat_lookahead =
82 Self::prefer_fast_binary_next_position_repeat_lookahead(level);
83 self.prefer_binary_next_position_lookahead =
84 Self::prefer_binary_next_position_lookahead(level);
85 self.prefer_oldest_first_window_probe = Self::prefer_oldest_first_window_probe(level);
86 self.use_complementary_end_insertion = Self::use_complementary_end_insertion(level);
87 self.use_second_newest_probe = Self::use_second_newest_probe(level);
88 self.use_fast_binary_small_second_newest = Self::use_fast_binary_small_second_newest(level);
89 self.use_text_repeat_pipeline = Self::use_text_repeat_pipeline(level);
90
91 self.match_generator.reset(|mut data, mut suffixes| {
92 data.resize(data.capacity(), 0);
93 vec_pool.push(data);
94 suffixes.clear();
95 suffix_pool.push(suffixes);
96 });
97 self.match_generator.set_window_sizes(
98 self.slice_size * Self::window_blocks(level),
99 fast_window_size,
100 );
101 self.match_generator.adaptive_binary_no_match_probe = self.adaptive_binary_no_match_probe;
102 self.match_generator.use_fast_small_dense_binary_probe =
103 self.use_fast_small_dense_binary_probe;
104 self.match_generator
105 .prefer_binary_next_position_repeat_lookahead =
106 self.prefer_binary_next_position_repeat_lookahead;
107 self.match_generator
108 .prefer_fast_binary_next_position_repeat_lookahead =
109 self.prefer_fast_binary_next_position_repeat_lookahead;
110 self.match_generator.prefer_binary_next_position_lookahead =
111 self.prefer_binary_next_position_lookahead;
112 self.match_generator.prefer_oldest_first_window_probe =
113 self.prefer_oldest_first_window_probe;
114 self.match_generator.use_complementary_end_insertion = self.use_complementary_end_insertion;
115 self.match_generator.use_second_newest_probe = self.use_second_newest_probe;
116 self.match_generator.use_fast_binary_small_second_newest =
117 self.use_fast_binary_small_second_newest;
118 self.match_generator.use_text_repeat_pipeline = self.use_text_repeat_pipeline;
119 self.match_generator.file_type_hint = self.file_type_hint;
120 self.match_generator.file_profile_hint = self.file_profile_hint;
121 }
122
123 fn window_size(&self) -> u64 {
124 self.match_generator.max_window_size as u64
125 }
126
127 fn get_next_space(&mut self) -> Vec<u8> {
128 match self.vec_pool.pop() {
129 Some(space) => space,
130 None => {
131 let mut space = alloc::vec![0; self.slice_size];
132 space.resize(space.capacity(), 0);
133 space
134 }
135 }
136 }
137
138 fn get_last_space(&self) -> &[u8] {
139 self.match_generator.last_entry().data.as_slice()
140 }
141
142 fn commit_space(&mut self, space: Vec<u8>) {
143 let vec_pool = &mut self.vec_pool;
144 let suffix_capacity = self.suffix_store_capacity;
145 let suffixes = match self.suffix_pool.pop() {
146 Some(suffixes)
147 if suffixes.capacity() == SuffixStore::normalized_capacity(suffix_capacity) =>
148 {
149 suffixes
150 }
151 _ => SuffixStore::with_capacity(suffix_capacity),
152 };
153 let suffix_pool = &mut self.suffix_pool;
154 self.match_generator
155 .add_data(space, suffixes, |mut data, mut suffixes| {
156 data.resize(data.capacity(), 0);
157 vec_pool.push(data);
158 suffixes.clear();
159 suffix_pool.push(suffixes);
160 });
161 }
162
163 fn start_matching(&mut self, mut handle_sequence: impl for<'a> FnMut(Sequence<'a>)) {
164 while self.match_generator.next_sequence(&mut handle_sequence) {}
165 }
166
167 fn set_repeat_offsets(&mut self, newest: u32, second: u32, third: u32) {
168 self.match_generator.offset_history = OffsetHistory::from_offsets(newest, second, third);
169 }
170
171 fn skip_matching(&mut self) {
172 self.match_generator.skip_matching();
173 }
174
175 fn skip_matching_for_incompressible(&mut self) {
176 self.match_generator.skip_matching_for_incompressible();
177 }
178
179 fn skip_matching_for_rle(&mut self) {
180 self.match_generator.skip_matching_for_rle();
181 }
182}
183
184impl MatchGeneratorDriver {
185 fn window_blocks(level: CompressionLevel) -> usize {
186 if level.uses_best_legacy_profile() {
187 BEST_WINDOW_BLOCKS
188 } else {
189 FASTEST_WINDOW_BLOCKS
190 }
191 }
192
193 fn suffix_store_capacity(slice_size: usize, level: CompressionLevel) -> usize {
194 if level.uses_best_legacy_profile() {
195 slice_size * BEST_SUFFIX_STORE_CAPACITY_MULTIPLIER
196 } else {
197 slice_size / SUFFIX_STORE_CAPACITY_DIVISOR
198 }
199 }
200
201 fn adaptive_binary_no_match_probe(level: CompressionLevel) -> bool {
202 level.uses_best_legacy_profile()
203 }
204
205 fn use_fast_small_dense_binary_probe(level: CompressionLevel) -> bool {
206 level.uses_fastest_legacy_profile()
207 }
208
209 fn prefer_binary_next_position_repeat_lookahead(level: CompressionLevel) -> bool {
210 level.uses_best_legacy_profile()
211 }
212
213 fn prefer_fast_binary_next_position_repeat_lookahead(level: CompressionLevel) -> bool {
214 level.uses_fastest_legacy_profile()
215 }
216
217 fn prefer_binary_next_position_lookahead(level: CompressionLevel) -> bool {
218 level.uses_best_legacy_profile()
219 }
220
221 fn prefer_oldest_first_window_probe(level: CompressionLevel) -> bool {
222 level.uses_best_legacy_profile()
223 }
224
225 fn use_complementary_end_insertion(level: CompressionLevel) -> bool {
226 level.uses_best_legacy_profile()
227 }
228
229 fn use_second_newest_probe(level: CompressionLevel) -> bool {
230 level.uses_best_legacy_profile()
231 }
232
233 fn use_fast_binary_small_second_newest(level: CompressionLevel) -> bool {
234 level.uses_fastest_legacy_profile()
235 }
236
237 fn use_text_repeat_pipeline(level: CompressionLevel) -> bool {
238 level.uses_best_legacy_profile()
239 }
240}