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}