Skip to main content

scanner_rust/
scanner_ascii.rs

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