Skip to main content

scanner_rust/
scanner_ascii.rs

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