1use super::{SliceSeekable, MAX_BLOCK_SIZE};
2use crate::{string_pattern::StringPattern, JSON_SPACE_BYTE};
3
4pub(super) struct PaddedBlock {
5 bytes: [u8; MAX_BLOCK_SIZE],
6 padding_len: usize,
7}
8
9pub struct EndPaddedInput<'a> {
10 middle: &'a [u8],
11 last_block: &'a PaddedBlock,
12}
13
14pub struct TwoSidesPaddedInput<'a> {
15 first_block: &'a PaddedBlock,
16 middle: &'a [u8],
17 last_block: &'a PaddedBlock,
18}
19
20impl PaddedBlock {
21 #[allow(clippy::unused_self)] pub(super) const fn len(&self) -> usize {
23 MAX_BLOCK_SIZE
24 }
25
26 pub(super) fn padding_len(&self) -> usize {
27 self.padding_len
28 }
29
30 pub(super) fn bytes(&self) -> &[u8] {
31 &self.bytes
32 }
33
34 pub(super) fn pad_first_block(bytes: &[u8]) -> Self {
35 assert!(bytes.len() <= MAX_BLOCK_SIZE);
36 let mut block_buf = [JSON_SPACE_BYTE; MAX_BLOCK_SIZE];
37 let block_start = MAX_BLOCK_SIZE - bytes.len();
38
39 block_buf[block_start..].copy_from_slice(bytes);
40
41 Self {
42 bytes: block_buf,
43 padding_len: block_start,
44 }
45 }
46
47 pub(super) fn pad_last_block(bytes: &[u8]) -> Self {
48 assert!(bytes.len() <= MAX_BLOCK_SIZE);
49 let mut last_block_buf = [JSON_SPACE_BYTE; MAX_BLOCK_SIZE];
50 let block_end = bytes.len();
51
52 last_block_buf[..block_end].copy_from_slice(bytes);
53
54 Self {
55 bytes: last_block_buf,
56 padding_len: MAX_BLOCK_SIZE - block_end,
57 }
58 }
59}
60
61impl SliceSeekable for EndPaddedInput<'_> {
62 #[cold]
63 #[inline(never)]
64 fn seek_backward(&self, from: usize, needle: u8) -> Option<usize> {
65 if from < self.middle.len() {
66 self.seek_backward_from_middle(from, needle)
67 } else {
68 self.seek_backward_from_last(from, needle)
69 }
70 }
71
72 #[cold]
73 #[inline(never)]
74 fn seek_forward<const N: usize>(&self, from: usize, needles: [u8; N]) -> Option<(usize, u8)> {
75 if from < self.middle.len() {
76 self.seek_forward_from_middle(from, needles)
77 } else {
78 self.seek_forward_from_last(from, needles)
79 }
80 }
81
82 #[cold]
83 #[inline(never)]
84 fn seek_non_whitespace_forward(&self, from: usize) -> Option<(usize, u8)> {
85 if from < self.middle.len() {
86 self.seek_non_whitespace_forward_from_middle(from)
87 } else {
88 self.seek_non_whitespace_forward_from_last(from)
89 }
90 }
91
92 #[cold]
93 #[inline(never)]
94 fn seek_non_whitespace_backward(&self, from: usize) -> Option<(usize, u8)> {
95 if from < self.middle.len() {
96 self.seek_non_whitespace_backward_from_middle(from)
97 } else {
98 self.seek_non_whitespace_backward_from_last(from)
99 }
100 }
101
102 #[cold]
103 #[inline(never)]
104 fn is_member_match(&self, from: usize, to: usize, member: &StringPattern) -> bool {
105 debug_assert!(from < to);
106 let other = member.quoted();
107 self.cold_member_match(other, from, to)
108 }
109}
110
111impl SliceSeekable for TwoSidesPaddedInput<'_> {
112 #[cold]
113 #[inline(never)]
114 fn seek_backward(&self, from: usize, needle: u8) -> Option<usize> {
115 if from < MAX_BLOCK_SIZE {
116 self.seek_backward_from_first(from, needle)
117 } else if from < self.middle.len() + MAX_BLOCK_SIZE {
118 self.seek_backward_from_middle(from, needle)
119 } else {
120 self.seek_backward_from_last(from, needle)
121 }
122 }
123
124 #[cold]
125 #[inline(never)]
126 fn seek_forward<const N: usize>(&self, from: usize, needles: [u8; N]) -> Option<(usize, u8)> {
127 if from < MAX_BLOCK_SIZE {
128 self.seek_forward_from_first(from, needles)
129 } else if from < self.middle.len() + MAX_BLOCK_SIZE {
130 self.seek_forward_from_middle(from, needles)
131 } else {
132 self.seek_forward_from_last(from, needles)
133 }
134 }
135
136 #[cold]
137 #[inline(never)]
138 fn seek_non_whitespace_forward(&self, from: usize) -> Option<(usize, u8)> {
139 if from < MAX_BLOCK_SIZE {
140 self.seek_non_whitespace_forward_from_first(from)
141 } else if from < self.middle.len() + MAX_BLOCK_SIZE {
142 self.seek_non_whitespace_forward_from_middle(from)
143 } else {
144 self.seek_non_whitespace_forward_from_last(from)
145 }
146 }
147
148 #[cold]
149 #[inline(never)]
150 fn seek_non_whitespace_backward(&self, from: usize) -> Option<(usize, u8)> {
151 if from < MAX_BLOCK_SIZE {
152 self.seek_non_whitespace_backward_from_first(from)
153 } else if from < self.middle.len() + MAX_BLOCK_SIZE {
154 self.seek_non_whitespace_backward_from_middle(from)
155 } else {
156 self.seek_non_whitespace_backward_from_last(from)
157 }
158 }
159
160 #[cold]
161 #[inline(never)]
162 fn is_member_match(&self, from: usize, to: usize, member: &StringPattern) -> bool {
163 debug_assert!(from < to);
164 let other = member.quoted();
165 self.cold_member_match(other, from, to)
166 }
167}
168
169impl<'a> EndPaddedInput<'a> {
170 pub(super) fn new(middle: &'a [u8], last: &'a PaddedBlock) -> Self {
171 Self {
172 middle,
173 last_block: last,
174 }
175 }
176
177 #[inline(always)]
178 pub(super) fn middle(&self) -> &'a [u8] {
179 self.middle
180 }
181
182 fn seek_backward_from_middle(&self, from: usize, needle: u8) -> Option<usize> {
183 debug_assert!(from < self.middle.len());
184 let bytes = self.middle;
185
186 seek_backward_impl(bytes, from, needle)
187 }
188
189 fn seek_backward_from_last(&self, from: usize, needle: u8) -> Option<usize> {
190 debug_assert!(from >= self.middle.len());
191 let bytes = &self.last_block.bytes;
192
193 seek_backward_impl(bytes, from - self.middle.len(), needle)
194 .map(|x| x + self.middle.len())
195 .or_else(|| self.seek_backward_from_middle(self.middle.len() - 1, needle))
196 }
197
198 fn seek_forward_from_middle<const N: usize>(&self, from: usize, needles: [u8; N]) -> Option<(usize, u8)> {
199 assert!(N > 0);
200 debug_assert!(from < self.middle.len());
201 let bytes = self.middle;
202
203 seek_forward_impl(bytes, from, needles).or_else(|| self.seek_forward_from_last(bytes.len(), needles))
204 }
205
206 fn seek_forward_from_last<const N: usize>(&self, from: usize, needles: [u8; N]) -> Option<(usize, u8)> {
207 assert!(N > 0);
208 debug_assert!(from >= self.middle.len());
209 let bytes = &self.last_block.bytes;
210
211 seek_forward_impl(bytes, from - self.middle.len(), needles).map(|(x, y)| (x + self.middle.len(), y))
212 }
213
214 fn seek_non_whitespace_forward_from_middle(&self, from: usize) -> Option<(usize, u8)> {
215 debug_assert!(from < self.middle.len());
216 let bytes = self.middle;
217
218 seek_non_whitespace_forward_impl(bytes, from)
219 .or_else(|| self.seek_non_whitespace_forward_from_last(bytes.len()))
220 }
221
222 fn seek_non_whitespace_forward_from_last(&self, from: usize) -> Option<(usize, u8)> {
223 debug_assert!(from >= self.middle.len());
224 let bytes = &self.last_block.bytes;
225
226 seek_non_whitespace_forward_impl(bytes, from - self.middle.len()).map(|(x, y)| (x + self.middle.len(), y))
227 }
228
229 fn seek_non_whitespace_backward_from_middle(&self, from: usize) -> Option<(usize, u8)> {
230 debug_assert!(from < self.middle.len());
231 let bytes = self.middle;
232
233 seek_non_whitespace_backward_impl(bytes, from)
234 }
235
236 fn seek_non_whitespace_backward_from_last(&self, from: usize) -> Option<(usize, u8)> {
237 debug_assert!(from >= self.middle.len());
238 let bytes = &self.last_block.bytes;
239
240 seek_non_whitespace_backward_impl(bytes, from - self.middle.len())
241 .map(|(x, y)| (x + self.middle.len(), y))
242 .or_else(|| self.seek_non_whitespace_backward_from_middle(self.middle.len() - 1))
243 }
244
245 pub(super) fn try_slice(&self, start: usize, len: usize) -> Option<&'a [u8]> {
246 debug_assert!(len < MAX_BLOCK_SIZE);
247
248 if start < self.middle.len() {
249 self.slice_middle(start, len)
250 } else {
251 self.slice_last(start, len)
252 }
253 }
254
255 fn slice_middle(&self, start: usize, len: usize) -> Option<&'a [u8]> {
256 Some(&self.middle[start..start + len])
257 }
258
259 fn slice_last(&self, start: usize, len: usize) -> Option<&'a [u8]> {
260 let start = start - self.middle.len();
261 (start < MAX_BLOCK_SIZE).then(|| &self.last_block.bytes[start..start + len])
262 }
263
264 fn slice_parts(&self, from: usize, to: usize) -> (&[u8], &[u8]) {
268 use std::cmp::min;
269
270 let middle_from = min(from, self.middle.len());
271 let middle_to = min(to, self.middle.len());
272
273 let from = from.saturating_sub(self.middle.len());
274 let to = to.saturating_sub(self.middle.len());
275 let last_from = min(from, self.last_block.len());
276 let last_to = min(to, self.last_block.len());
277
278 (
279 &self.middle[middle_from..middle_to],
280 &self.last_block.bytes[last_from..last_to],
281 )
282 }
283
284 fn get_at(&self, idx: usize) -> Option<u8> {
285 if idx < self.middle.len() {
286 Some(self.middle[idx])
287 } else if idx < self.middle.len() + MAX_BLOCK_SIZE {
288 Some(self.last_block.bytes[idx - self.middle.len()])
289 } else {
290 None
291 }
292 }
293
294 fn cold_member_match(&self, other: &[u8], from: usize, to: usize) -> bool {
295 let (middle_self, last_self) = self.slice_parts(from, to);
296 let middle_other = &other[..middle_self.len()];
297 let last_other = &other[middle_self.len()..];
298 let preceding_char = from.checked_sub(1).and_then(|x| self.get_at(x));
299
300 middle_self == middle_other && last_self == last_other && preceding_char != Some(b'\\')
301 }
302}
303
304impl<'a> TwoSidesPaddedInput<'a> {
305 pub(super) fn new(first: &'a PaddedBlock, middle: &'a [u8], last: &'a PaddedBlock) -> Self {
306 Self {
307 first_block: first,
308 middle,
309 last_block: last,
310 }
311 }
312
313 #[inline(always)]
314 pub(super) fn middle(&self) -> &'a [u8] {
315 self.middle
316 }
317
318 fn seek_backward_from_first(&self, from: usize, needle: u8) -> Option<usize> {
319 debug_assert!(from < MAX_BLOCK_SIZE);
320 let bytes = &self.first_block.bytes;
321
322 seek_backward_impl(bytes, from, needle)
323 }
324
325 fn seek_backward_from_middle(&self, from: usize, needle: u8) -> Option<usize> {
326 debug_assert!(from >= MAX_BLOCK_SIZE);
327 let bytes = self.middle;
328
329 seek_backward_impl(bytes, from - MAX_BLOCK_SIZE, needle)
330 .map(|x| x + MAX_BLOCK_SIZE)
331 .or_else(|| self.seek_backward_from_first(MAX_BLOCK_SIZE - 1, needle))
332 }
333
334 fn seek_backward_from_last(&self, from: usize, needle: u8) -> Option<usize> {
335 debug_assert!(from >= self.middle.len() + MAX_BLOCK_SIZE);
336 let bytes = &self.last_block.bytes;
337
338 seek_backward_impl(bytes, from - self.middle.len() - MAX_BLOCK_SIZE, needle)
339 .map(|x| x + self.middle.len() + MAX_BLOCK_SIZE)
340 .or_else(|| {
341 if self.middle.is_empty() {
342 self.seek_backward_from_first(MAX_BLOCK_SIZE - 1, needle)
343 } else {
344 self.seek_backward_from_middle(self.middle.len() + MAX_BLOCK_SIZE - 1, needle)
345 }
346 })
347 }
348
349 fn seek_forward_from_first<const N: usize>(&self, from: usize, needles: [u8; N]) -> Option<(usize, u8)> {
350 assert!(N > 0);
351 debug_assert!(from < MAX_BLOCK_SIZE);
352 let bytes = &self.first_block.bytes;
353
354 seek_forward_impl(bytes, from, needles).or_else(|| {
355 if self.middle.is_empty() {
356 self.seek_forward_from_last(bytes.len(), needles)
357 } else {
358 self.seek_forward_from_middle(bytes.len(), needles)
359 }
360 })
361 }
362
363 fn seek_forward_from_middle<const N: usize>(&self, from: usize, needles: [u8; N]) -> Option<(usize, u8)> {
364 assert!(N > 0);
365 debug_assert!(from >= MAX_BLOCK_SIZE);
366 let bytes = self.middle;
367
368 seek_forward_impl(bytes, from - MAX_BLOCK_SIZE, needles)
369 .map(|(x, y)| (x + MAX_BLOCK_SIZE, y))
370 .or_else(|| self.seek_forward_from_last(bytes.len() + MAX_BLOCK_SIZE, needles))
371 }
372
373 fn seek_forward_from_last<const N: usize>(&self, from: usize, needles: [u8; N]) -> Option<(usize, u8)> {
374 assert!(N > 0);
375 debug_assert!(from >= self.middle.len() + MAX_BLOCK_SIZE);
376 let bytes = &self.last_block.bytes;
377
378 seek_forward_impl(bytes, from - self.middle.len() - MAX_BLOCK_SIZE, needles)
379 .map(|(x, y)| (x + self.middle.len() + MAX_BLOCK_SIZE, y))
380 }
381
382 fn seek_non_whitespace_forward_from_first(&self, from: usize) -> Option<(usize, u8)> {
383 debug_assert!(from < MAX_BLOCK_SIZE);
384 let bytes = &self.first_block.bytes;
385
386 seek_non_whitespace_forward_impl(bytes, from).or_else(|| {
387 if self.middle.is_empty() {
388 self.seek_non_whitespace_forward_from_last(bytes.len())
389 } else {
390 self.seek_non_whitespace_forward_from_middle(bytes.len())
391 }
392 })
393 }
394
395 fn seek_non_whitespace_forward_from_middle(&self, from: usize) -> Option<(usize, u8)> {
396 debug_assert!(from >= MAX_BLOCK_SIZE);
397 let bytes = self.middle;
398
399 seek_non_whitespace_forward_impl(bytes, from - MAX_BLOCK_SIZE)
400 .map(|(x, y)| (x + MAX_BLOCK_SIZE, y))
401 .or_else(|| self.seek_non_whitespace_forward_from_last(bytes.len() + MAX_BLOCK_SIZE))
402 }
403
404 fn seek_non_whitespace_forward_from_last(&self, from: usize) -> Option<(usize, u8)> {
405 debug_assert!(from >= self.middle.len() + MAX_BLOCK_SIZE);
406 let bytes = &self.last_block.bytes;
407
408 seek_non_whitespace_forward_impl(bytes, from - self.middle.len() - MAX_BLOCK_SIZE)
409 .map(|(x, y)| (x + self.middle.len() + MAX_BLOCK_SIZE, y))
410 }
411
412 fn seek_non_whitespace_backward_from_first(&self, from: usize) -> Option<(usize, u8)> {
413 debug_assert!(from < MAX_BLOCK_SIZE);
414 let bytes = &self.first_block.bytes;
415
416 seek_non_whitespace_backward_impl(bytes, from)
417 }
418
419 fn seek_non_whitespace_backward_from_middle(&self, from: usize) -> Option<(usize, u8)> {
420 debug_assert!(from >= MAX_BLOCK_SIZE);
421 let bytes = self.middle;
422
423 seek_non_whitespace_backward_impl(bytes, from - MAX_BLOCK_SIZE)
424 .map(|(x, y)| (x + MAX_BLOCK_SIZE, y))
425 .or_else(|| self.seek_non_whitespace_backward_from_first(MAX_BLOCK_SIZE - 1))
426 }
427
428 fn seek_non_whitespace_backward_from_last(&self, from: usize) -> Option<(usize, u8)> {
429 debug_assert!(from >= self.middle.len() + MAX_BLOCK_SIZE);
430 let bytes = &self.last_block.bytes;
431
432 seek_non_whitespace_backward_impl(bytes, from - self.middle.len() - MAX_BLOCK_SIZE)
433 .map(|(x, y)| (x + self.middle.len() + MAX_BLOCK_SIZE, y))
434 .or_else(|| {
435 if self.middle.is_empty() {
436 self.seek_non_whitespace_backward_from_first(MAX_BLOCK_SIZE - 1)
437 } else {
438 self.seek_non_whitespace_backward_from_middle(self.middle.len() + MAX_BLOCK_SIZE - 1)
439 }
440 })
441 }
442
443 pub(super) fn try_slice(&self, start: usize, len: usize) -> Option<&'a [u8]> {
444 debug_assert!(len < MAX_BLOCK_SIZE);
445
446 if start < MAX_BLOCK_SIZE {
447 Some(self.slice_first(start, len))
448 } else if start < self.middle.len() + MAX_BLOCK_SIZE {
449 Some(self.slice_middle(start, len))
450 } else {
451 self.slice_last(start, len)
452 }
453 }
454
455 fn slice_first(&self, start: usize, len: usize) -> &'a [u8] {
456 &self.first_block.bytes[start..start + len]
457 }
458
459 fn slice_middle(&self, start: usize, len: usize) -> &'a [u8] {
460 let start = start - MAX_BLOCK_SIZE;
461 &self.middle[start..start + len]
462 }
463
464 fn slice_last(&self, start: usize, len: usize) -> Option<&'a [u8]> {
465 let start = start - self.middle.len() - MAX_BLOCK_SIZE;
466 (start < MAX_BLOCK_SIZE).then(|| &self.last_block.bytes[start..start + len])
467 }
468
469 fn slice_parts(&self, from: usize, to: usize) -> (&[u8], &[u8], &[u8]) {
473 use std::cmp::min;
474
475 let first_from = min(from, MAX_BLOCK_SIZE);
476 let first_to = min(to, MAX_BLOCK_SIZE);
477
478 let from = from.saturating_sub(MAX_BLOCK_SIZE);
479 let to = to.saturating_sub(MAX_BLOCK_SIZE);
480 let middle_from = min(from, self.middle.len());
481 let middle_to = min(to, self.middle.len());
482
483 let from = from.saturating_sub(self.middle.len());
484 let to = to.saturating_sub(self.middle.len());
485 let last_from = min(from, self.last_block.len());
486 let last_to = min(to, self.last_block.len());
487
488 (
489 &self.first_block.bytes[first_from..first_to],
490 &self.middle[middle_from..middle_to],
491 &self.last_block.bytes[last_from..last_to],
492 )
493 }
494
495 fn get_at(&self, idx: usize) -> Option<u8> {
496 if idx < MAX_BLOCK_SIZE {
497 Some(self.first_block.bytes[idx])
498 } else if idx < self.middle.len() + MAX_BLOCK_SIZE {
499 Some(self.middle[idx - MAX_BLOCK_SIZE])
500 } else if idx < self.middle.len() + 2 * MAX_BLOCK_SIZE {
501 Some(self.last_block.bytes[idx - MAX_BLOCK_SIZE - self.middle.len()])
502 } else {
503 None
504 }
505 }
506
507 fn cold_member_match(&self, other: &[u8], from: usize, to: usize) -> bool {
508 let (first_self, middle_self, last_self) = self.slice_parts(from, to);
509 let first_other = &other[..first_self.len()];
510 let middle_other = &other[first_self.len()..first_self.len() + middle_self.len()];
511 let last_other = &other[first_self.len() + middle_self.len()..];
512 let preceding_char = from.checked_sub(1).and_then(|x| self.get_at(x));
513
514 first_self == first_other
515 && middle_self == middle_other
516 && last_self == last_other
517 && preceding_char != Some(b'\\')
518 }
519}
520
521#[inline(always)]
522fn seek_backward_impl(bytes: &[u8], from: usize, needle: u8) -> Option<usize> {
523 let mut idx = from;
524 assert!(idx < bytes.len());
525
526 loop {
527 if bytes[idx] == needle {
528 return Some(idx);
529 }
530 if idx == 0 {
531 return None;
532 }
533 idx -= 1;
534 }
535}
536
537#[inline(always)]
538fn seek_forward_impl<const N: usize>(bytes: &[u8], from: usize, needles: [u8; N]) -> Option<(usize, u8)> {
539 let mut idx = from;
540 if idx >= bytes.len() {
541 return None;
542 }
543
544 loop {
545 let b = bytes[idx];
546 if needles.contains(&b) {
547 return Some((idx, b));
548 }
549 idx += 1;
550 if idx == bytes.len() {
551 return None;
552 }
553 }
554}
555
556#[inline(always)]
557fn seek_non_whitespace_forward_impl(bytes: &[u8], from: usize) -> Option<(usize, u8)> {
558 let mut idx = from;
559 if idx >= bytes.len() {
560 return None;
561 }
562
563 loop {
564 let b = bytes[idx];
565 if !b.is_ascii_whitespace() {
566 return Some((idx, b));
567 }
568 idx += 1;
569 if idx == bytes.len() {
570 return None;
571 }
572 }
573}
574
575#[inline(always)]
576fn seek_non_whitespace_backward_impl(bytes: &[u8], from: usize) -> Option<(usize, u8)> {
577 let mut idx = from;
578 if idx >= bytes.len() {
579 return None;
580 }
581
582 loop {
583 let b = bytes[idx];
584 if !b.is_ascii_whitespace() {
585 return Some((idx, b));
586 }
587 if idx == 0 {
588 return None;
589 }
590 idx -= 1;
591 }
592}
593
594#[cfg(test)]
595mod test {
596 use super::*;
597 use pretty_assertions::assert_eq;
598
599 #[test]
600 fn on_empty_bytes_is_all_whitespace() {
601 let result = PaddedBlock::pad_last_block(&[]);
602
603 assert_eq!(result.bytes, [JSON_SPACE_BYTE; MAX_BLOCK_SIZE]);
604 }
605
606 #[test]
607 fn on_bytes_smaller_than_full_block_gives_entire_block() {
608 let bytes = r#"{"test":42}"#.as_bytes();
609
610 let result = PaddedBlock::pad_last_block(bytes);
611
612 assert_eq!(&result.bytes[0..11], bytes);
613 assert_eq!(&result.bytes[11..], [JSON_SPACE_BYTE; MAX_BLOCK_SIZE - 11]);
614 }
615
616 #[test]
617 fn on_bytes_equal_to_full_block_does_not_change_block() {
618 let bytes = [42; MAX_BLOCK_SIZE];
619
620 let result = PaddedBlock::pad_last_block(&bytes);
621
622 assert_eq!(result.bytes, bytes);
623 }
624
625 mod two_sided_padded_input {
626 mod seek_forward_1 {
627 use crate::input::{
628 padding::{PaddedBlock, TwoSidesPaddedInput},
629 SliceSeekable,
630 };
631 use pretty_assertions::assert_eq;
632 use std::iter;
633
634 #[test]
635 fn in_empty_slice_returns_none() {
636 let input = TwoSidesPaddedInput {
637 first_block: &PaddedBlock::pad_first_block(&[]),
638 middle: &[],
639 last_block: &PaddedBlock::pad_last_block(&[]),
640 };
641
642 let result = input.seek_forward(0, [0]);
643
644 assert_eq!(result, None);
645 }
646
647 #[test]
648 fn seeking_from_first_block_from_needle_returns_that() {
649 let input = TwoSidesPaddedInput {
650 first_block: &PaddedBlock::pad_first_block(r#"{"seek": 42}"#.as_bytes()),
651 middle: &[],
652 last_block: &PaddedBlock::pad_last_block(&[]),
653 };
654
655 let result = input.seek_forward(123, [b':']);
656
657 assert_eq!(result, Some((123, b':')));
658 }
659
660 #[test]
661 fn seeking_from_middle_block_from_needle_returns_that() {
662 let input = TwoSidesPaddedInput {
663 first_block: &PaddedBlock::pad_first_block(&[]),
664 middle: r#"{"seek": 42}"#.as_bytes(),
665 last_block: &PaddedBlock::pad_last_block(&[]),
666 };
667
668 let result = input.seek_forward(128 + 7, [b':']);
669
670 assert_eq!(result, Some((128 + 7, b':')));
671 }
672
673 #[test]
674 fn seeking_from_last_block_from_needle_returns_that() {
675 let input = TwoSidesPaddedInput {
676 first_block: &PaddedBlock::pad_first_block(&[]),
677 middle: &iter::repeat(b' ').take(256).collect::<Vec<_>>(),
678 last_block: &PaddedBlock::pad_last_block(r#"{"seek": 42}"#.as_bytes()),
679 };
680
681 let result = input.seek_forward(128 + 256 + 7, [b':']);
682
683 assert_eq!(result, Some((128 + 256 + 7, b':')));
684 }
685
686 #[test]
687 fn seeking_from_first_block_from_not_needle_returns_next_needle() {
688 let input = TwoSidesPaddedInput {
689 first_block: &PaddedBlock::pad_first_block(r"seek: \t\n42}".as_bytes()),
690 middle: &[],
691 last_block: &PaddedBlock::pad_last_block(&[]),
692 };
693
694 let result = input.seek_forward(119, [b'2']);
695
696 assert_eq!(result, Some((126, b'2')));
697 }
698
699 #[test]
700 fn seeking_from_middle_block_from_not_needle_returns_next_needle() {
701 let input = TwoSidesPaddedInput {
702 first_block: &PaddedBlock::pad_first_block(&[]),
703 middle: r"seek: \t\n42}".as_bytes(),
704 last_block: &PaddedBlock::pad_last_block(&[]),
705 };
706
707 let result = input.seek_forward(128 + 5, [b'2']);
708
709 assert_eq!(result, Some((128 + 11, b'2')));
710 }
711
712 #[test]
713 fn seeking_from_last_block_from_not_needle_returns_next_needle() {
714 let input = TwoSidesPaddedInput {
715 first_block: &PaddedBlock::pad_first_block(&[]),
716 middle: &iter::repeat(b' ').take(256).collect::<Vec<_>>(),
717 last_block: &PaddedBlock::pad_last_block(r"seek: \t\n42}".as_bytes()),
718 };
719
720 let result = input.seek_forward(128 + 256 + 5, [b'2']);
721
722 assert_eq!(result, Some((128 + 256 + 11, b'2')));
723 }
724
725 #[test]
726 fn seeking_from_first_block_from_not_needle_when_there_is_no_needle_returns_none() {
727 let bytes = "seek: \t\n42}".as_bytes();
728
729 let result = bytes.seek_forward(5, [b'3']);
730
731 assert_eq!(result, None);
732 }
733 }
734
735 mod seek_forward_2 {
736 use crate::input::{
737 padding::{PaddedBlock, TwoSidesPaddedInput},
738 SliceSeekable,
739 };
740 use pretty_assertions::assert_eq;
741
742 #[test]
743 fn in_empty_input_returns_none() {
744 let input = TwoSidesPaddedInput {
745 first_block: &PaddedBlock::pad_first_block(&[]),
746 middle: &[],
747 last_block: &PaddedBlock::pad_last_block(&[]),
748 };
749
750 let result = input.seek_forward(0, [0, 1]);
751
752 assert_eq!(result, None);
753 }
754
755 #[test]
756 fn seeking_from_needle_1_returns_that() {
757 let bytes = r#"{"seek": 42}"#.as_bytes();
758
759 let result = bytes.seek_forward(7, [b':', b'4']);
760
761 assert_eq!(result, Some((7, b':')));
762 }
763
764 #[test]
765 fn seeking_from_needle_2_returns_that() {
766 let bytes = r#"{"seek": 42}"#.as_bytes();
767
768 let result = bytes.seek_forward(7, [b'4', b':']);
769
770 assert_eq!(result, Some((7, b':')));
771 }
772
773 #[test]
774 fn seeking_from_not_needle_when_next_is_needle_1_returns_that() {
775 let bytes = "seek: \t\n42}".as_bytes();
776
777 let result = bytes.seek_forward(5, [b'4', b'2']);
778
779 assert_eq!(result, Some((8, b'4')));
780 }
781
782 #[test]
783 fn seeking_from_not_needle_when_next_is_needle_2_returns_that() {
784 let bytes = "seek: \t\n42}".as_bytes();
785
786 let result = bytes.seek_forward(5, [b'2', b'4']);
787
788 assert_eq!(result, Some((8, b'4')));
789 }
790
791 #[test]
792 fn seeking_from_not_needle_when_there_is_no_needle_returns_none() {
793 let bytes = "seek: \t\n42}".as_bytes();
794
795 let result = bytes.seek_forward(5, [b'3', b'0']);
796
797 assert_eq!(result, None);
798 }
799 }
800
801 mod seek_backward {
802 use crate::input::{
803 padding::{PaddedBlock, TwoSidesPaddedInput},
804 SliceSeekable,
805 };
806 use pretty_assertions::assert_eq;
807
808 #[test]
809 fn in_empty_slice_returns_none() {
810 let input = TwoSidesPaddedInput {
811 first_block: &PaddedBlock::pad_first_block(&[]),
812 middle: &[],
813 last_block: &PaddedBlock::pad_last_block(&[]),
814 };
815
816 let result = input.seek_non_whitespace_forward(0);
817
818 assert_eq!(result, None);
819 }
820
821 #[test]
822 fn seeking_from_needle_returns_that() {
823 let input = TwoSidesPaddedInput {
824 first_block: &PaddedBlock::pad_first_block(&[]),
825 middle: r#"{"seek": 42}"#.as_bytes(),
826 last_block: &PaddedBlock::pad_last_block(&[]),
827 };
828
829 let result = input.seek_backward(136, b':');
830
831 assert_eq!(result, Some(135));
832 }
833
834 #[test]
835 fn seeking_from_not_needle_when_previous_is_needle_returns_that() {
836 let input = TwoSidesPaddedInput {
837 first_block: &PaddedBlock::pad_first_block(&[]),
838 middle: "seek: \t\n42}".as_bytes(),
839 last_block: &PaddedBlock::pad_last_block(&[]),
840 };
841
842 let result = input.seek_backward(137, b'4');
843
844 assert_eq!(result, Some(136));
845 }
846
847 #[test]
848 fn seeking_from_not_needle_when_there_is_no_needle_returns_none() {
849 let input = TwoSidesPaddedInput {
850 first_block: &PaddedBlock::pad_first_block(&[]),
851 middle: "seek: \t\n42}".as_bytes(),
852 last_block: &PaddedBlock::pad_last_block(&[]),
853 };
854
855 let result = input.seek_backward(138, b'3');
856
857 assert_eq!(result, None);
858 }
859 }
860
861 mod seek_non_whitespace_forward {
862 use crate::input::{
863 padding::{PaddedBlock, TwoSidesPaddedInput},
864 SliceSeekable,
865 };
866 use pretty_assertions::assert_eq;
867 use std::iter;
868
869 #[test]
870 fn in_empty_slice_returns_none() {
871 let input = TwoSidesPaddedInput {
872 first_block: &PaddedBlock::pad_first_block(&[]),
873 middle: &[],
874 last_block: &PaddedBlock::pad_last_block(&[]),
875 };
876
877 let result = input.seek_non_whitespace_forward(0);
878
879 assert_eq!(result, None);
880 }
881
882 #[test]
883 fn seeking_from_first_block_from_non_whitespace_returns_that() {
884 let input = TwoSidesPaddedInput {
885 first_block: &PaddedBlock::pad_first_block(r#"{"seek": 42}"#.as_bytes()),
886 middle: &[],
887 last_block: &PaddedBlock::pad_last_block(&[]),
888 };
889
890 let result = input.seek_non_whitespace_forward(123);
891
892 assert_eq!(result, Some((123, b':')));
893 }
894
895 #[test]
896 fn seeking_from_middle_block_from_non_whitespace_returns_that() {
897 let input = TwoSidesPaddedInput {
898 first_block: &PaddedBlock::pad_first_block(&[]),
899 middle: r#"{"seek": 42}"#.as_bytes(),
900 last_block: &PaddedBlock::pad_last_block(&[]),
901 };
902
903 let result = input.seek_non_whitespace_forward(128 + 7);
904
905 assert_eq!(result, Some((128 + 7, b':')));
906 }
907
908 #[test]
909 fn seeking_from_last_block_from_non_whitespace_returns_that() {
910 let input = TwoSidesPaddedInput {
911 first_block: &PaddedBlock::pad_first_block(&[]),
912 middle: &iter::repeat(b' ').take(256).collect::<Vec<_>>(),
913 last_block: &PaddedBlock::pad_last_block(r#"{"seek": 42}"#.as_bytes()),
914 };
915
916 let result = input.seek_non_whitespace_forward(128 + 256 + 7);
917
918 assert_eq!(result, Some((128 + 256 + 7, b':')));
919 }
920
921 #[test]
922 fn seeking_from_whitespace_returns_next_non_whitespace() {
923 let bytes = "seek: \t\n42}".as_bytes();
924
925 let result = bytes.seek_non_whitespace_forward(5);
926
927 assert_eq!(result, Some((8, b'4')));
928 }
929
930 #[test]
931 fn seeking_from_whitespace_when_there_is_no_more_non_whitespace_returns_none() {
932 let bytes = "seek: \t\n ".as_bytes();
933
934 let result = bytes.seek_non_whitespace_forward(5);
935
936 assert_eq!(result, None);
937 }
938 }
939 }
940}