1use core::cmp::{max, min};
2pub const kNumDistanceCacheEntries: usize = 4;
3
4use super::super::dictionary::{
5 kBrotliDictionary, kBrotliDictionaryOffsetsByLength, kBrotliDictionarySizeBitsByLength,
6};
7use super::static_dict_lut::{
8 kDictHashMul32, kDictNumBits, kStaticDictionaryBuckets, kStaticDictionaryWords, DictWord,
9};
10#[allow(unused)]
11static kUppercaseFirst: u8 = 10u8;
12
13#[allow(unused)]
14static kOmitLastNTransforms: [u8; 10] = [0, 12, 27, 23, 42, 63, 56, 48, 59, 64];
15
16pub struct BrotliDictionary {
17 pub size_bits_by_length: &'static [u8; 25],
18 pub offsets_by_length: &'static [u32; 25],
19 pub data: &'static [u8; 122784],
20}
21
22pub static kBrotliEncDictionary: BrotliDictionary = BrotliDictionary {
23 size_bits_by_length: &kBrotliDictionarySizeBitsByLength,
24 offsets_by_length: &kBrotliDictionaryOffsetsByLength,
25 data: &kBrotliDictionary,
26};
27
28#[inline(always)]
29pub fn BrotliGetDictionary() -> &'static BrotliDictionary {
30 &kBrotliEncDictionary
31}
32#[inline(always)]
33pub fn BROTLI_UNALIGNED_LOAD32(sl: &[u8]) -> u32 {
34 let mut p = [0u8; 4];
35 p[..].clone_from_slice(sl.split_at(4).0);
36 (p[0] as u32) | ((p[1] as u32) << 8) | ((p[2] as u32) << 16) | ((p[3] as u32) << 24)
37}
38#[inline(always)]
39pub fn Hash(data: &[u8]) -> u32 {
40 let h: u32 = BROTLI_UNALIGNED_LOAD32(data).wrapping_mul(kDictHashMul32);
41 h >> (32i32 - kDictNumBits)
42}
43#[inline(always)]
44pub fn BROTLI_UNALIGNED_LOAD64(sl: &[u8]) -> u64 {
45 let mut p = [0u8; 8];
46 p[..].clone_from_slice(sl.split_at(8).0);
47 (p[0] as u64)
48 | ((p[1] as u64) << 8)
49 | ((p[2] as u64) << 16)
50 | ((p[3] as u64) << 24)
51 | ((p[4] as u64) << 32)
52 | ((p[5] as u64) << 40)
53 | ((p[6] as u64) << 48)
54 | ((p[7] as u64) << 56)
55}
56#[inline(always)]
57pub fn BROTLI_UNALIGNED_STORE64(outp: &mut [u8], v: u64) {
58 let p = [
59 (v & 0xff) as u8,
60 ((v >> 8) & 0xff) as u8,
61 ((v >> 16) & 0xff) as u8,
62 ((v >> 24) & 0xff) as u8,
63 ((v >> 32) & 0xff) as u8,
64 ((v >> 40) & 0xff) as u8,
65 ((v >> 48) & 0xff) as u8,
66 ((v >> 56) & 0xff) as u8,
67 ];
68 outp.split_at_mut(8).0.clone_from_slice(&p[..]);
69}
70
71macro_rules! sub_match {
72 ($s1 : expr, $s2 : expr, $limit : expr, $matched : expr, $split_pair1 : expr, $split_pair2 : expr, $s1_lo : expr, $s2_lo : expr, $s1_as_64 : expr, $s2_as_64 : expr, $vec_len: expr) => {
73 $split_pair1 = $s1.split_at($vec_len);
74 $s1_lo[..$vec_len].clone_from_slice($split_pair1.0);
75 $s1 = $split_pair1.1;
76 $split_pair2 = $s2.split_at($vec_len);
77 $s2_lo[..$vec_len].clone_from_slice($split_pair2.0);
78 $s2 = $split_pair2.1;
79 $limit -= $vec_len;
80 for index in 0..($vec_len >> 3) {
81 $s1_as_64 = BROTLI_UNALIGNED_LOAD64(&$s1_lo[(index << 3)..((index + 1) << 3)]);
82 $s2_as_64 = BROTLI_UNALIGNED_LOAD64(&$s2_lo[(index << 3)..((index + 1) << 3)]);
83 if $s2_as_64 == $s1_as_64 {
84 $matched = $matched.wrapping_add(8) as u32 as usize;
85 } else {
86 $matched = $matched
87 .wrapping_add((($s2_as_64 ^ $s1_as_64).trailing_zeros() >> 3) as usize)
88 as u32 as usize;
89 return $matched;
90 }
91 }
92 };
93}
94
95macro_rules! sub_match8 {
96 ($s1 : expr, $s2 : expr, $limit : expr, $matched : expr, $s1_as_64 : expr, $s2_as_64 : expr) => {
97 $limit -= 8;
98 $s1_as_64 = BROTLI_UNALIGNED_LOAD64($s1);
99 $s1 = $s1.split_at(8).1;
100 $s2_as_64 = BROTLI_UNALIGNED_LOAD64($s2);
101 $s2 = $s2.split_at(8).1;
102 if $s2_as_64 == $s1_as_64 {
103 $matched = $matched.wrapping_add(8) as u32 as usize;
104 } else {
105 $matched = $matched
106 .wrapping_add((($s2_as_64 ^ $s1_as_64).trailing_zeros() >> 3) as usize)
107 as u32 as usize;
108 return $matched;
109 }
110 };
111}
112
113#[allow(unused)]
115pub fn SlowerFindMatchLengthWithLimit(s1: &[u8], s2: &[u8], limit: usize) -> usize {
116 for index in 0..limit {
117 if s1[index] != s2[index] {
118 return index;
119 }
120 }
121 limit
122}
123#[allow(unused)]
125pub fn FindMatchLengthWithLimit(s1: &[u8], s2: &[u8], limit: usize) -> usize {
126 for (index, pair) in s1[..limit].iter().zip(s2[..limit].iter()).enumerate() {
127 if *pair.0 != *pair.1 {
128 return index;
129 }
130 }
131 limit
132}
133#[allow(unused)]
134pub fn FindMatchLengthWithLimitMin4(s1: &[u8], s2: &[u8], limit: usize) -> usize {
135 let (s1_start, s1_rest) = s1.split_at(5);
136 let (s2_start, s2_rest) = s2.split_at(5);
137 let v0 = BROTLI_UNALIGNED_LOAD32(s1_start);
138 let v1 = BROTLI_UNALIGNED_LOAD32(s2_start);
139 let beyond_ok = s1_start[4] != s2_start[4];
140 if v0 != v1 {
141 return 0;
142 }
143 if limit <= 4 || beyond_ok {
144 return min(limit, 4);
145 }
146 ComplexFindMatchLengthWithLimit(s1_rest, s2_rest, limit - 5) + 5
147}
148#[inline]
149pub fn ComplexFindMatchLengthWithLimit(mut s1: &[u8], mut s2: &[u8], mut limit: usize) -> usize {
150 let mut matched: usize = 0usize;
151 let mut s1_as_64: u64;
152 let mut s2_as_64: u64;
153 if limit >= 8 {
154 sub_match8!(s1, s2, limit, matched, s1_as_64, s2_as_64);
155 if limit >= 16 {
156 let mut split_pair1: (&[u8], &[u8]);
157 let mut split_pair2: (&[u8], &[u8]);
158 {
159 let mut s1_lo = [0u8; 16];
160 let mut s1_hi = [0u8; 16];
161 sub_match!(
162 s1,
163 s2,
164 limit,
165 matched,
166 split_pair1,
167 split_pair2,
168 s1_lo,
169 s1_hi,
170 s1_as_64,
171 s2_as_64,
172 16
173 );
174 }
175 if limit >= 32 {
176 let mut s1_lo_a = [0u8; 128];
177 let mut s1_hi_a = [0u8; 128];
178 sub_match!(
179 s1,
180 s2,
181 limit,
182 matched,
183 split_pair1,
184 split_pair2,
185 s1_lo_a,
186 s1_hi_a,
187 s1_as_64,
188 s2_as_64,
189 32
190 );
191 if limit >= 64 {
192 sub_match!(
193 s1,
194 s2,
195 limit,
196 matched,
197 split_pair1,
198 split_pair2,
199 s1_lo_a,
200 s1_hi_a,
201 s1_as_64,
202 s2_as_64,
203 64
204 );
205 while limit >= 128 {
206 sub_match!(
207 s1,
208 s2,
209 limit,
210 matched,
211 split_pair1,
212 split_pair2,
213 s1_lo_a,
214 s1_hi_a,
215 s1_as_64,
216 s2_as_64,
217 128
218 );
219 }
220 }
221 }
222 }
223 while limit >= 8 {
224 sub_match8!(s1, s2, limit, matched, s1_as_64, s2_as_64);
225 }
226 }
227 assert!(s1.len() >= (limit & 7usize));
228 assert!(s2.len() >= (limit & 7usize));
229 for index in 0..(limit & 7usize) {
230 if s1[index] != s2[index] {
231 return matched + index;
232 }
233 }
234 matched + (limit & 7usize) }
236
237#[allow(unused)]
238pub fn slowFindMatchLengthWithLimit(s1: &[u8], s2: &[u8], limit: usize) -> usize {
239 for (index, it) in s1[..limit].iter().zip(s2[..limit].iter()).enumerate() {
240 if it.0 != it.1 {
241 return index;
242 }
243 }
244 limit
245}
246
247pub fn IsMatch(dictionary: &BrotliDictionary, w: DictWord, data: &[u8], max_length: usize) -> i32 {
248 if w.l as usize > max_length {
249 0
250 } else {
251 let offset: usize = (dictionary.offsets_by_length[w.l as usize] as usize)
252 .wrapping_add((w.len() as usize).wrapping_mul(w.idx() as usize));
253 let dict = &dictionary.data.split_at(offset).1;
254 if w.transform() as i32 == 0i32 {
255 if FindMatchLengthWithLimit(dict, data, w.l as usize) == w.l as usize {
256 1
257 } else {
258 0
259 }
260 } else if w.transform() as i32 == 10i32 {
261 if dict[0] as i32 >= b'a' as i32
262 && (dict[0] as i32 <= b'z' as i32)
263 && (dict[0] as i32 ^ 32i32 == data[0] as i32)
264 && (FindMatchLengthWithLimit(
265 dict.split_at(1).1,
266 data.split_at(1).1,
267 (w.len() as u32).wrapping_sub(1) as usize,
268 ) == (w.len() as u32).wrapping_sub(1) as usize)
269 {
270 1
271 } else {
272 0
273 }
274 } else {
275 for i in 0usize..w.len() as usize {
276 if dict[i] as i32 >= b'a' as i32 && (dict[i] as i32 <= b'z' as i32) {
277 if dict[i] as i32 ^ 32i32 != data[i] as i32 {
278 return 0;
279 }
280 } else if dict[i] as i32 != data[i] as i32 {
281 return 0;
282 }
283 }
284 1
285 }
286 }
287}
288
289#[allow(unused)]
290fn AddMatch(distance: usize, len: usize, len_code: usize, mut matches: &mut [u32]) {
291 let match_: u32 = (distance << 5).wrapping_add(len_code) as u32;
292 matches[len] = min(matches[len], match_);
293}
294
295#[allow(unused)]
296fn DictMatchLength(
297 dictionary: &BrotliDictionary,
298 data: &[u8],
299 id: usize,
300 len: usize,
301 maxlen: usize,
302) -> usize {
303 let offset: usize =
304 (dictionary.offsets_by_length[len] as usize).wrapping_add(len.wrapping_mul(id));
305 FindMatchLengthWithLimit(dictionary.data.split_at(offset).1, data, min(len, maxlen))
306}
307
308#[allow(unused)]
309pub fn BrotliFindAllStaticDictionaryMatches(
310 dictionary: &BrotliDictionary,
311 data: &[u8],
312 min_length: usize,
313 max_length: usize,
314 mut matches: &mut [u32],
315) -> i32 {
316 let mut has_found_match: i32 = 0i32;
317 {
318 let mut offset: usize = kStaticDictionaryBuckets[Hash(data) as usize] as usize;
319 let mut end: i32 = (offset == 0) as i32;
320 while end == 0 {
321 let mut w: DictWord = kStaticDictionaryWords[offset];
322 offset = offset.wrapping_add(1);
323 let l: usize = (w.len() as i32 & 0x1fi32) as usize;
324 let n: usize = 1usize << dictionary.size_bits_by_length[l] as i32;
325 let id: usize = w.idx() as usize;
326 end = !(w.len() as i32 & 0x80i32 == 0) as i32;
327 w.l = l as u8;
328 if w.transform() as i32 == 0i32 {
329 let matchlen: usize = DictMatchLength(dictionary, data, id, l, max_length);
330
331 let mut minlen: usize;
332
333 let mut len: usize;
334 if matchlen == l {
335 AddMatch(id, l, l, matches);
337 has_found_match = 1i32;
338 }
339 if matchlen >= l.wrapping_sub(1) {
340 AddMatch(
342 id.wrapping_add((12usize).wrapping_mul(n)),
343 l.wrapping_sub(1),
344 l,
345 matches,
346 );
347 if l.wrapping_add(2) < max_length
348 && (data[(l.wrapping_sub(1) as usize)] as i32 == b'i' as i32)
349 && (data[(l as usize)] as i32 == b'n' as i32)
350 && (data[(l.wrapping_add(1) as usize)] as i32 == b'g' as i32)
351 && (data[(l.wrapping_add(2) as usize)] as i32 == b' ' as i32)
352 {
353 AddMatch(
355 id.wrapping_add((49usize).wrapping_mul(n)),
356 l.wrapping_add(3),
357 l,
358 matches,
359 );
360 }
361 has_found_match = 1i32;
362 }
363 minlen = min_length;
364 if l > 9usize {
365 minlen = max(minlen, l.wrapping_sub(9));
366 }
367 let maxlen: usize = min(matchlen, l.wrapping_sub(2));
368 for len in minlen..=maxlen {
369 AddMatch(
371 id.wrapping_add(
372 (kOmitLastNTransforms[l.wrapping_sub(len)] as usize).wrapping_mul(n),
373 ),
374 len,
375 l,
376 matches,
377 );
378 has_found_match = 1i32;
379 }
380
381 if matchlen < l || l.wrapping_add(6) >= max_length {
382 continue;
383 }
384 let s: &[u8] = data.split_at(l as usize).1;
385 if s[0] as i32 == b' ' as i32 {
386 AddMatch(id.wrapping_add(n), l.wrapping_add(1), l, matches);
388 if s[1] as i32 == b'a' as i32 {
389 if s[2] as i32 == b' ' as i32 {
390 AddMatch(
392 id.wrapping_add((28usize).wrapping_mul(n)),
393 l.wrapping_add(3),
394 l,
395 matches,
396 );
397 } else if s[2] as i32 == b's' as i32 {
398 if s[3] as i32 == b' ' as i32 {
399 AddMatch(
401 id.wrapping_add((46usize).wrapping_mul(n)),
402 l.wrapping_add(4),
403 l,
404 matches,
405 );
406 }
407 } else if s[2] as i32 == b't' as i32 {
408 if s[3] as i32 == b' ' as i32 {
409 AddMatch(
411 id.wrapping_add((60usize).wrapping_mul(n)),
412 l.wrapping_add(4),
413 l,
414 matches,
415 );
416 }
417 } else if s[2] as i32 == b'n' as i32
418 && s[3] as i32 == b'd' as i32
419 && (s[4] as i32 == b' ' as i32)
420 {
421 AddMatch(
423 id.wrapping_add((10usize).wrapping_mul(n)),
424 l.wrapping_add(5),
425 l,
426 matches,
427 );
428 }
429 } else if s[1] as i32 == b'b' as i32 {
430 if s[2] as i32 == b'y' as i32 && (s[3] as i32 == b' ' as i32) {
431 AddMatch(
433 id.wrapping_add((38usize).wrapping_mul(n)),
434 l.wrapping_add(4),
435 l,
436 matches,
437 );
438 }
439 } else if s[1] as i32 == b'i' as i32 {
440 if s[2] as i32 == b'n' as i32 {
441 if s[3] as i32 == b' ' as i32 {
442 AddMatch(
444 id.wrapping_add((16usize).wrapping_mul(n)),
445 l.wrapping_add(4),
446 l,
447 matches,
448 );
449 }
450 } else if s[2] as i32 == b's' as i32 && s[3] as i32 == b' ' as i32 {
451 AddMatch(
453 id.wrapping_add((47usize).wrapping_mul(n)),
454 l.wrapping_add(4),
455 l,
456 matches,
457 );
458 }
459 } else if s[1] as i32 == b'f' as i32 {
460 if s[2] as i32 == b'o' as i32 {
461 if s[3] as i32 == b'r' as i32 && (s[4] as i32 == b' ' as i32) {
462 AddMatch(
464 id.wrapping_add((25usize).wrapping_mul(n)),
465 l.wrapping_add(5),
466 l,
467 matches,
468 );
469 }
470 } else if s[2] as i32 == b'r' as i32
471 && s[3] as i32 == b'o' as i32
472 && (s[4] as i32 == b'm' as i32)
473 && (s[5] as i32 == b' ' as i32)
474 {
475 AddMatch(
477 id.wrapping_add((37usize).wrapping_mul(n)),
478 l.wrapping_add(6),
479 l,
480 matches,
481 );
482 }
483 } else if s[1] as i32 == b'o' as i32 {
484 if s[2] as i32 == b'f' as i32 {
485 if s[3] as i32 == b' ' as i32 {
486 AddMatch(
488 id.wrapping_add((8usize).wrapping_mul(n)),
489 l.wrapping_add(4),
490 l,
491 matches,
492 );
493 }
494 } else if s[2] as i32 == b'n' as i32 && s[3] as i32 == b' ' as i32 {
495 AddMatch(
497 id.wrapping_add((45usize).wrapping_mul(n)),
498 l.wrapping_add(4),
499 l,
500 matches,
501 );
502 }
503 } else if s[1] as i32 == b'n' as i32 {
504 if s[2] as i32 == b'o' as i32
505 && (s[3] as i32 == b't' as i32)
506 && (s[4] as i32 == b' ' as i32)
507 {
508 AddMatch(
510 id.wrapping_add((80usize).wrapping_mul(n)),
511 l.wrapping_add(5),
512 l,
513 matches,
514 );
515 }
516 } else if s[1] as i32 == b't' as i32 {
517 if s[2] as i32 == b'h' as i32 {
518 if s[3] as i32 == b'e' as i32 {
519 if s[4] as i32 == b' ' as i32 {
520 AddMatch(
522 id.wrapping_add((5usize).wrapping_mul(n)),
523 l.wrapping_add(5),
524 l,
525 matches,
526 );
527 }
528 } else if s[3] as i32 == b'a' as i32
529 && s[4] as i32 == b't' as i32
530 && (s[5] as i32 == b' ' as i32)
531 {
532 AddMatch(
534 id.wrapping_add((29usize).wrapping_mul(n)),
535 l.wrapping_add(6),
536 l,
537 matches,
538 );
539 }
540 } else if s[2] as i32 == b'o' as i32 && s[3] as i32 == b' ' as i32 {
541 AddMatch(
543 id.wrapping_add((17usize).wrapping_mul(n)),
544 l.wrapping_add(4),
545 l,
546 matches,
547 );
548 }
549 } else if s[1] as i32 == b'w' as i32
550 && s[2] as i32 == b'i' as i32
551 && (s[3] as i32 == b't' as i32)
552 && (s[4] as i32 == b'h' as i32)
553 && (s[5] as i32 == b' ' as i32)
554 {
555 AddMatch(
557 id.wrapping_add((35usize).wrapping_mul(n)),
558 l.wrapping_add(6),
559 l,
560 matches,
561 );
562 }
563 } else if s[0] as i32 == b'\"' as i32 {
564 AddMatch(
566 id.wrapping_add((19usize).wrapping_mul(n)),
567 l.wrapping_add(1),
568 l,
569 matches,
570 );
571 if s[1] as i32 == b'>' as i32 {
572 AddMatch(
574 id.wrapping_add((21usize).wrapping_mul(n)),
575 l.wrapping_add(2),
576 l,
577 matches,
578 );
579 }
580 } else if s[0] as i32 == b'.' as i32 {
581 AddMatch(
583 id.wrapping_add((20usize).wrapping_mul(n)),
584 l.wrapping_add(1),
585 l,
586 matches,
587 );
588 if s[1] as i32 == b' ' as i32 {
589 AddMatch(
591 id.wrapping_add((31usize).wrapping_mul(n)),
592 l.wrapping_add(2),
593 l,
594 matches,
595 );
596 if s[2] as i32 == b'T' as i32 && (s[3] as i32 == b'h' as i32) {
597 if s[4] as i32 == b'e' as i32 {
598 if s[5] as i32 == b' ' as i32 {
599 AddMatch(
601 id.wrapping_add((43usize).wrapping_mul(n)),
602 l.wrapping_add(6),
603 l,
604 matches,
605 );
606 }
607 } else if s[4] as i32 == b'i' as i32
608 && s[5] as i32 == b's' as i32
609 && (s[6] as i32 == b' ' as i32)
610 {
611 AddMatch(
613 id.wrapping_add((75usize).wrapping_mul(n)),
614 l.wrapping_add(7),
615 l,
616 matches,
617 );
618 }
619 }
620 }
621 } else if s[0] as i32 == b',' as i32 {
622 AddMatch(
624 id.wrapping_add((76usize).wrapping_mul(n)),
625 l.wrapping_add(1),
626 l,
627 matches,
628 );
629 if s[1] as i32 == b' ' as i32 {
630 AddMatch(
632 id.wrapping_add((14usize).wrapping_mul(n)),
633 l.wrapping_add(2),
634 l,
635 matches,
636 );
637 }
638 } else if s[0] as i32 == b'\n' as i32 {
639 AddMatch(
641 id.wrapping_add((22usize).wrapping_mul(n)),
642 l.wrapping_add(1),
643 l,
644 matches,
645 );
646 if s[1] as i32 == b'\t' as i32 {
647 AddMatch(
649 id.wrapping_add((50usize).wrapping_mul(n)),
650 l.wrapping_add(2),
651 l,
652 matches,
653 );
654 }
655 } else if s[0] as i32 == b']' as i32 {
656 AddMatch(
658 id.wrapping_add((24usize).wrapping_mul(n)),
659 l.wrapping_add(1),
660 l,
661 matches,
662 );
663 } else if s[0] as i32 == b'\'' as i32 {
664 AddMatch(
666 id.wrapping_add((36usize).wrapping_mul(n)),
667 l.wrapping_add(1),
668 l,
669 matches,
670 );
671 } else if s[0] as i32 == b':' as i32 {
672 AddMatch(
674 id.wrapping_add((51usize).wrapping_mul(n)),
675 l.wrapping_add(1),
676 l,
677 matches,
678 );
679 } else if s[0] as i32 == b'(' as i32 {
680 AddMatch(
682 id.wrapping_add((57usize).wrapping_mul(n)),
683 l.wrapping_add(1),
684 l,
685 matches,
686 );
687 } else if s[0] as i32 == b'=' as i32 {
688 if s[1] as i32 == b'\"' as i32 {
689 AddMatch(
691 id.wrapping_add((70usize).wrapping_mul(n)),
692 l.wrapping_add(2),
693 l,
694 matches,
695 );
696 } else if s[1] as i32 == b'\'' as i32 {
697 AddMatch(
699 id.wrapping_add((86usize).wrapping_mul(n)),
700 l.wrapping_add(2),
701 l,
702 matches,
703 );
704 }
705 } else if s[0] as i32 == b'a' as i32 {
706 if s[1] as i32 == b'l' as i32 && (s[2] as i32 == b' ' as i32) {
707 AddMatch(
709 id.wrapping_add((84usize).wrapping_mul(n)),
710 l.wrapping_add(3),
711 l,
712 matches,
713 );
714 }
715 } else if s[0] as i32 == b'e' as i32 {
716 if s[1] as i32 == b'd' as i32 {
717 if s[2] as i32 == b' ' as i32 {
718 AddMatch(
720 id.wrapping_add((53usize).wrapping_mul(n)),
721 l.wrapping_add(3),
722 l,
723 matches,
724 );
725 }
726 } else if s[1] as i32 == b'r' as i32 {
727 if s[2] as i32 == b' ' as i32 {
728 AddMatch(
730 id.wrapping_add((82usize).wrapping_mul(n)),
731 l.wrapping_add(3),
732 l,
733 matches,
734 );
735 }
736 } else if s[1] as i32 == b's' as i32
737 && s[2] as i32 == b't' as i32
738 && (s[3] as i32 == b' ' as i32)
739 {
740 AddMatch(
742 id.wrapping_add((95usize).wrapping_mul(n)),
743 l.wrapping_add(4),
744 l,
745 matches,
746 );
747 }
748 } else if s[0] as i32 == b'f' as i32 {
749 if s[1] as i32 == b'u' as i32
750 && (s[2] as i32 == b'l' as i32)
751 && (s[3] as i32 == b' ' as i32)
752 {
753 AddMatch(
755 id.wrapping_add((90usize).wrapping_mul(n)),
756 l.wrapping_add(4),
757 l,
758 matches,
759 );
760 }
761 } else if s[0] as i32 == b'i' as i32 {
762 if s[1] as i32 == b'v' as i32 {
763 if s[2] as i32 == b'e' as i32 && (s[3] as i32 == b' ' as i32) {
764 AddMatch(
766 id.wrapping_add((92usize).wrapping_mul(n)),
767 l.wrapping_add(4),
768 l,
769 matches,
770 );
771 }
772 } else if s[1] as i32 == b'z' as i32
773 && s[2] as i32 == b'e' as i32
774 && (s[3] as i32 == b' ' as i32)
775 {
776 AddMatch(
778 id.wrapping_add((100usize).wrapping_mul(n)),
779 l.wrapping_add(4),
780 l,
781 matches,
782 );
783 }
784 } else if s[0] as i32 == b'l' as i32 {
785 if s[1] as i32 == b'e' as i32 {
786 if s[2] as i32 == b's' as i32
787 && (s[3] as i32 == b's' as i32)
788 && (s[4] as i32 == b' ' as i32)
789 {
790 AddMatch(
792 id.wrapping_add((93usize).wrapping_mul(n)),
793 l.wrapping_add(5),
794 l,
795 matches,
796 );
797 }
798 } else if s[1] as i32 == b'y' as i32 && s[2] as i32 == b' ' as i32 {
799 AddMatch(
801 id.wrapping_add((61usize).wrapping_mul(n)),
802 l.wrapping_add(3),
803 l,
804 matches,
805 );
806 }
807 } else if s[0] as i32 == b'o' as i32
808 && s[1] as i32 == b'u' as i32
809 && (s[2] as i32 == b's' as i32)
810 && (s[3] as i32 == b' ' as i32)
811 {
812 AddMatch(
814 id.wrapping_add((106usize).wrapping_mul(n)),
815 l.wrapping_add(4),
816 l,
817 matches,
818 );
819 }
820 } else {
821 let is_all_caps = w.transform() != kUppercaseFirst;
822
823 if IsMatch(dictionary, w, data, max_length) == 0 {
824 continue;
825 }
826 AddMatch(
828 id.wrapping_add((if is_all_caps { 44usize } else { 9usize }).wrapping_mul(n)),
829 l,
830 l,
831 matches,
832 );
833 has_found_match = 1i32;
834 if l.wrapping_add(1) >= max_length {
835 continue;
836 }
837 let s: &[u8] = data.split_at(l as usize).1;
838 if s[0] as i32 == b' ' as i32 {
839 AddMatch(
841 id.wrapping_add(
842 (if is_all_caps { 68usize } else { 4usize }).wrapping_mul(n),
843 ),
844 l.wrapping_add(1),
845 l,
846 matches,
847 );
848 } else if s[0] as i32 == b'\"' as i32 {
849 AddMatch(
851 id.wrapping_add(
852 (if is_all_caps { 87usize } else { 66usize }).wrapping_mul(n),
853 ),
854 l.wrapping_add(1),
855 l,
856 matches,
857 );
858 if s[1] as i32 == b'>' as i32 {
859 AddMatch(
861 id.wrapping_add(
862 (if is_all_caps { 97usize } else { 69usize }).wrapping_mul(n),
863 ),
864 l.wrapping_add(2),
865 l,
866 matches,
867 );
868 }
869 } else if s[0] as i32 == b'.' as i32 {
870 AddMatch(
872 id.wrapping_add(
873 (if is_all_caps { 101usize } else { 79usize }).wrapping_mul(n),
874 ),
875 l.wrapping_add(1),
876 l,
877 matches,
878 );
879 if s[1] as i32 == b' ' as i32 {
880 AddMatch(
882 id.wrapping_add(
883 (if is_all_caps { 114usize } else { 88usize }).wrapping_mul(n),
884 ),
885 l.wrapping_add(2),
886 l,
887 matches,
888 );
889 }
890 } else if s[0] as i32 == b',' as i32 {
891 AddMatch(
893 id.wrapping_add(
894 (if is_all_caps { 112usize } else { 99usize }).wrapping_mul(n),
895 ),
896 l.wrapping_add(1),
897 l,
898 matches,
899 );
900 if s[1] as i32 == b' ' as i32 {
901 AddMatch(
903 id.wrapping_add(
904 (if is_all_caps { 107usize } else { 58usize }).wrapping_mul(n),
905 ),
906 l.wrapping_add(2),
907 l,
908 matches,
909 );
910 }
911 } else if s[0] as i32 == b'\'' as i32 {
912 AddMatch(
914 id.wrapping_add(
915 (if is_all_caps { 94usize } else { 74usize }).wrapping_mul(n),
916 ),
917 l.wrapping_add(1),
918 l,
919 matches,
920 );
921 } else if s[0] as i32 == b'(' as i32 {
922 AddMatch(
924 id.wrapping_add(
925 (if is_all_caps { 113usize } else { 78usize }).wrapping_mul(n),
926 ),
927 l.wrapping_add(1),
928 l,
929 matches,
930 );
931 } else if s[0] as i32 == b'=' as i32 {
932 if s[1] as i32 == b'\"' as i32 {
933 AddMatch(
935 id.wrapping_add(
936 (if is_all_caps { 105usize } else { 104usize }).wrapping_mul(n),
937 ),
938 l.wrapping_add(2),
939 l,
940 matches,
941 );
942 } else if s[1] as i32 == b'\'' as i32 {
943 AddMatch(
945 id.wrapping_add(
946 (if is_all_caps { 116usize } else { 108usize }).wrapping_mul(n),
947 ),
948 l.wrapping_add(2),
949 l,
950 matches,
951 );
952 }
953 }
954 }
955 }
956 }
957 if max_length >= 5usize && (data[0] as i32 == b' ' as i32 || data[0] as i32 == b'.' as i32) {
958 let is_space = data[0] == b' ';
959 let mut offset: usize =
960 kStaticDictionaryBuckets[Hash(data.split_at(1).1) as usize] as usize;
961 let mut end: i32 = (offset == 0) as i32;
962 while end == 0 {
963 let mut w: DictWord = kStaticDictionaryWords[offset];
964 offset = offset.wrapping_add(1);
965 let l: usize = (w.len() as i32 & 0x1fi32) as usize;
966 let n: usize = 1usize << dictionary.size_bits_by_length[l] as i32;
967 let id: usize = w.idx() as usize;
968 end = !(w.len() as i32 & 0x80i32 == 0) as i32;
969 w.l = l as u8;
970 if w.transform() as i32 == 0i32 {
971 if IsMatch(
972 dictionary,
973 w,
974 data.split_at(1).1,
975 max_length.wrapping_sub(1),
976 ) == 0
977 {
978 continue;
979 }
980 AddMatch(
982 id.wrapping_add((if is_space { 6usize } else { 32usize }).wrapping_mul(n)),
983 l.wrapping_add(1),
984 l,
985 matches,
986 );
987 has_found_match = 1i32;
988 if l.wrapping_add(2) >= max_length {
989 continue;
990 }
991 let s: &[u8] = data.split_at(l.wrapping_add(1) as usize).1;
992 if s[0] as i32 == b' ' as i32 {
993 AddMatch(
995 id.wrapping_add((if is_space { 2usize } else { 77usize }).wrapping_mul(n)),
996 l.wrapping_add(2),
997 l,
998 matches,
999 );
1000 } else if s[0] as i32 == b'(' as i32 {
1001 AddMatch(
1003 id.wrapping_add((if is_space { 89usize } else { 67usize }).wrapping_mul(n)),
1004 l.wrapping_add(2),
1005 l,
1006 matches,
1007 );
1008 } else if is_space {
1009 if s[0] as i32 == b',' as i32 {
1010 AddMatch(
1012 id.wrapping_add((103usize).wrapping_mul(n)),
1013 l.wrapping_add(2),
1014 l,
1015 matches,
1016 );
1017 if s[1] as i32 == b' ' as i32 {
1018 AddMatch(
1020 id.wrapping_add((33usize).wrapping_mul(n)),
1021 l.wrapping_add(3),
1022 l,
1023 matches,
1024 );
1025 }
1026 } else if s[0] as i32 == b'.' as i32 {
1027 AddMatch(
1029 id.wrapping_add((71usize).wrapping_mul(n)),
1030 l.wrapping_add(2),
1031 l,
1032 matches,
1033 );
1034 if s[1] as i32 == b' ' as i32 {
1035 AddMatch(
1037 id.wrapping_add((52usize).wrapping_mul(n)),
1038 l.wrapping_add(3),
1039 l,
1040 matches,
1041 );
1042 }
1043 } else if s[0] as i32 == b'=' as i32 {
1044 if s[1] as i32 == b'\"' as i32 {
1045 AddMatch(
1047 id.wrapping_add((81usize).wrapping_mul(n)),
1048 l.wrapping_add(3),
1049 l,
1050 matches,
1051 );
1052 } else if s[1] as i32 == b'\'' as i32 {
1053 AddMatch(
1055 id.wrapping_add((98usize).wrapping_mul(n)),
1056 l.wrapping_add(3),
1057 l,
1058 matches,
1059 );
1060 }
1061 }
1062 }
1063 } else if is_space {
1064 let is_all_caps = w.transform() != kUppercaseFirst;
1065
1066 if IsMatch(
1067 dictionary,
1068 w,
1069 data.split_at(1).1,
1070 max_length.wrapping_sub(1),
1071 ) == 0
1072 {
1073 continue;
1074 }
1075 AddMatch(
1077 id.wrapping_add((if is_all_caps { 85usize } else { 30usize }).wrapping_mul(n)),
1078 l.wrapping_add(1),
1079 l,
1080 matches,
1081 );
1082 has_found_match = 1i32;
1083 if l.wrapping_add(2) >= max_length {
1084 continue;
1085 }
1086 let s: &[u8] = data.split_at(l.wrapping_add(1)).1;
1087 if s[0] as i32 == b' ' as i32 {
1088 AddMatch(
1090 id.wrapping_add(
1091 (if is_all_caps { 83usize } else { 15usize }).wrapping_mul(n),
1092 ),
1093 l.wrapping_add(2),
1094 l,
1095 matches,
1096 );
1097 } else if s[0] as i32 == b',' as i32 {
1098 if !is_all_caps {
1099 AddMatch(
1101 id.wrapping_add((109usize).wrapping_mul(n)),
1102 l.wrapping_add(2),
1103 l,
1104 matches,
1105 );
1106 }
1107 if s[1] as i32 == b' ' as i32 {
1108 AddMatch(
1110 id.wrapping_add(
1111 (if is_all_caps { 111usize } else { 65usize }).wrapping_mul(n),
1112 ),
1113 l.wrapping_add(3),
1114 l,
1115 matches,
1116 );
1117 }
1118 } else if s[0] as i32 == b'.' as i32 {
1119 AddMatch(
1121 id.wrapping_add(
1122 (if is_all_caps { 115usize } else { 96usize }).wrapping_mul(n),
1123 ),
1124 l.wrapping_add(2),
1125 l,
1126 matches,
1127 );
1128 if s[1] as i32 == b' ' as i32 {
1129 AddMatch(
1131 id.wrapping_add(
1132 (if is_all_caps { 117usize } else { 91usize }).wrapping_mul(n),
1133 ),
1134 l.wrapping_add(3),
1135 l,
1136 matches,
1137 );
1138 }
1139 } else if s[0] as i32 == b'=' as i32 {
1140 if s[1] as i32 == b'\"' as i32 {
1141 AddMatch(
1143 id.wrapping_add(
1144 (if is_all_caps { 110usize } else { 118usize }).wrapping_mul(n),
1145 ),
1146 l.wrapping_add(3),
1147 l,
1148 matches,
1149 );
1150 } else if s[1] as i32 == b'\'' as i32 {
1151 AddMatch(
1153 id.wrapping_add(
1154 (if is_all_caps { 119usize } else { 120usize }).wrapping_mul(n),
1155 ),
1156 l.wrapping_add(3),
1157 l,
1158 matches,
1159 );
1160 }
1161 }
1162 }
1163 }
1164 }
1165 if max_length >= 6usize
1166 && (data[1] as i32 == b' ' as i32
1167 && (data[0] as i32 == b'e' as i32
1168 || data[0] as i32 == b's' as i32
1169 || data[0] as i32 == b',' as i32)
1170 || data[0] as i32 == 0xc2i32 && (data[1] as i32 == 0xa0i32))
1171 {
1172 let mut offset: usize =
1173 kStaticDictionaryBuckets[Hash(data.split_at(2).1) as usize] as usize;
1174 let mut end: i32 = (offset == 0) as i32;
1175 while end == 0 {
1176 let mut w: DictWord = kStaticDictionaryWords[offset];
1177 offset = offset.wrapping_add(1);
1178 let l: usize = (w.len() as i32 & 0x1fi32) as usize;
1179 let n: usize = 1usize << dictionary.size_bits_by_length[l] as i32;
1180 let id: usize = w.idx() as usize;
1181 end = !(w.len() as i32 & 0x80i32 == 0) as i32;
1182 w.l = l as u8;
1183 if w.transform() as i32 == 0i32
1184 && (IsMatch(
1185 dictionary,
1186 w,
1187 data.split_at(2).1,
1188 max_length.wrapping_sub(2),
1189 ) != 0)
1190 {
1191 if data[0] as i32 == 0xc2i32 {
1192 AddMatch(
1194 id.wrapping_add((102usize).wrapping_mul(n)),
1195 l.wrapping_add(2),
1196 l,
1197 matches,
1198 );
1199 has_found_match = 1i32;
1200 } else if l.wrapping_add(2) < max_length
1201 && (data[(l.wrapping_add(2) as usize)] as i32 == b' ' as i32)
1202 {
1203 let t: usize = (if data[0] as i32 == b'e' as i32 {
1204 18i32
1205 } else if data[0] as i32 == b's' as i32 {
1206 7i32
1207 } else {
1208 13i32
1209 }) as usize;
1210 AddMatch(
1212 id.wrapping_add(t.wrapping_mul(n)),
1213 l.wrapping_add(3),
1214 l,
1215 matches,
1216 );
1217 has_found_match = 1i32;
1218 }
1219 }
1220 }
1221 }
1222 if max_length >= 9usize
1223 && (data[0] as i32 == b' ' as i32
1224 && (data[1] as i32 == b't' as i32)
1225 && (data[2] as i32 == b'h' as i32)
1226 && (data[3] as i32 == b'e' as i32)
1227 && (data[4] as i32 == b' ' as i32)
1228 || data[0] as i32 == b'.' as i32
1229 && (data[1] as i32 == b'c' as i32)
1230 && (data[2] as i32 == b'o' as i32)
1231 && (data[3] as i32 == b'm' as i32)
1232 && (data[4] as i32 == b'/' as i32))
1233 {
1234 let mut offset: usize =
1235 kStaticDictionaryBuckets[Hash(data.split_at(5).1) as usize] as usize;
1236 let mut end: i32 = (offset == 0) as i32;
1237 while end == 0 {
1238 let mut w: DictWord = kStaticDictionaryWords[offset];
1239 offset = offset.wrapping_add(1);
1240 let l: usize = (w.len() as i32 & 0x1fi32) as usize;
1241 let n: usize = 1usize << dictionary.size_bits_by_length[l] as i32;
1242 let id: usize = w.idx() as usize;
1243 end = !(w.len() as i32 & 0x80i32 == 0) as i32;
1244 w.l = l as u8;
1245 if w.transform() as i32 == 0i32
1246 && (IsMatch(
1247 dictionary,
1248 w,
1249 data.split_at(5).1,
1250 max_length.wrapping_sub(5),
1251 ) != 0)
1252 {
1253 AddMatch(
1255 id.wrapping_add(
1256 (if data[0] as i32 == b' ' as i32 {
1257 41i32
1258 } else {
1259 72i32
1260 } as usize)
1261 .wrapping_mul(n),
1262 ),
1263 l.wrapping_add(5),
1264 l,
1265 matches,
1266 );
1267 has_found_match = 1i32;
1268 if l.wrapping_add(5) < max_length {
1269 let s: &[u8] = data.split_at(l.wrapping_add(5) as usize).1;
1270 if data[0] as i32 == b' ' as i32
1271 && l.wrapping_add(8) < max_length
1272 && (s[0] as i32 == b' ' as i32)
1273 && (s[1] as i32 == b'o' as i32)
1274 && (s[2] as i32 == b'f' as i32)
1275 && (s[3] as i32 == b' ' as i32)
1276 {
1277 AddMatch(
1279 id.wrapping_add((62usize).wrapping_mul(n)),
1280 l.wrapping_add(9),
1281 l,
1282 matches,
1283 );
1284 if l.wrapping_add(12) < max_length
1285 && (s[4] as i32 == b't' as i32)
1286 && (s[5] as i32 == b'h' as i32)
1287 && (s[6] as i32 == b'e' as i32)
1288 && (s[7] as i32 == b' ' as i32)
1289 {
1290 AddMatch(
1292 id.wrapping_add((73usize).wrapping_mul(n)),
1293 l.wrapping_add(13),
1294 l,
1295 matches,
1296 );
1297 }
1298 }
1299 }
1300 }
1301 }
1302 }
1303 has_found_match
1304}
1305
1306#[cfg(test)]
1307mod test {
1308 #[allow(unused)]
1309 fn construct_situation(seed: &[u8], mut output: &mut [u8], limit: usize, matchfor: usize) {
1310 output[..].clone_from_slice(seed);
1311 if matchfor >= limit {
1312 return;
1313 }
1314 output[matchfor] = output[matchfor].wrapping_add((matchfor as u8 % 253u8).wrapping_add(1));
1315 }
1316 #[test]
1317 fn test_find_match_length() {
1318 let mut a = [91u8; 600000];
1319 let mut b = [0u8; 600000];
1320 for i in 1..a.len() {
1321 a[i] = (a[i - 1] % 19u8).wrapping_add(17);
1322 }
1323 construct_situation(&a[..], &mut b[..], a.len(), 0);
1324 assert_eq!(super::FindMatchLengthWithLimit(&a[..], &b[..], a.len()), 0);
1325 construct_situation(&a[..], &mut b[..], a.len(), 1);
1326 assert_eq!(super::FindMatchLengthWithLimit(&a[..], &b[..], a.len()), 1);
1327 construct_situation(&a[..], &mut b[..], a.len(), 10);
1328 assert_eq!(super::FindMatchLengthWithLimit(&a[..], &b[..], a.len()), 10);
1329 construct_situation(&a[..], &mut b[..], a.len(), 9);
1330 assert_eq!(super::FindMatchLengthWithLimit(&a[..], &b[..], a.len()), 9);
1331 construct_situation(&a[..], &mut b[..], a.len(), 7);
1332 assert_eq!(super::FindMatchLengthWithLimit(&a[..], &b[..], a.len()), 7);
1333 construct_situation(&a[..], &mut b[..], a.len(), 8);
1334 assert_eq!(super::FindMatchLengthWithLimit(&a[..], &b[..], a.len()), 8);
1335 construct_situation(&a[..], &mut b[..], a.len(), 48);
1336 assert_eq!(super::FindMatchLengthWithLimit(&a[..], &b[..], a.len()), 48);
1337 construct_situation(&a[..], &mut b[..], a.len(), 49);
1338 assert_eq!(super::FindMatchLengthWithLimit(&a[..], &b[..], a.len()), 49);
1339 construct_situation(&a[..], &mut b[..], a.len(), 63);
1340 assert_eq!(super::FindMatchLengthWithLimit(&a[..], &b[..], a.len()), 63);
1341 construct_situation(&a[..], &mut b[..], a.len(), 222);
1342 assert_eq!(
1343 super::FindMatchLengthWithLimit(&a[..], &b[..], a.len()),
1344 222
1345 );
1346 construct_situation(&a[..], &mut b[..], a.len(), 1590);
1347 assert_eq!(
1348 super::FindMatchLengthWithLimit(&a[..], &b[..], a.len()),
1349 1590
1350 );
1351 construct_situation(&a[..], &mut b[..], a.len(), 12590);
1352 assert_eq!(
1353 super::FindMatchLengthWithLimit(&a[..], &b[..], a.len()),
1354 12590
1355 );
1356 construct_situation(&a[..], &mut b[..], a.len(), 52592);
1357 assert_eq!(
1358 super::FindMatchLengthWithLimit(&a[..], &b[..], a.len()),
1359 52592
1360 );
1361 construct_situation(&a[..], &mut b[..], a.len(), 152592);
1362 assert_eq!(
1363 super::FindMatchLengthWithLimit(&a[..], &b[..], a.len()),
1364 152592
1365 );
1366 construct_situation(&a[..], &mut b[..], a.len(), 252591);
1367 assert_eq!(
1368 super::FindMatchLengthWithLimit(&a[..], &b[..], a.len()),
1369 252591
1370 );
1371 construct_situation(&a[..], &mut b[..], a.len(), 131072);
1372 assert_eq!(
1373 super::FindMatchLengthWithLimit(&a[..], &b[..], a.len()),
1374 131072
1375 );
1376 construct_situation(&a[..], &mut b[..], a.len(), 131073);
1377 assert_eq!(
1378 super::FindMatchLengthWithLimit(&a[..], &b[..], a.len()),
1379 131073
1380 );
1381 construct_situation(&a[..], &mut b[..], a.len(), 131072 + 64 + 32 + 16 + 8);
1382 assert_eq!(
1383 super::FindMatchLengthWithLimit(&a[..], &b[..], a.len()),
1384 131072 + 64 + 32 + 16 + 8
1385 );
1386 construct_situation(&a[..], &mut b[..], a.len(), 272144 + 64 + 32 + 16 + 8 + 1);
1387 assert_eq!(
1388 super::FindMatchLengthWithLimit(&a[..], &b[..], a.len()),
1389 272144 + 64 + 32 + 16 + 8 + 1
1390 );
1391 construct_situation(&a[..], &mut b[..], a.len(), 2 * 272144 + 64 + 32 + 16 + 8);
1392 assert_eq!(
1393 super::FindMatchLengthWithLimit(&a[..], &b[..], a.len()),
1394 2 * 272144 + 64 + 32 + 16 + 8
1395 );
1396 construct_situation(&a[..], &mut b[..], a.len(), a.len());
1397 assert_eq!(
1398 super::FindMatchLengthWithLimit(&a[..], &b[..], a.len()),
1399 a.len()
1400 );
1401 }
1402}