1 //! `BufRead` pointer or `BufReader` owned.
2 
3 use std::cmp;
4 use std::fmt;
5 use std::io;
6 use std::io::BufRead;
7 use std::io::BufReader;
8 use std::io::Read;
9 use std::mem::MaybeUninit;
10 
11 use crate::misc::maybe_uninit_write_slice;
12 
13 /// Helper type to simplify `BufReadIter` implementation.
14 pub(crate) enum BufReadOrReader<'a> {
15     BufReader(BufReader<&'a mut dyn Read>),
16     BufRead(&'a mut dyn BufRead),
17 }
18 
19 impl<'a> fmt::Debug for BufReadOrReader<'a> {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result20     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
21         match self {
22             BufReadOrReader::BufReader(..) => write!(f, "BufReader(...)"),
23             BufReadOrReader::BufRead(..) => write!(f, "BufRead(...)"),
24         }
25     }
26 }
27 
28 impl<'a> Read for BufReadOrReader<'a> {
read(&mut self, buf: &mut [u8]) -> Result<usize, io::Error>29     fn read(&mut self, buf: &mut [u8]) -> Result<usize, io::Error> {
30         match self {
31             BufReadOrReader::BufReader(r) => r.read(buf),
32             BufReadOrReader::BufRead(r) => r.read(buf),
33         }
34     }
35 
read_to_end(&mut self, buf: &mut Vec<u8>) -> Result<usize, io::Error>36     fn read_to_end(&mut self, buf: &mut Vec<u8>) -> Result<usize, io::Error> {
37         match self {
38             BufReadOrReader::BufReader(r) => r.read_to_end(buf),
39             BufReadOrReader::BufRead(r) => r.read_to_end(buf),
40         }
41     }
42 
read_exact(&mut self, buf: &mut [u8]) -> Result<(), io::Error>43     fn read_exact(&mut self, buf: &mut [u8]) -> Result<(), io::Error> {
44         match self {
45             BufReadOrReader::BufReader(r) => r.read_exact(buf),
46             BufReadOrReader::BufRead(r) => r.read_exact(buf),
47         }
48     }
49 }
50 
51 impl<'a> BufReadOrReader<'a> {
52     /// Similar to `read_exact` but reads into `MaybeUninit`.
read_exact_uninit( &mut self, buf: &mut [MaybeUninit<u8>], ) -> Result<(), io::Error>53     pub(crate) fn read_exact_uninit(
54         &mut self,
55         buf: &mut [MaybeUninit<u8>],
56     ) -> Result<(), io::Error> {
57         let mut pos = 0;
58         while pos != buf.len() {
59             let fill_buf = match self {
60                 BufReadOrReader::BufReader(r) => r.fill_buf()?,
61                 BufReadOrReader::BufRead(r) => r.fill_buf()?,
62             };
63             if fill_buf.is_empty() {
64                 return Err(io::Error::new(
65                     io::ErrorKind::UnexpectedEof,
66                     "Unexpected end of file",
67                 ));
68             }
69             let consume = cmp::min(fill_buf.len(), buf.len() - pos);
70             maybe_uninit_write_slice(&mut buf[pos..pos + consume], &fill_buf[..consume]);
71             match self {
72                 BufReadOrReader::BufReader(r) => r.consume(consume),
73                 BufReadOrReader::BufRead(r) => r.consume(consume),
74             }
75             pos += consume;
76         }
77         Ok(())
78     }
79 
skip_bytes(&mut self, count: usize) -> Result<(), io::Error>80     pub(crate) fn skip_bytes(&mut self, count: usize) -> Result<(), io::Error> {
81         let mut rem = count;
82         while rem != 0 {
83             let buf = self.fill_buf()?;
84             if buf.is_empty() {
85                 return Err(io::Error::new(
86                     io::ErrorKind::UnexpectedEof,
87                     "Unexpected end of file",
88                 ));
89             }
90             let consume = cmp::min(buf.len(), rem);
91             self.consume(consume);
92             rem -= consume;
93         }
94         Ok(())
95     }
96 }
97 
98 impl<'a> BufRead for BufReadOrReader<'a> {
fill_buf(&mut self) -> Result<&[u8], io::Error>99     fn fill_buf(&mut self) -> Result<&[u8], io::Error> {
100         match self {
101             BufReadOrReader::BufReader(r) => r.fill_buf(),
102             BufReadOrReader::BufRead(r) => r.fill_buf(),
103         }
104     }
105 
consume(&mut self, amt: usize)106     fn consume(&mut self, amt: usize) {
107         match self {
108             BufReadOrReader::BufReader(r) => r.consume(amt),
109             BufReadOrReader::BufRead(r) => r.consume(amt),
110         }
111     }
112 }
113