irox_tools/read/
buffer.rs

1// SPDX-License-Identifier: MIT
2// Copyright 2025 IROX Contributors
3//
4extern crate alloc;
5
6use alloc::collections::VecDeque;
7use core::cmp::min;
8use core::ops::RangeBounds;
9use std::io::{BufRead, BufReader, Read};
10
11///
12/// An effective, infinite cached buffer.  What [`BufRead`] and [`BufReader`]
13/// would be if they weren't backed by a fixed buffer.
14///
15/// Calls to `read()` and `next()` fill the internal buffer & peek the data, but do not consume it.  Call either
16/// `drain()` or one of the `consume_*` functions.
17#[derive()]
18pub struct Buffer<T> {
19    reader: BufReader<T>,
20    buffer: VecDeque<u8>,
21}
22
23impl<T: Read> Buffer<T> {
24    /// Creates a new buffer
25    pub fn new(reader: T) -> Self {
26        Buffer {
27            reader: BufReader::new(reader),
28            buffer: VecDeque::new(),
29        }
30    }
31
32    /// The associated iterator call 'next' fills the buffer and returns the
33    /// individual byte-by-byte values.  This function returns and clears the
34    /// buffer as a consecutive block, up to 'len' items.
35    pub fn consume_read_buffer_up_to(&mut self, len: usize) -> Vec<u8> {
36        let len = min(len, self.buffer.len());
37        self.buffer.drain(0..len).collect()
38    }
39
40    /// The associated iterator call 'next' fills the buffer and returns the
41    /// individual byte-by-byte values. This function returns the entire read buffer.
42    pub fn consume_read_buffer(&mut self) -> VecDeque<u8> {
43        core::mem::take(&mut self.buffer)
44    }
45
46    /// Removes the specified range and throws it away.
47    pub fn drain<R: RangeBounds<usize>>(&mut self, range: R) {
48        self.buffer.drain(range);
49    }
50}
51
52impl<T: Read> Read for Buffer<T> {
53    fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
54        if self.buffer.is_empty() {
55            let mut buf: [u8; 4096] = [0; 4096];
56            let read = self.reader.read(&mut buf)?;
57            self.buffer.extend(buf.get(0..read).unwrap_or_default());
58        }
59        let read = self.buffer.read(buf)?;
60        Ok(read)
61    }
62}
63
64impl<T: Read> Iterator for Buffer<T> {
65    type Item = u8;
66
67    fn next(&mut self) -> Option<Self::Item> {
68        let mut buf: [u8; 1] = [0; 1];
69        let Ok(val) = self.reader.read(&mut buf) else {
70            return None;
71        };
72        if val == 1 {
73            self.buffer.push_back(buf[0]);
74            return Some(buf[0]);
75        }
76        None
77    }
78}
79
80impl<T: Read> BufRead for Buffer<T> {
81    fn fill_buf(&mut self) -> std::io::Result<&[u8]> {
82        let buf = self.reader.fill_buf()?;
83        let len = buf.len();
84        self.buffer.extend(buf.iter());
85        self.reader.consume(len);
86        Ok(self.buffer.make_contiguous())
87    }
88
89    fn consume(&mut self, amt: usize) {
90        self.consume_read_buffer_up_to(amt);
91    }
92}