scanner_rust/scanner.rs
1use std::{
2 char::REPLACEMENT_CHARACTER,
3 fs::File,
4 io::Read,
5 path::Path,
6 str::{FromStr, from_utf8},
7};
8
9use educe::Educe;
10use utf8_width::*;
11
12use crate::{
13 ScannerError,
14 kmp::compute_lps,
15 reader::read,
16 text::{into_string_lossy, numeric_text},
17 whitespaces::*,
18};
19
20/// A simple text scanner which can parse primitive types and strings using UTF-8.
21#[derive(Educe)]
22#[educe(Debug)]
23pub struct Scanner<R: Read, const N: usize = 256> {
24 #[educe(Debug(ignore))]
25 reader: R,
26 buf: [u8; N],
27 buf_length: usize,
28 buf_offset: usize,
29 passing_byte: Option<u8>,
30}
31
32impl<R: Read> Scanner<R> {
33 /// Create a scanner from a reader.
34 ///
35 /// ```rust
36 /// use std::io;
37 ///
38 /// use scanner_rust::Scanner;
39 ///
40 /// let mut sc = Scanner::new(io::stdin());
41 /// ```
42 #[inline]
43 pub fn new(reader: R) -> Scanner<R> {
44 Self::new2(reader)
45 }
46}
47
48impl<R: Read, const N: usize> Scanner<R, N> {
49 /// Create a scanner from a reader and set the buffer size via generics.
50 ///
51 /// The buffer size `N` must be at least 4 bytes.
52 ///
53 /// ```rust
54 /// use std::io;
55 ///
56 /// use scanner_rust::Scanner;
57 ///
58 /// let mut sc: Scanner<_, 1024> = Scanner::new2(io::stdin());
59 /// ```
60 #[inline]
61 pub fn new2(reader: R) -> Scanner<R, N> {
62 // The buffer must be at least 4 bytes to hold a full UTF-8 character.
63 const { assert!(N >= 4, "the buffer size N must be at least 4 bytes") };
64
65 Scanner {
66 reader,
67 buf: [0u8; N],
68 buf_length: 0,
69 buf_offset: 0,
70 passing_byte: None,
71 }
72 }
73}
74
75impl Scanner<File> {
76 /// Create a scanner to read data from a file by its path.
77 ///
78 /// ```rust
79 /// use scanner_rust::Scanner;
80 ///
81 /// let mut sc = Scanner::scan_path("Cargo.toml").unwrap();
82 /// ```
83 #[inline]
84 pub fn scan_path<P: AsRef<Path>>(path: P) -> Result<Scanner<File>, ScannerError> {
85 Self::scan_path2(path)
86 }
87}
88
89impl<const N: usize> Scanner<File, N> {
90 /// Create a scanner to read data from a file by its path and set the buffer size via generics.
91 ///
92 /// The buffer size `N` must be at least 4 bytes.
93 ///
94 /// ```rust
95 /// use scanner_rust::Scanner;
96 ///
97 /// let mut sc: Scanner<_, 1024> = Scanner::scan_path2("Cargo.toml").unwrap();
98 /// ```
99 #[inline]
100 pub fn scan_path2<P: AsRef<Path>>(path: P) -> Result<Scanner<File, N>, ScannerError> {
101 let reader = File::open(path)?;
102
103 Ok(Scanner::new2(reader))
104 }
105}
106
107impl<R: Read, const N: usize> Scanner<R, N> {
108 #[inline]
109 fn buf_align_to_front_end(&mut self) {
110 self.buf.copy_within(self.buf_offset..(self.buf_offset + self.buf_length), 0);
111
112 self.buf_offset = 0;
113 }
114
115 #[inline]
116 fn buf_left_shift(&mut self, distance: usize) {
117 debug_assert!(self.buf_length >= distance);
118
119 self.buf_offset += distance;
120 self.buf_length -= distance;
121
122 if self.buf_offset >= N - 4 {
123 self.buf_align_to_front_end();
124 }
125 }
126
127 /// Left shift (if necessary) the buffer to remove bytes from the start of the buffer. Typically, you should use this after `peek`ing the buffer.
128 ///
129 /// # Safety
130 ///
131 /// `number_of_bytes` must not be greater than the length of the currently buffered data (the length of the slice returned by `peek`). A larger value underflows the internal buffer length and causes out-of-bounds access afterwards.
132 #[inline]
133 pub unsafe fn remove_heading_bytes_from_buffer(&mut self, number_of_bytes: usize) {
134 self.buf_left_shift(number_of_bytes);
135 }
136
137 #[inline]
138 fn buf_skip_line(&mut self, line_length: usize) {
139 let ending = if self.buf[self.buf_offset + line_length] == b'\n' { b'\r' } else { b'\n' };
140 let mut consumed = line_length + 1;
141
142 if consumed == self.buf_length {
143 // Defer the second byte when a line ending is split across reads.
144 self.passing_byte = Some(ending);
145 } else if self.buf[self.buf_offset + consumed] == ending {
146 consumed += 1;
147 }
148
149 self.buf_left_shift(consumed);
150 }
151
152 #[inline]
153 fn buf_fill_char(&mut self, width: usize) -> Result<usize, ScannerError> {
154 while self.buf_length < width {
155 let size =
156 read(&mut self.reader, &mut self.buf[(self.buf_offset + self.buf_length)..])?;
157
158 if size == 0 {
159 // A sequence cut off by the end of data is handled one byte at a time.
160 return Ok(1);
161 }
162
163 self.buf_length += size;
164 }
165
166 Ok(width)
167 }
168
169 #[inline]
170 fn buf_raw_char_width(&mut self) -> Result<usize, ScannerError> {
171 let width = get_width(self.buf[self.buf_offset]);
172
173 if width <= 1 || self.buf_fill_char(width)? == 1 {
174 return Ok(1);
175 }
176
177 // A broken sequence must not skip over a whitespace byte.
178 if self.buf[(self.buf_offset + 1)..(self.buf_offset + width)]
179 .iter()
180 .all(|byte| byte & 0xC0 == 0x80)
181 {
182 Ok(width)
183 } else {
184 Ok(1)
185 }
186 }
187
188 // Force inlining because this runs for every multi-byte character in hot loops.
189 #[inline(always)]
190 fn buf_push_char(&mut self, temp: &mut String, width: usize) {
191 match from_utf8(&self.buf[self.buf_offset..(self.buf_offset + width)]) {
192 Ok(char_str) => {
193 temp.push_str(char_str);
194
195 self.buf_left_shift(width);
196 },
197 Err(_) => {
198 temp.push(REPLACEMENT_CHARACTER);
199
200 self.buf_left_shift(1);
201 },
202 }
203 }
204
205 fn passing_read(&mut self) -> Result<bool, ScannerError> {
206 if self.buf_length == 0 {
207 let size = read(&mut self.reader, &mut self.buf[self.buf_offset..])?;
208
209 if size == 0 {
210 return Ok(false);
211 }
212
213 self.buf_length += size;
214
215 if let Some(passing_byte) = self.passing_byte.take()
216 && self.buf[self.buf_offset] == passing_byte
217 {
218 self.buf_left_shift(1);
219
220 return if size == 1 {
221 let size = read(&mut self.reader, &mut self.buf[self.buf_offset..])?;
222
223 if size == 0 {
224 Ok(false)
225 } else {
226 self.buf_length += size;
227
228 Ok(true)
229 }
230 } else {
231 Ok(true)
232 };
233 }
234
235 Ok(true)
236 } else {
237 Ok(true)
238 }
239 }
240}
241
242impl<R: Read, const N: usize> Scanner<R, N> {
243 /// Read the next char. If the data is not a correct char, it will return a `Ok(Some(REPLACEMENT_CHARACTER))` which is �. If there is nothing to read, it will return `Ok(None)`.
244 ///
245 /// ```rust
246 /// use scanner_rust::Scanner;
247 ///
248 /// let mut sc = Scanner::new("5 c 中文".as_bytes());
249 ///
250 /// assert_eq!(Some('5'), sc.next_char().unwrap());
251 /// assert_eq!(Some(' '), sc.next_char().unwrap());
252 /// assert_eq!(Some('c'), sc.next_char().unwrap());
253 /// assert_eq!(Some(' '), sc.next_char().unwrap());
254 /// assert_eq!(Some('中'), sc.next_char().unwrap());
255 /// assert_eq!(Some('文'), sc.next_char().unwrap());
256 /// assert_eq!(None, sc.next_char().unwrap());
257 /// ```
258 pub fn next_char(&mut self) -> Result<Option<char>, ScannerError> {
259 if !self.passing_read()? {
260 return Ok(None);
261 }
262
263 let e = self.buf[self.buf_offset];
264
265 let width = get_width(e);
266
267 match width {
268 0 => {
269 self.buf_left_shift(1);
270
271 Ok(Some(REPLACEMENT_CHARACTER))
272 },
273 1 => {
274 self.buf_left_shift(1);
275
276 Ok(Some(e as char))
277 },
278 _ => {
279 let width = self.buf_fill_char(width)?;
280 let char_str_bytes = &self.buf[self.buf_offset..(self.buf_offset + width)];
281
282 match from_utf8(char_str_bytes) {
283 Ok(char_str) => {
284 let c = char_str.chars().next();
285
286 self.buf_left_shift(width);
287
288 Ok(c)
289 },
290 Err(_) => {
291 self.buf_left_shift(1);
292
293 Ok(Some(REPLACEMENT_CHARACTER))
294 },
295 }
296 },
297 }
298 }
299
300 /// Read the next line but not include the trailing line character (or line characters like `CrLf`(`\r\n`)). If there is nothing to read, it will return `Ok(None)`.
301 ///
302 /// ```rust
303 /// use scanner_rust::Scanner;
304 ///
305 /// let mut sc = Scanner::new("123 456\r\n789 \n\n 中文 ".as_bytes());
306 ///
307 /// assert_eq!(Some("123 456".into()), sc.next_line().unwrap());
308 /// assert_eq!(Some("789 ".into()), sc.next_line().unwrap());
309 /// assert_eq!(Some("".into()), sc.next_line().unwrap());
310 /// assert_eq!(Some(" 中文 ".into()), sc.next_line().unwrap());
311 /// ```
312 pub fn next_line(&mut self) -> Result<Option<String>, ScannerError> {
313 if !self.passing_read()? {
314 return Ok(None);
315 }
316
317 let mut temp = String::new();
318
319 loop {
320 let e = self.buf[self.buf_offset];
321
322 let width = get_width(e);
323
324 match width {
325 0 => {
326 self.buf_left_shift(1);
327
328 temp.push(REPLACEMENT_CHARACTER);
329 },
330 1 => {
331 if e == b'\n' || e == b'\r' {
332 self.buf_skip_line(0);
333
334 return Ok(Some(temp));
335 }
336
337 self.buf_left_shift(1);
338
339 temp.push(e as char);
340 },
341 _ => {
342 let width = self.buf_fill_char(width)?;
343
344 self.buf_push_char(&mut temp, width);
345 },
346 }
347
348 if self.buf_length == 0 {
349 let size = read(&mut self.reader, &mut self.buf[self.buf_offset..])?;
350
351 if size == 0 {
352 return Ok(Some(temp));
353 }
354
355 self.buf_length += size;
356 }
357 }
358 }
359
360 /// Read the next line but not include the trailing line character (or line characters like `CrLf`(`\r\n`)) without fully validating UTF-8. If there is nothing to read, it will return `Ok(None)`.
361 ///
362 /// ```rust
363 /// use scanner_rust::Scanner;
364 ///
365 /// let mut sc = Scanner::new("123 456\r\n789 \n\n 中文 ".as_bytes());
366 ///
367 /// assert_eq!(Some("123 456".into()), sc.next_line_raw().unwrap());
368 /// assert_eq!(Some("789 ".into()), sc.next_line_raw().unwrap());
369 /// assert_eq!(Some("".into()), sc.next_line_raw().unwrap());
370 /// assert_eq!(Some(" 中文 ".into()), sc.next_line_raw().unwrap());
371 /// ```
372 pub fn next_line_raw(&mut self) -> Result<Option<Vec<u8>>, ScannerError> {
373 if !self.passing_read()? {
374 return Ok(None);
375 }
376
377 let mut temp = Vec::new();
378
379 loop {
380 let data = &self.buf[self.buf_offset..(self.buf_offset + self.buf_length)];
381
382 if let Some(line_length) = data.iter().position(|&byte| byte == b'\n' || byte == b'\r')
383 {
384 temp.extend_from_slice(&data[..line_length]);
385 self.buf_skip_line(line_length);
386
387 return Ok(Some(temp));
388 }
389
390 temp.extend_from_slice(data);
391 self.buf_left_shift(self.buf_length);
392
393 if !self.passing_read()? {
394 return Ok(Some(temp));
395 }
396 }
397 }
398
399 /// Drop the next line but not include the trailing line character (or line characters like `CrLf`(`\r\n`)). If there is nothing to read, it will return `Ok(None)`. If there is something to read, it will return `Ok(Some(i))`. The `i` is the length (in bytes) of the dropped line.
400 ///
401 /// ```rust
402 /// use scanner_rust::Scanner;
403 ///
404 /// let mut sc = Scanner::new("123 456\r\n789 \n\n 中文 ".as_bytes());
405 ///
406 /// assert_eq!(Some(7), sc.drop_next_line().unwrap());
407 /// assert_eq!(Some("789 ".into()), sc.next_line().unwrap());
408 /// assert_eq!(Some(0), sc.drop_next_line().unwrap());
409 /// assert_eq!(Some(" 中文 ".into()), sc.next_line().unwrap());
410 /// assert_eq!(None, sc.drop_next_line().unwrap());
411 /// ```
412 pub fn drop_next_line(&mut self) -> Result<Option<usize>, ScannerError> {
413 if !self.passing_read()? {
414 return Ok(None);
415 }
416
417 let mut c = 0;
418
419 loop {
420 let data = &self.buf[self.buf_offset..(self.buf_offset + self.buf_length)];
421
422 if let Some(line_length) = data.iter().position(|&byte| byte == b'\n' || byte == b'\r')
423 {
424 self.buf_skip_line(line_length);
425
426 return Ok(Some(c + line_length));
427 }
428
429 c += self.buf_length;
430 self.buf_left_shift(self.buf_length);
431
432 if !self.passing_read()? {
433 return Ok(Some(c));
434 }
435 }
436 }
437}
438
439impl<R: Read, const N: usize> Scanner<R, N> {
440 /// Skip the next whitespaces (`javaWhitespace`). If there is nothing to read, it will return `Ok(false)`.
441 ///
442 /// ```rust
443 /// use scanner_rust::Scanner;
444 ///
445 /// let mut sc = Scanner::new("1 2 c".as_bytes());
446 ///
447 /// assert_eq!(Some('1'), sc.next_char().unwrap());
448 /// assert_eq!(Some(' '), sc.next_char().unwrap());
449 /// assert_eq!(Some('2'), sc.next_char().unwrap());
450 /// assert_eq!(true, sc.skip_whitespaces().unwrap());
451 /// assert_eq!(Some('c'), sc.next_char().unwrap());
452 /// assert_eq!(false, sc.skip_whitespaces().unwrap());
453 /// ```
454 pub fn skip_whitespaces(&mut self) -> Result<bool, ScannerError> {
455 if !self.passing_read()? {
456 return Ok(false);
457 }
458
459 loop {
460 let e = self.buf[self.buf_offset];
461
462 let width = get_width(e);
463
464 match width {
465 0 => {
466 break;
467 },
468 1 => {
469 if !is_whitespace_1(e) {
470 break;
471 }
472
473 self.buf_left_shift(1);
474 },
475 3 if self.buf_fill_char(width)? == width
476 && is_whitespace_3(
477 self.buf[self.buf_offset],
478 self.buf[self.buf_offset + 1],
479 self.buf[self.buf_offset + 2],
480 ) =>
481 {
482 self.buf_left_shift(3);
483 },
484 _ => {
485 break;
486 },
487 }
488
489 if self.buf_length == 0 {
490 let size = read(&mut self.reader, &mut self.buf[self.buf_offset..])?;
491
492 if size == 0 {
493 return Ok(true);
494 }
495
496 self.buf_length += size;
497 }
498 }
499
500 Ok(true)
501 }
502
503 /// Read the next token separated by whitespaces. If there is nothing to read, it will return `Ok(None)`.
504 ///
505 /// ```rust
506 /// use scanner_rust::Scanner;
507 ///
508 /// let mut sc = Scanner::new("123 456\r\n789 \n\n 中文 ".as_bytes());
509 ///
510 /// assert_eq!(Some("123".into()), sc.next().unwrap());
511 /// assert_eq!(Some("456".into()), sc.next().unwrap());
512 /// assert_eq!(Some("789".into()), sc.next().unwrap());
513 /// assert_eq!(Some("中文".into()), sc.next().unwrap());
514 /// assert_eq!(None, sc.next().unwrap());
515 /// ```
516 #[allow(clippy::should_implement_trait)]
517 pub fn next(&mut self) -> Result<Option<String>, ScannerError> {
518 if !self.skip_whitespaces()? || self.buf_length == 0 {
519 return Ok(None);
520 }
521
522 let mut temp = String::new();
523
524 loop {
525 let e = self.buf[self.buf_offset];
526
527 let width = get_width(e);
528
529 match width {
530 0 => {
531 self.buf_left_shift(1);
532
533 temp.push(REPLACEMENT_CHARACTER);
534 },
535 1 => {
536 if is_whitespace_1(e) {
537 return Ok(Some(temp));
538 }
539
540 self.buf_left_shift(1);
541
542 temp.push(e as char);
543 },
544 _ => {
545 let width = self.buf_fill_char(width)?;
546
547 if width == 3
548 && is_whitespace_3(
549 self.buf[self.buf_offset],
550 self.buf[self.buf_offset + 1],
551 self.buf[self.buf_offset + 2],
552 )
553 {
554 return Ok(Some(temp));
555 }
556
557 self.buf_push_char(&mut temp, width);
558 },
559 }
560
561 if self.buf_length == 0 {
562 let size = read(&mut self.reader, &mut self.buf[self.buf_offset..])?;
563
564 if size == 0 {
565 return Ok(Some(temp));
566 }
567
568 self.buf_length += size;
569 }
570 }
571 }
572
573 /// Read the next token separated by whitespaces without fully validating UTF-8. If there is nothing to read, it will return `Ok(None)`.
574 ///
575 /// ```rust
576 /// use scanner_rust::Scanner;
577 ///
578 /// let mut sc = Scanner::new("123 456\r\n789 \n\n 中文 ".as_bytes());
579 ///
580 /// assert_eq!(Some("123".into()), sc.next_raw().unwrap());
581 /// assert_eq!(Some("456".into()), sc.next_raw().unwrap());
582 /// assert_eq!(Some("789".into()), sc.next_raw().unwrap());
583 /// assert_eq!(Some("中文".into()), sc.next_raw().unwrap());
584 /// assert_eq!(None, sc.next_raw().unwrap());
585 /// ```
586 pub fn next_raw(&mut self) -> Result<Option<Vec<u8>>, ScannerError> {
587 if !self.skip_whitespaces()? || self.buf_length == 0 {
588 return Ok(None);
589 }
590
591 let mut temp = Vec::new();
592
593 loop {
594 let width = self.buf_raw_char_width()?;
595
596 if (width == 1 && is_whitespace_1(self.buf[self.buf_offset]))
597 || (width == 3
598 && is_whitespace_3(
599 self.buf[self.buf_offset],
600 self.buf[self.buf_offset + 1],
601 self.buf[self.buf_offset + 2],
602 ))
603 {
604 return Ok(Some(temp));
605 }
606
607 temp.extend_from_slice(&self.buf[self.buf_offset..(self.buf_offset + width)]);
608 self.buf_left_shift(width);
609
610 if !self.passing_read()? {
611 return Ok(Some(temp));
612 }
613 }
614 }
615
616 /// Drop the next token separated by whitespaces. If there is nothing to read, it will return `Ok(None)`. If there is something to read, it will return `Ok(Some(i))`. The `i` is the length (in bytes) of the dropped token.
617 ///
618 /// ```rust
619 /// use scanner_rust::Scanner;
620 ///
621 /// let mut sc = Scanner::new("123 456\r\n789 \n\n 中文 ".as_bytes());
622 ///
623 /// assert_eq!(Some(3), sc.drop_next().unwrap());
624 /// assert_eq!(Some("456".into()), sc.next().unwrap());
625 /// assert_eq!(Some(3), sc.drop_next().unwrap());
626 /// assert_eq!(Some("中文".into()), sc.next().unwrap());
627 /// assert_eq!(None, sc.drop_next().unwrap());
628 /// ```
629 pub fn drop_next(&mut self) -> Result<Option<usize>, ScannerError> {
630 if !self.skip_whitespaces()? || self.buf_length == 0 {
631 return Ok(None);
632 }
633
634 let mut c = 0;
635
636 loop {
637 let width = self.buf_raw_char_width()?;
638
639 if (width == 1 && is_whitespace_1(self.buf[self.buf_offset]))
640 || (width == 3
641 && is_whitespace_3(
642 self.buf[self.buf_offset],
643 self.buf[self.buf_offset + 1],
644 self.buf[self.buf_offset + 2],
645 ))
646 {
647 return Ok(Some(c));
648 }
649
650 c += width;
651 self.buf_left_shift(width);
652
653 if !self.passing_read()? {
654 return Ok(Some(c));
655 }
656 }
657 }
658}
659
660impl<R: Read, const N: usize> Scanner<R, N> {
661 /// Read the next bytes. If there is nothing to read, it will return `Ok(None)`.
662 ///
663 /// ```rust
664 /// use scanner_rust::Scanner;
665 ///
666 /// let mut sc = Scanner::new("123 456\r\n789 \n\n 中文 ".as_bytes());
667 ///
668 /// assert_eq!(Some("123".into()), sc.next_bytes(3).unwrap());
669 /// assert_eq!(Some(" 456".into()), sc.next_bytes(4).unwrap());
670 /// assert_eq!(Some("\r\n789 ".into()), sc.next_bytes(6).unwrap());
671 /// assert_eq!(Some("中文".into()), sc.next_raw().unwrap());
672 /// assert_eq!(Some(" ".into()), sc.next_bytes(2).unwrap());
673 /// assert_eq!(None, sc.next_bytes(2).unwrap());
674 /// ```
675 pub fn next_bytes(
676 &mut self,
677 max_number_of_bytes: usize,
678 ) -> Result<Option<Vec<u8>>, ScannerError> {
679 if !self.passing_read()? {
680 return Ok(None);
681 }
682
683 let mut temp = Vec::new();
684 let mut c = 0;
685
686 while c < max_number_of_bytes {
687 if self.buf_length == 0 {
688 let size = read(&mut self.reader, &mut self.buf[self.buf_offset..])?;
689
690 if size == 0 {
691 return Ok(Some(temp));
692 }
693
694 self.buf_length += size;
695 }
696
697 let dropping_bytes = self.buf_length.min(max_number_of_bytes - c);
698
699 temp.extend_from_slice(&self.buf[self.buf_offset..(self.buf_offset + dropping_bytes)]);
700
701 self.buf_left_shift(dropping_bytes);
702
703 c += dropping_bytes;
704 }
705
706 Ok(Some(temp))
707 }
708
709 /// Drop the next N bytes. If there is nothing to read, it will return `Ok(None)`. If there is something to read, it will return `Ok(Some(i))`. The `i` is the length of the actually dropped bytes.
710 ///
711 /// ```rust
712 /// use scanner_rust::Scanner;
713 ///
714 /// let mut sc = Scanner::new("123 456\r\n789 \n\n 中文 ".as_bytes());
715 ///
716 /// assert_eq!(Some(7), sc.drop_next_bytes(7).unwrap());
717 /// assert_eq!(Some("".into()), sc.next_line().unwrap());
718 /// assert_eq!(Some("789 ".into()), sc.next_line().unwrap());
719 /// assert_eq!(Some(1), sc.drop_next_bytes(1).unwrap());
720 /// assert_eq!(Some(" 中文 ".into()), sc.next_line().unwrap());
721 /// assert_eq!(None, sc.drop_next_bytes(1).unwrap());
722 /// ```
723 pub fn drop_next_bytes(
724 &mut self,
725 max_number_of_bytes: usize,
726 ) -> Result<Option<usize>, ScannerError> {
727 if !self.passing_read()? {
728 return Ok(None);
729 }
730
731 let mut c = 0;
732
733 while c < max_number_of_bytes {
734 if self.buf_length == 0 {
735 let size = read(&mut self.reader, &mut self.buf[self.buf_offset..])?;
736
737 if size == 0 {
738 return Ok(Some(c));
739 }
740
741 self.buf_length += size;
742 }
743
744 let dropping_bytes = self.buf_length.min(max_number_of_bytes - c);
745
746 self.buf_left_shift(dropping_bytes);
747
748 c += dropping_bytes;
749 }
750
751 Ok(Some(c))
752 }
753}
754
755impl<R: Read, const N: usize> Scanner<R, N> {
756 /// Read the next text until it reaches a specific boundary. If there is nothing to read, it will return `Ok(None)`.
757 ///
758 /// An empty boundary reads all remaining data.
759 ///
760 /// ```rust
761 /// use scanner_rust::Scanner;
762 ///
763 /// let mut sc = Scanner::new("123 456\r\n789 \n\n 中文 ".as_bytes());
764 ///
765 /// assert_eq!(Some("123".into()), sc.next_until(" ").unwrap());
766 /// assert_eq!(Some("456\r".into()), sc.next_until("\n").unwrap());
767 /// assert_eq!(Some("78".into()), sc.next_until("9 ").unwrap());
768 /// assert_eq!(Some("\n\n 中文 ".into()), sc.next_until("kk").unwrap());
769 /// assert_eq!(None, sc.next().unwrap());
770 /// ```
771 pub fn next_until<S: AsRef<str>>(
772 &mut self,
773 boundary: S,
774 ) -> Result<Option<String>, ScannerError> {
775 let boundary = boundary.as_ref();
776
777 Ok(self.next_until_raw(boundary.as_bytes())?.map(into_string_lossy))
778 }
779
780 /// Read the next data until it reaches a specific boundary without fully validating UTF-8. If there is nothing to read, it will return `Ok(None)`.
781 ///
782 /// An empty boundary reads all remaining data.
783 ///
784 /// ```rust
785 /// use scanner_rust::Scanner;
786 ///
787 /// let mut sc = Scanner::new("123 456\r\n789 \n\n 中文 ".as_bytes());
788 ///
789 /// assert_eq!(Some("123".into()), sc.next_until_raw(" ").unwrap());
790 /// assert_eq!(Some("456\r".into()), sc.next_until_raw("\n").unwrap());
791 /// assert_eq!(Some("78".into()), sc.next_until_raw("9 ").unwrap());
792 /// assert_eq!(Some("\n\n 中文 ".into()), sc.next_until_raw("kk").unwrap());
793 /// assert_eq!(None, sc.next().unwrap());
794 /// ```
795 pub fn next_until_raw<D: ?Sized + AsRef<[u8]>>(
796 &mut self,
797 boundary: &D,
798 ) -> Result<Option<Vec<u8>>, ScannerError> {
799 if !self.passing_read()? {
800 return Ok(None);
801 }
802
803 let boundary = boundary.as_ref();
804 let boundary_length = boundary.len();
805 let mut temp = Vec::new();
806
807 // An empty boundary never matches, so keep reading until the end.
808 if boundary_length == 0 {
809 loop {
810 temp.extend_from_slice(
811 &self.buf[self.buf_offset..(self.buf_offset + self.buf_length)],
812 );
813
814 self.buf_left_shift(self.buf_length);
815
816 let size = read(&mut self.reader, &mut self.buf[self.buf_offset..])?;
817
818 if size == 0 {
819 return Ok(Some(temp));
820 }
821
822 self.buf_length += size;
823 }
824 }
825
826 // Match the boundary across buffer refills with KMP so a mismatch never re-reads bytes.
827 let lps = compute_lps(boundary);
828 let mut b = 0;
829
830 loop {
831 let mut i = 0;
832
833 while i < self.buf_length {
834 let e = self.buf[self.buf_offset + i];
835
836 while b > 0 && e != boundary[b] {
837 b = lps[b - 1];
838 }
839
840 if e == boundary[b] {
841 b += 1;
842 }
843
844 i += 1;
845
846 if b == boundary_length {
847 // The matched boundary is the last `boundary_length` bytes seen so far.
848 temp.extend_from_slice(&self.buf[self.buf_offset..(self.buf_offset + i)]);
849 temp.truncate(temp.len() - boundary_length);
850
851 self.buf_left_shift(i);
852
853 return Ok(Some(temp));
854 }
855 }
856
857 temp.extend_from_slice(&self.buf[self.buf_offset..(self.buf_offset + self.buf_length)]);
858
859 self.buf_left_shift(self.buf_length);
860
861 let size = read(&mut self.reader, &mut self.buf[self.buf_offset..])?;
862
863 if size == 0 {
864 return Ok(Some(temp));
865 }
866
867 self.buf_length += size;
868 }
869 }
870
871 /// Drop the next data until it reaches a specific boundary. If there is nothing to read, it will return `Ok(None)`. If there is something to read, it will return `Ok(Some(i))`. The `i` is the length (in bytes) of the dropped data, excluding the boundary.
872 ///
873 /// An empty boundary drops all remaining data.
874 ///
875 /// ```rust
876 /// use scanner_rust::Scanner;
877 ///
878 /// let mut sc = Scanner::new("123 456\r\n789 \n\n 中文 ".as_bytes());
879 ///
880 /// assert_eq!(Some(7), sc.drop_next_until("\r\n").unwrap());
881 /// assert_eq!(Some("789 ".into()), sc.next_line().unwrap());
882 /// assert_eq!(Some(0), sc.drop_next_until("\n").unwrap());
883 /// assert_eq!(Some(" 中文 ".into()), sc.next_line().unwrap());
884 /// assert_eq!(None, sc.drop_next_until("").unwrap());
885 /// ```
886 pub fn drop_next_until<D: ?Sized + AsRef<[u8]>>(
887 &mut self,
888 boundary: &D,
889 ) -> Result<Option<usize>, ScannerError> {
890 if !self.passing_read()? {
891 return Ok(None);
892 }
893
894 let boundary = boundary.as_ref();
895 let boundary_length = boundary.len();
896 let mut c = 0;
897
898 // An empty boundary never matches, so keep reading until the end.
899 if boundary_length == 0 {
900 loop {
901 c += self.buf_length;
902
903 self.buf_left_shift(self.buf_length);
904
905 let size = read(&mut self.reader, &mut self.buf[self.buf_offset..])?;
906
907 if size == 0 {
908 return Ok(Some(c));
909 }
910
911 self.buf_length += size;
912 }
913 }
914
915 // Match the boundary across buffer refills with KMP so a mismatch never re-reads bytes.
916 let lps = compute_lps(boundary);
917 let mut b = 0;
918
919 loop {
920 let mut i = 0;
921
922 while i < self.buf_length {
923 let e = self.buf[self.buf_offset + i];
924
925 while b > 0 && e != boundary[b] {
926 b = lps[b - 1];
927 }
928
929 if e == boundary[b] {
930 b += 1;
931 }
932
933 i += 1;
934
935 if b == boundary_length {
936 self.buf_left_shift(i);
937
938 return Ok(Some(c + i - boundary_length));
939 }
940 }
941
942 c += self.buf_length;
943
944 self.buf_left_shift(self.buf_length);
945
946 let size = read(&mut self.reader, &mut self.buf[self.buf_offset..])?;
947
948 if size == 0 {
949 return Ok(Some(c));
950 }
951
952 self.buf_length += size;
953 }
954 }
955}
956
957impl<R: Read, const N: usize> Scanner<R, N> {
958 /// Fill up the buffer as much as possible and return an immutable slice of all the currently buffered (unread) data.
959 /// Reading stops at the end of the stream or when the buffer is full. If `shift` is `true`, the buffered data is first moved to the front of the buffer so that up to the whole buffer size can be filled; if `false`, only the space after the current read position is filled.
960 ///
961 /// ```rust
962 /// use scanner_rust::Scanner;
963 ///
964 /// let mut sc = Scanner::new("123 456\r\n789 \n\n 中文 ".as_bytes());
965 ///
966 /// assert_eq!("123 456\r\n789 \n\n 中文 ".as_bytes(), sc.peek(false).unwrap());
967 /// ```
968 #[inline]
969 pub fn peek(&mut self, shift: bool) -> Result<&[u8], ScannerError> {
970 // Consume any line-terminator byte deferred by a previous read so it is not peeked again.
971 if !self.passing_read()? {
972 return Ok(&[]);
973 }
974
975 if shift {
976 self.buf_align_to_front_end();
977 }
978
979 while self.buf_offset + self.buf_length < N {
980 let size =
981 read(&mut self.reader, &mut self.buf[(self.buf_offset + self.buf_length)..])?;
982
983 if size == 0 {
984 break;
985 }
986
987 self.buf_length += size;
988 }
989
990 Ok(&self.buf[self.buf_offset..(self.buf_offset + self.buf_length)])
991 }
992}
993
994impl<R: Read, const N: usize> Scanner<R, N> {
995 #[inline]
996 fn next_raw_parse<T: FromStr>(&mut self) -> Result<Option<T>, ScannerError>
997 where
998 ScannerError: From<<T as FromStr>::Err>, {
999 let result = self.next_raw()?;
1000
1001 match result {
1002 Some(s) => Ok(Some(numeric_text(&s).parse()?)),
1003 None => Ok(None),
1004 }
1005 }
1006}
1007
1008impl<R: Read, const N: usize> Scanner<R, N> {
1009 #[inline]
1010 fn next_until_raw_parse<T: FromStr, D: ?Sized + AsRef<[u8]>>(
1011 &mut self,
1012 boundary: &D,
1013 ) -> Result<Option<T>, ScannerError>
1014 where
1015 ScannerError: From<<T as FromStr>::Err>, {
1016 let result = self.next_until_raw(boundary)?;
1017
1018 match result {
1019 Some(s) => Ok(Some(numeric_text(&s).parse()?)),
1020 None => Ok(None),
1021 }
1022 }
1023}
1024
1025macro_rules! scanner_number_methods {
1026 ($(($t:ty, $next:ident, $next_until:ident, $sample:literal, $v1:literal, $v2:literal)),+ $(,)?) => {
1027 impl<R: Read, const N: usize> Scanner<R, N> {
1028 $(
1029 #[doc = concat!(
1030 "Read the next token separated by whitespaces and parse it to a `", stringify!($t), "` value. If there is nothing to read, it will return `Ok(None)`.\n\n```rust\nuse scanner_rust::Scanner;\n\nlet mut sc = Scanner::new(", stringify!($sample), ".as_bytes());\n\nassert_eq!(Some(", stringify!($v1), "), sc.", stringify!($next), "().unwrap());\nassert_eq!(Some(", stringify!($v2), "), sc.", stringify!($next), "().unwrap());\n```"
1031 )]
1032 #[inline]
1033 pub fn $next(&mut self) -> Result<Option<$t>, ScannerError> {
1034 self.next_raw_parse()
1035 }
1036 )+
1037 }
1038
1039 impl<R: Read, const N: usize> Scanner<R, N> {
1040 $(
1041 #[doc = concat!(
1042 "Read the next text until it reaches a specific boundary and parse it to a `", stringify!($t), "` value. If there is nothing to read, it will return `Ok(None)`. An empty boundary reads all remaining data before parsing.\n\n```rust\nuse scanner_rust::Scanner;\n\nlet mut sc = Scanner::new(", stringify!($sample), ".as_bytes());\n\nassert_eq!(Some(", stringify!($v1), "), sc.", stringify!($next_until), "(\" \").unwrap());\nassert_eq!(Some(", stringify!($v2), "), sc.", stringify!($next_until), "(\" \").unwrap());\n```"
1043 )]
1044 #[inline]
1045 pub fn $next_until<D: ?Sized + AsRef<[u8]>>(
1046 &mut self,
1047 boundary: &D,
1048 ) -> Result<Option<$t>, ScannerError> {
1049 self.next_until_raw_parse(boundary)
1050 }
1051 )+
1052 }
1053 };
1054}
1055
1056scanner_number_methods! {
1057 (u8, next_u8, next_u8_until, "1 2", 1, 2),
1058 (u16, next_u16, next_u16_until, "1 2", 1, 2),
1059 (u32, next_u32, next_u32_until, "1 2", 1, 2),
1060 (u64, next_u64, next_u64_until, "1 2", 1, 2),
1061 (u128, next_u128, next_u128_until, "1 2", 1, 2),
1062 (usize, next_usize, next_usize_until, "1 2", 1, 2),
1063 (i8, next_i8, next_i8_until, "1 2", 1, 2),
1064 (i16, next_i16, next_i16_until, "1 2", 1, 2),
1065 (i32, next_i32, next_i32_until, "1 2", 1, 2),
1066 (i64, next_i64, next_i64_until, "1 2", 1, 2),
1067 (i128, next_i128, next_i128_until, "1 2", 1, 2),
1068 (isize, next_isize, next_isize_until, "1 2", 1, 2),
1069 (f32, next_f32, next_f32_until, "1 2.5", 1.0, 2.5),
1070 (f64, next_f64, next_f64_until, "1 2.5", 1.0, 2.5),
1071}