template_cp/
iom.rs

1//! # Input and output manager
2
3use std::{io, str};
4
5/// Scanner is a struct that can be used to parse input from a reader.
6///
7/// # Examples
8/// ```
9/// use cp_template::Scanner;
10/// use std::io;
11///
12/// fn main() {
13///     let mut scan = Scanner::new(io::stdin().lock());
14///     let mut out = io::BufWriter::new(io::stdout().lock());
15///     solve(&mut scan, &mut out);
16/// }
17///
18/// fn solve<R: io::BufRead, W: io::Write>(scan: &mut Scanner<R>, out: &mut W) {
19///     let n: usize = scan.tok();
20///     let v: Vec<i32> = (0..n).map(|_| scan.tok()).collect();
21///     writeln!(out, "{} {v:?}", n).ok();
22/// }
23/// ```
24/// ```
25/// use cp_template::Scanner;
26/// use std::io;
27///
28/// fn main() {
29///     let mut scan = read_file("in.txt").unwrap();
30///     let mut out = writer_file("out.txt").unwrap();
31///     solve(&mut scan, &mut out);
32/// }
33///
34/// fn solve<R: io::BufRead, W: io::Write>(scan: &mut Scanner<R>, out: &mut W) {
35///     let n: usize = scan.tok();
36///     let v: Vec<i32> = (0..n).map(|_| scan.tok()).collect();
37///     writeln!(out, "{} {v:?}", n).ok();
38/// }
39/// ```
40pub struct Scanner<R> {
41    reader: R,
42    buf_str: Vec<u8>,
43    buf_iter: str::SplitAsciiWhitespace<'static>,
44}
45
46impl<R: io::BufRead> Scanner<R> {
47    /// Creates a new Scanner.
48    /// # Examples
49    /// ```
50    /// use cp_template::Scanner;
51    ///
52    /// let mut scan = Scanner::new(std::io::stdin().lock());
53    /// ```
54    /// ```
55    /// use cp_template::Scanner;
56    ///
57    /// let file = std::fs::File::open(filename)?;
58    /// Scanner::new(io::BufReader::new(file))
59    /// ```
60    pub fn new(reader: R) -> Self {
61        Self {
62            reader,
63            buf_str: vec![],
64            buf_iter: "".split_ascii_whitespace(),
65        }
66    }
67
68    /// Reads a token.
69    /// # Panics
70    /// Panics if the token can't be parsed or the input is empty.
71    /// # Examples
72    /// ```
73    /// use cp_template::Scanner;
74    ///
75    /// let mut scan = Scanner::new(std::io::stdin().lock());
76    /// let n: i32 = scan.tok();
77    /// ```
78    /// ```
79    /// use cp_template::Scanner;
80    ///
81    /// let mut scan = Scanner::new(std::io::stdin().lock());
82    /// let n = scan.tok::<i32>();
83    /// ```
84    pub fn tok<T: str::FromStr>(&mut self) -> T {
85        loop {
86            if let Some(token) = self.buf_iter.next() {
87                return token.parse().ok().expect("Failed parse");
88            }
89            self.buf_str.clear();
90            self.reader
91                .read_until(b'\n', &mut self.buf_str)
92                .expect("Failed read");
93            self.buf_iter = unsafe {
94                let slice = str::from_utf8_unchecked(&self.buf_str);
95                std::mem::transmute(slice.split_ascii_whitespace())
96            }
97        }
98    }
99}
100
101/// Creates a Scanner from a file
102/// # Examples
103/// ```
104/// use template_cp::file_reader;
105///
106/// let mut scan = file_reader("in.txt").unwrap();
107/// let n: i32 = scan.tok();
108/// ```
109pub fn file_reader(filename: &str) -> io::Result<Scanner<io::BufReader<std::fs::File>>> {
110    let file = std::fs::File::open(filename)?;
111    Ok(Scanner::new(io::BufReader::new(file)))
112}
113
114/// Creates a BufWriter from a file
115/// # Examples
116/// ```
117/// use template_cp::file_writer;
118///
119/// let n = 42;
120/// let mut out = file_writer("out.txt").unwrap();
121/// writeln!(out, "{}", n).ok();
122/// ```
123pub fn file_writer(filename: &str) -> io::Result<io::BufWriter<std::fs::File>> {
124    let file = std::fs::File::create(filename)?;
125    Ok(io::BufWriter::new(file))
126}