read_collection/read_back/buf_read_backer/
mod.rs

1mod buffer;
2
3use std::io::BufReader;
4
5use crate::{BufReadBack, ReadBack, DEFAULT_BUF_SIZE};
6
7use self::buffer::Buffer;
8
9/// The `BufReadBacker<R>` struct adds buffering to any [`ReadBack`]er.
10///
11/// It's basically the same as `BufReader` just for reading back instead of forward.
12///
13/// # Examples
14/// ```no_run
15/// use std::io::{BufReader, Read};
16/// use std::fs::File;
17/// use read_collection::{BufReadBacker, ReadBack};
18///
19/// fn main() -> std::io::Result<()> {
20///     let file = File::open("some/path")?;
21///     let mut reader = BufReader::new(file);
22///
23///     let mut buffer = Vec::new();
24///     reader.read(&mut buffer).unwrap();
25///
26///
27///     // let's read the stuff back in
28///     let mut buffer2 = Vec::new();
29///     let mut reader = BufReadBacker::from(reader);
30///     reader.read_back(&mut buffer2)?;
31///
32///     assert_eq!(buffer, buffer2);
33///     Ok(())
34/// }
35/// ```
36#[derive(Debug)]
37pub struct BufReadBacker<R> {
38    inner: R,
39    buf: Buffer,
40}
41
42impl<R> BufReadBacker<R> {
43    /// Returns a reference to the internally buffered data.
44    ///
45    /// Unlike [read_back_fill_buf], this will not attempt to fill the buffer if it is empty.
46    ///
47    /// # Example
48    /// ```no_run
49    /// use read_collection::{BufReadBacker, BufReadBack};
50    /// use std::fs::File;
51    ///
52    /// fn main() -> std::io::Result<()> {
53    ///     let f = File::open("log.txt")?;
54    ///     let mut reader = BufReadBacker::new(f);
55    ///     assert!(reader.buffer().is_empty());
56    ///
57    ///     if reader.read_back_fill_buf()?.len() > 0 {
58    ///         assert!(!reader.buffer().is_empty());
59    ///     }
60    ///     Ok(())
61    /// }
62    /// ```
63    ///
64    /// [read_back_fill_buf]: BufReadBack::read_back_fill_buf
65    pub fn buffer(&self) -> &[u8] {
66        self.buf.buffer()
67    }
68
69    /// Gets a reference to the underlying reader.
70    ///
71    /// It is inadvisable to directly read from the underlying reader.
72    ///
73    /// # Example
74    /// ```no_run
75    /// use read_collection::BufReadBacker;
76    /// use std::fs::File;
77    ///
78    /// fn main() -> std::io::Result<()> {
79    ///     let f1 = File::open("log.txt")?;
80    ///     let reader = BufReadBacker::new(f1);
81    ///
82    ///     let f2 = reader.get_ref();
83    ///     Ok(())
84    /// }
85    /// ```
86    pub fn get_ref(&self) -> &R {
87        &self.inner
88    }
89
90    /// Gets a mutable reference to the underlying reader.
91    ///
92    /// It is inadvisable to directly read from the underlying reader.
93    ///
94    /// # Example
95    /// ```no_run
96    /// use read_collection::BufReadBacker;
97    /// use std::fs::File;
98    ///
99    /// fn main() -> std::io::Result<()> {
100    ///     let f1 = File::open("log.txt")?;
101    ///     let mut reader = BufReadBacker::new(f1);
102    ///
103    ///     let f2 = reader.get_mut();
104    ///     Ok(())
105    /// }
106    /// ```
107    pub fn get_mut(&mut self) -> &mut R {
108        &mut self.inner
109    }
110
111    /// Returns the number of bytes the internal buffer can hold at once.
112    ///
113    /// # Example
114    /// ```
115    /// use read_collection::BufReadBacker;
116    ///
117    /// fn main() {
118    ///     let data: [u8; 5] = [1, 2, 3, 4, 5];
119    ///     let reader = BufReadBacker::with_capacity(42, data.as_slice());
120    ///
121    ///     assert_eq!(reader.capacity(), 42);
122    /// }
123    /// ````
124    pub fn capacity(&self) -> usize {
125        self.buf.capacity()
126    }
127
128    /// Unwraps this `BufReadBacker<R>`, returning the underlying reader.
129    ///
130    /// Note that any leftover data in the internal buffer is lost. Therefore, a following read from the underlying reader may lead to data loss.
131    ///
132    /// # Example
133    /// ```
134    /// use read_collection::{BufReadBacker, ReadBack};
135    ///
136    /// fn main() {
137    ///     let data: [u8; 5] = [1, 2, 3, 4, 5];
138    ///     let mut buffer: [u8; 5] = [0; 5];
139    ///
140    ///     let mut reader = BufReadBacker::new(data.as_slice());
141    ///     assert_eq!(reader.read_back(&mut buffer).ok(), Some(5));
142    ///
143    ///     let mut inner = reader.into_inner();
144    ///     // note how the inner reference is "empty" now.
145    ///     assert_eq!(inner.read_back(&mut buffer).ok(), Some(0));
146    /// }
147    /// ```
148    pub fn into_inner(self) -> R {
149        self.inner
150    }
151
152    pub(crate) fn discard_buffer(&mut self) {
153        self.buf.discard_buffer();
154    }
155}
156
157impl<R: ReadBack> BufReadBacker<R> {
158    /// Creates a new `BufReadBacker<R>` with a default buffer capacity. The default is currently 8 KiB (or 512 B for bare metal platforms), but may change
159    /// in the future.
160    ///
161    /// # Example
162    /// ```no_run
163    /// use read_collection::BufReadBacker;
164    /// use std::fs::File;
165    ///
166    /// fn main() -> std::io::Result<()> {
167    ///     let file = File::open("amogus.txt")?;
168    ///     let reader = BufReadBacker::new(file);
169    ///     Ok(())
170    /// }
171    /// ```
172    pub fn new(inner: R) -> Self {
173        Self::with_capacity(DEFAULT_BUF_SIZE, inner)
174    }
175
176    /// Creates a new `BufReadBacker<R>` with the specified buffer capacity.
177    ///
178    /// # Examples
179    /// ```no_run
180    /// use read_collection::BufReadBacker;
181    /// use std::fs::File;
182    ///
183    /// fn main() -> std::io::Result<()> {
184    ///     let nice = File::open("amogus.txt")?;
185    ///     let reader = BufReadBacker::with_capacity(69, nice);
186    ///     Ok(())
187    /// }
188    /// ```
189    pub fn with_capacity(capacity: usize, inner: R) -> Self {
190        Self {
191            inner,
192            buf: Buffer::with_capacity(capacity),
193        }
194    }
195}
196
197impl<R: ReadBack> ReadBack for BufReadBacker<R> {
198    fn read_back(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
199        if self.buf.pos() == self.buf.filled() && buf.len() >= self.capacity() {
200            self.discard_buffer();
201            return self.inner.read_back(buf);
202        }
203
204        let mut rem = self.read_back_fill_buf()?;
205        let nread = rem.read_back(buf)?;
206        self.read_back_consume(nread);
207        Ok(nread)
208    }
209}
210
211impl<R: ReadBack> BufReadBack for BufReadBacker<R> {
212    fn read_back_fill_buf(&mut self) -> std::io::Result<&[u8]> {
213        self.buf.fill_buf(&mut self.inner)
214    }
215
216    fn read_back_consume(&mut self, amt: usize) {
217        self.buf.consume(amt)
218    }
219}
220
221impl<R: ReadBack> From<BufReader<R>> for BufReadBacker<R> {
222    fn from(value: BufReader<R>) -> Self {
223        Self::new(value.into_inner())
224    }
225}
226
227#[cfg(test)]
228mod tests {
229    use super::*;
230
231    #[test]
232    fn general() {
233        let data: [u8; 3] = [1, 2, 3];
234        let mut buffer: [u8; 3] = [0; 3];
235
236        let mut buf_reader = BufReadBacker::new(data.as_slice());
237
238        assert_eq!(buf_reader.read_back(&mut buffer).ok(), Some(data.len()));
239        assert_eq!(buffer, data);
240    }
241
242    #[test]
243    fn small_capacity() {
244        let data: [u8; 4] = [1, 2, 3, 4];
245        let mut buffer: [u8; 2] = [0; 2];
246
247        let mut buf_reader = BufReadBacker::with_capacity(2, data.as_slice());
248
249        assert_eq!(buf_reader.read_back(&mut buffer).ok(), Some(2));
250        assert_eq!(buffer, data[2..4]);
251
252        assert_eq!(buf_reader.read_back(&mut buffer).ok(), Some(2));
253        assert_eq!(buffer, data[..2]);
254    }
255}