Skip to main content

FastInput

Struct FastInput 

Source
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 u8

Implementations§

Source§

impl FastInput

Source

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.

Source

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.

Source

pub fn skip_whitespace(&mut self)

Skips ASCII whitespace without advancing beyond the input.

Examples found in repository?
crates/competitive/src/tools/fast_scanner.rs (line 16)
15    fn skip_whitespace(&mut self) {
16        self.skip_whitespace();
17    }
More examples
Hide additional examples
crates/competitive/src/tools/fastio.rs (line 740)
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    }
Source

unsafe fn fetch_ud4(&mut self) -> u16

Examples found in repository?
crates/competitive/src/tools/fastio.rs (line 138)
137    pub unsafe fn u8(&mut self) -> u8 {
138        unsafe { self.fetch_ud4() as u8 }
139    }
Source

unsafe fn fetch_ud8(&mut self) -> u32

Examples found in repository?
crates/competitive/src/tools/fastio.rs (line 143)
142    pub unsafe fn u16(&mut self) -> u16 {
143        unsafe { self.fetch_ud8() as u16 }
144    }
145
146    /// 0..=99_999_999
147    #[inline]
148    pub unsafe fn u32_small(&mut self) -> u32 {
149        unsafe { self.fetch_ud8() }
150    }
Source

pub unsafe fn u8(&mut self) -> u8

Examples found in repository?
crates/competitive/src/tools/fastio.rs (line 474)
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    }
Source

pub unsafe fn u16(&mut self) -> u16

Examples found in repository?
crates/competitive/src/tools/fastio.rs (line 487)
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    }
Source

pub unsafe fn u32_small(&mut self) -> u32

0..=99_999_999

Source

pub unsafe fn u32(&mut self) -> u32

Examples found in repository?
crates/competitive/src/tools/fastio.rs (line 500)
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    }
Source

pub unsafe fn u64(&mut self) -> u64

Examples found in repository?
crates/competitive/src/tools/fastio.rs (line 466)
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    }
Source

pub unsafe fn u128(&mut self) -> u128

Examples found in repository?
crates/competitive/src/tools/fastio.rs (line 529)
525    pub unsafe fn i128(&mut self) -> i128 {
526        unsafe {
527            let b = *self.ptr == b'-';
528            self.ptr = self.ptr.add(b as usize);
529            let mut x = self.u128() as i128;
530            if b {
531                x = x.wrapping_neg();
532            }
533            x
534        }
535    }
Source

pub unsafe fn usize(&mut self) -> usize

Source

pub unsafe fn i8(&mut self) -> i8

Source

pub unsafe fn i16(&mut self) -> i16

Source

pub unsafe fn i32(&mut self) -> i32

Source

pub unsafe fn i64(&mut self) -> i64

Examples found in repository?
crates/competitive/src/tools/fastio.rs (line 539)
538    pub unsafe fn isize(&mut self) -> isize {
539        unsafe { self.i64() as isize }
540    }
Source

pub unsafe fn i128(&mut self) -> i128

Source

pub unsafe fn isize(&mut self) -> isize

Source

pub unsafe fn byte(&mut self) -> u8

Source

pub unsafe fn bytes<'a>(&mut self) -> &'a [u8] ⓘ

Examples found in repository?
crates/competitive/src/tools/fast_scanner.rs (line 21)
20    fn next_token(&mut self) -> Option<&str> {
21        Some(unsafe { from_utf8_unchecked(self.bytes()) })
22    }
More examples
Hide additional examples
crates/competitive/src/tools/fastio.rs (line 625)
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    }
Source

pub unsafe fn parse<T>(&mut self) -> T
where T: FromStr,

Trait Implementations§

Source§

impl ScanSource for FastInput

Source§

fn skip_whitespace(&mut self)

Skips separators without consuming the next token.
Source§

fn next_token(&mut self) -> Option<&str>

Reads a token under the source’s input requirements. Checked sources return None at EOF; unchecked sources require available input.
Source§

fn read_u8(&mut self) -> Option<u8>

Source§

fn read_u16(&mut self) -> Option<u16>

Source§

fn read_u32(&mut self) -> Option<u32>

Source§

fn read_u64(&mut self) -> Option<u64>

Source§

fn read_u128(&mut self) -> Option<u128>

Source§

fn read_usize(&mut self) -> Option<usize>

Source§

fn read_i8(&mut self) -> Option<i8>

Source§

fn read_i16(&mut self) -> Option<i16>

Source§

fn read_i32(&mut self) -> Option<i32>

Source§

fn read_i64(&mut self) -> Option<i64>

Source§

fn read_i128(&mut self) -> Option<i128>

Source§

fn read_isize(&mut self) -> Option<isize>

Source§

fn scan<T: Scan>(&mut self) -> T::Output

Panics if reading fails.
Source§

fn mscan<T: MarkedScan>(&mut self, marker: T) -> T::Output

Panics if reading fails.
Source§

fn scan_vec<T: Scan>(&mut self, size: usize) -> Vec<T::Output>

Source§

fn iter<T: Scan>(&mut self) -> ScannerIter<'_, Self, T> ⓘ

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> ToArrayVecScalar for T

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.