1use std::fs::File;
2use std::io::{BufRead, BufReader, Error, ErrorKind, Read, Stdin};
3use std::path::Path;
4
5pub type FileReader = BufReader<File>;
6pub type StdinReader = BufReader<Stdin>;
7
8pub enum BufferedInput {
10 File(FileReader),
11 Stdin(StdinReader),
12}
13
14pub fn file_reader<P: AsRef<Path>>(path: P) -> std::io::Result<FileReader> {
15 let file = File::open(path)?;
16 let meta = file.metadata()?;
17
18 if meta.is_dir() {
19 return Err(Error::new(ErrorKind::Other, "Is a directory"));
20 }
21
22 let returned_reader = BufReader::new(file);
23
24 Ok(returned_reader)
25}
26
27pub fn stdin_reader() -> StdinReader {
28 BufReader::new(std::io::stdin())
29}
30
31impl BufferedInput {
32 pub fn unwrapped_lines(self) -> impl Iterator<Item = String> {
35 self.lines().map(Result::unwrap)
36 }
37}
38
39impl Read for BufferedInput {
40 fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
41 match self {
42 Self::File(file_reader) => file_reader.read(buf),
43 Self::Stdin(stdin_reader) => stdin_reader.read(buf),
44 }
45 }
46}
47
48impl BufRead for BufferedInput {
49 fn fill_buf(&mut self) -> std::io::Result<&[u8]> {
50 match self {
51 Self::File(file_reader) => file_reader.fill_buf(),
52 Self::Stdin(stdin_reader) => stdin_reader.fill_buf(),
53 }
54 }
55
56 fn consume(&mut self, amt: usize) {
57 match self {
58 Self::File(file_reader) => file_reader.consume(amt),
59 Self::Stdin(stdin_reader) => stdin_reader.consume(amt),
60 };
61 }
62}