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}