Skip to main content

easy_io/
input_reader.rs

1/*
2  A fast and dead-simple reader for competitive programming in Rust
3
4  Author: Axel Lindeberg, github.com/AxlLind
5  Repository: https://github.com/AxlLind/easy_io
6  License: MIT
7  2020
8*/
9#![allow(dead_code)]
10use std::io::{self, Read, Stdin};
11use std::fs::File;
12
13pub struct InputReader<R: Read> {
14  reader: R,
15  buf: Vec<u8>,
16  bytes_read: usize,
17  current_index: usize,
18}
19
20impl InputReader<Stdin> {
21  pub fn new() -> Self {
22    Self::from_reader(io::stdin())
23  }
24}
25
26impl InputReader<File> {
27  pub fn from_file(path: &str) -> Self {
28    Self::from_reader(File::open(path).unwrap())
29  }
30}
31
32impl<R: Read> InputReader<R> {
33  pub fn from_reader(reader: R) -> Self {
34    Self {
35      reader,
36      buf: vec![0; 1 << 16],
37      bytes_read: 0,
38      current_index: 0,
39    }
40  }
41
42  pub fn next<T: InputReadable>(&mut self) -> T {
43    T::from_input(self)
44  }
45
46  pub fn next_line(&mut self) -> String {
47    self.assert_has_more();
48    let mut line = String::new();
49    while self.peek() != '\n' {
50      line.push(self.peek());
51      self.consume();
52      if !self.has_more() { break; }
53    }
54    self.consume(); // consume newline
55    line
56  }
57
58  pub fn has_more(&mut self) -> bool {
59    if self.current_index >= self.bytes_read {
60      self.bytes_read = self.reader.read(&mut self.buf[..]).unwrap();
61      self.current_index = 0
62    }
63    self.bytes_read > 0
64  }
65
66  pub fn set_buf_size(&mut self, buf_size: usize) {
67    self.buf.resize(buf_size, 0);
68  }
69}
70
71// private methods
72impl<R: Read> InputReader<R> {
73  fn peek(&self) -> char { self.buf[self.current_index] as char }
74
75  fn consume(&mut self) { self.current_index += 1; }
76
77  fn assert_has_more(&mut self) {
78    assert!(self.has_more(), "InputReader: Reached end of input!");
79  }
80
81  fn pop_digit(&mut self) -> u64 {
82    let c = self.peek();
83    self.consume();
84    c as u64 - '0' as u64
85  }
86
87  fn consume_until<F: Fn(char) -> bool>(&mut self, test: F) {
88    loop {
89      self.assert_has_more();
90      if test(self.peek()) { return; }
91      self.consume();
92    }
93  }
94
95  fn consume_until_sign(&mut self) -> i64 {
96    loop {
97      self.consume_until(|c| c.is_ascii_digit() || c == '-');
98      if self.peek() != '-' { return 1; }
99
100      self.consume();
101      self.assert_has_more();
102      if self.peek().is_ascii_digit() { return -1; }
103    }
104  }
105}
106
107pub trait InputReadable {
108  fn from_input<R: Read>(input: &mut InputReader<R>) -> Self;
109}
110
111impl InputReadable for u64 {
112  fn from_input<R: Read>(input: &mut InputReader<R>) -> Self {
113    input.consume_until(|c| c.is_ascii_digit());
114    let mut num = 0;
115    while input.peek().is_ascii_digit() {
116      num = num * 10 + input.pop_digit();
117      if !input.has_more() { break; }
118    }
119    num
120  }
121}
122
123impl InputReadable for i64 {
124  fn from_input<R: Read>(input: &mut InputReader<R>) -> Self {
125    let sign = input.consume_until_sign();
126    u64::from_input(input) as i64 * sign
127  }
128}
129
130impl InputReadable for f64 {
131  fn from_input<R: Read>(input: &mut InputReader<R>) -> Self {
132    let sign = input.consume_until_sign() as f64;
133    let mut num = 0.0;
134    while input.peek().is_ascii_digit() {
135      num = num * 10.0 + input.pop_digit() as f64;
136      if !input.has_more() { break; }
137    }
138
139    let mut factor = 1.0;
140    if input.peek() == '.' {
141      input.consume();
142      while input.has_more() && input.peek().is_ascii_digit() {
143        num = num * 10.0 + input.pop_digit() as f64;
144        factor *= 10.0;
145      }
146    }
147    sign * num / factor
148  }
149}
150
151impl InputReadable for String {
152  fn from_input<R: Read>(input: &mut InputReader<R>) -> Self {
153    input.consume_until(|c| c.is_ascii_graphic());
154    let mut word = String::new();
155    while input.peek().is_ascii_graphic() {
156      word.push(input.peek());
157      input.consume();
158      if !input.has_more() { break; }
159    }
160    word
161  }
162}
163
164impl InputReadable for char {
165  fn from_input<R: Read>(input: &mut InputReader<R>) -> Self {
166    input.consume_until(|c| c.is_ascii_graphic());
167    let c = input.peek();
168    input.consume();
169    c
170  }
171}
172
173macro_rules! impl_readable_from {
174  ($A:ty, [$T:ty]) => {
175    impl InputReadable for $T {
176      fn from_input<R: Read>(input: &mut InputReader<R>) -> Self {
177        <$A>::from_input(input) as $T
178      }
179    }
180  };
181  ($A:ty, [$T:ty, $($Ts:ty),+]) => {
182    impl_readable_from!{$A, [$T]}
183    impl_readable_from!{$A, [$($Ts),*]}
184  };
185}
186impl_readable_from!{ u64, [u32, u16, u8, usize] }
187impl_readable_from!{ i64, [i32, i16, i8, isize] }
188impl_readable_from!{ f64, [f32] }