pub struct FastInput {
ptr: *const u8,
end: *const u8,
}Expand description
Token reader for little-endian targets. Integer reads require a decimal
representation that fits the requested type, with at most that type’s maximum
number of digits and an optional - for signed types.
Every read, including iterator reads, must start at an available token.
Reads consume exactly one trailing ASCII whitespace byte. parse and
ScanSource require UTF-8. Slices returned by bytes must not outlive the input
allocation. bytes and parse may also read an empty field at a delimiter.
Fields§
§ptr: *const u8§end: *const u8Implementations§
Source§impl FastInput
impl FastInput
Sourcepub unsafe fn stdin() -> Self
pub unsafe fn stdin() -> Self
Reads all of stdin and retains its storage until process exit.
§Safety
Call before any other stdin reads. A mapped input file must not be modified
while its contents or slices returned by this reader are in use.
Subsequent ScanSource reads must satisfy this type’s token requirements.
Sourcepub unsafe fn from_slice(s: &[u8]) -> Self
pub unsafe fn from_slice(s: &[u8]) -> Self
§Safety
s must contain at least 16 initialized padding bytes after its final
token delimiter. Its allocation must remain valid and unchanged while
this reader or any slices returned by it are in use.
Subsequent ScanSource reads must satisfy this type’s token requirements.
Sourcepub fn skip_whitespace(&mut self)
pub fn skip_whitespace(&mut self)
Skips ASCII whitespace without advancing beyond the input.
Examples found in repository?
More examples
Sourcepub unsafe fn u64(&mut self) -> u64
pub unsafe fn u64(&mut self) -> u64
Examples found in repository?
465 pub unsafe fn usize(&mut self) -> usize {
466 unsafe { self.u64() as usize }
467 }
468
469 #[inline]
470 pub unsafe fn i8(&mut self) -> i8 {
471 unsafe {
472 let b = *self.ptr == b'-';
473 self.ptr = self.ptr.add(b as usize);
474 let mut x = self.u8() as i8;
475 if b {
476 x = x.wrapping_neg();
477 }
478 x
479 }
480 }
481
482 #[inline]
483 pub unsafe fn i16(&mut self) -> i16 {
484 unsafe {
485 let b = *self.ptr == b'-';
486 self.ptr = self.ptr.add(b as usize);
487 let mut x = self.u16() as i16;
488 if b {
489 x = x.wrapping_neg();
490 }
491 x
492 }
493 }
494
495 #[inline]
496 pub unsafe fn i32(&mut self) -> i32 {
497 unsafe {
498 let b = *self.ptr == b'-';
499 self.ptr = self.ptr.add(b as usize);
500 let mut x = self.u32() as i32;
501 if b {
502 x = x.wrapping_neg();
503 }
504 x
505 }
506 }
507
508 #[inline]
509 pub unsafe fn i64(&mut self) -> i64 {
510 unsafe {
511 let b = *self.ptr == b'-';
512 self.ptr = self.ptr.add(b as usize);
513 #[cfg(all(target_arch = "x86_64", target_feature = "ssse3"))]
514 let mut x = self.u64_simd::<19>() as i64;
515 #[cfg(not(all(target_arch = "x86_64", target_feature = "ssse3")))]
516 let mut x = self.u64() as i64;
517 if b {
518 x = x.wrapping_neg();
519 }
520 x
521 }
522 }pub unsafe fn usize(&mut self) -> usize
pub unsafe fn i8(&mut self) -> i8
pub unsafe fn i16(&mut self) -> i16
pub unsafe fn i32(&mut self) -> i32
pub unsafe fn i128(&mut self) -> i128
pub unsafe fn isize(&mut self) -> isize
pub unsafe fn byte(&mut self) -> u8
Sourcepub unsafe fn bytes<'a>(&mut self) -> &'a [u8] ⓘ
pub unsafe fn bytes<'a>(&mut self) -> &'a [u8] ⓘ
Examples found in repository?
More examples
620 pub unsafe fn parse<T>(&mut self) -> T
621 where
622 T: FromStr,
623 {
624 unsafe {
625 let s = std::str::from_utf8_unchecked(self.bytes());
626 s.parse().ok().unwrap()
627 }
628 }
629}
630
631/// Buffered token reader with the same token requirements as [`FastInput`].
632/// Tokens may span reads and borrowed tokens remain valid until the next scan.
633pub struct BufferedInput<R> {
634 reader: R,
635 buffer: Vec<u8>,
636 input: FastInput,
637 filled: usize,
638 eof: bool,
639}
640
641impl<R: Read> BufferedInput<R> {
642 /// # Safety
643 /// Every scan must satisfy [`FastInput`]'s token requirements, including UTF-8.
644 pub unsafe fn new(reader: R) -> Self {
645 let buffer = vec![b' '; (1 << 16) + 16];
646 let input = FastInput {
647 ptr: buffer.as_ptr(),
648 end: buffer.as_ptr(),
649 };
650 Self {
651 reader,
652 buffer,
653 input,
654 filled: 0,
655 eof: false,
656 }
657 }
658
659 #[cold]
660 fn refill(&mut self) -> bool {
661 if self.eof {
662 return false;
663 }
664 let position = unsafe { self.input.ptr.offset_from(self.buffer.as_ptr()) as usize };
665 self.buffer.copy_within(position..self.filled, 0);
666 self.filled -= position;
667 self.input = FastInput {
668 ptr: self.buffer.as_ptr(),
669 end: self.buffer.as_ptr(),
670 };
671 loop {
672 if self.filled == self.buffer.len() - 16 {
673 self.buffer.resize(2 * self.filled + 16, b' ');
674 self.input = FastInput {
675 ptr: self.buffer.as_ptr(),
676 end: self.buffer.as_ptr(),
677 };
678 }
679 let end = self.buffer.len() - 16;
680 let start = self.filled;
681 match self.reader.read(&mut self.buffer[self.filled..end]) {
682 Ok(0) => {
683 self.eof = true;
684 if self.filled != 0 {
685 self.buffer[self.filled] = b' ';
686 self.filled += 1;
687 }
688 }
689 Ok(n) => self.filled += n,
690 Err(e) if e.kind() == std::io::ErrorKind::Interrupted => continue,
691 Err(e) => panic!("io error: {e}"),
692 }
693 let (prefix, chunks) = self.buffer[start..self.filled].as_rchunks();
694 let end = prefix.len()
695 + 8 * chunks
696 .iter()
697 .rposition(|&chunk| {
698 let x = u64::from_le_bytes(chunk);
699 x.wrapping_sub(0x2121_2121_2121_2121) & !x & 0x8080_8080_8080_8080 != 0
700 })
701 .map_or(0, |i| i + 1);
702 if let Some(end) = self.buffer[start..start + end]
703 .iter()
704 .rposition(u8::is_ascii_whitespace)
705 {
706 self.buffer[self.filled..self.filled + 16].fill(b' ');
707 self.input = FastInput {
708 ptr: self.buffer.as_ptr(),
709 end: unsafe { self.buffer.as_ptr().add(start + end + 1) },
710 };
711 return true;
712 }
713 if self.eof {
714 self.input = FastInput {
715 ptr: self.buffer.as_ptr(),
716 end: self.buffer.as_ptr(),
717 };
718 return false;
719 }
720 }
721 }
722}
723
724macro_rules! impl_buffered_scan_integer {
725 ($($ty:ty, $read:ident, $method:ident);* $(;)?) => {$(
726 #[inline]
727 fn $read(&mut self) -> Option<$ty> {
728 if self.input.ptr >= self.input.end && !self.refill() {
729 return None;
730 }
731 Some(unsafe { self.input.$method() })
732 }
733 )*};
734}
735
736impl<R: Read> ScanSource for BufferedInput<R> {
737 #[inline]
738 fn skip_whitespace(&mut self) {
739 loop {
740 self.input.skip_whitespace();
741 if self.input.ptr < self.input.end || !self.refill() {
742 break;
743 }
744 }
745 }
746
747 #[inline]
748 fn next_token(&mut self) -> Option<&str> {
749 if self.input.ptr >= self.input.end && !self.refill() {
750 return None;
751 }
752 Some(unsafe { std::str::from_utf8_unchecked(self.input.bytes()) })
753 }pub unsafe fn parse<T>(&mut self) -> Twhere
T: FromStr,
Trait Implementations§
Source§impl ScanSource for FastInput
impl ScanSource for FastInput
Source§fn skip_whitespace(&mut self)
fn skip_whitespace(&mut self)
Source§fn next_token(&mut self) -> Option<&str>
fn next_token(&mut self) -> Option<&str>
None at EOF; unchecked sources require available input.