Skip to main content

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(Debug)]
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    pub fn len(&self) -> usize {
33        self.buffer.len()
34    }
35
36    pub fn is_empty(&self) -> bool {
37        self.len() == 0
38    }
39    /// The associated iterator call 'next' fills the buffer and returns the
40    /// individual byte-by-byte values.  This function returns and clears the
41    /// buffer as a consecutive block, up to 'len' items.
42    pub fn consume_read_buffer_up_to(&mut self, len: usize) -> Vec<u8> {
43        let len = min(len, self.buffer.len());
44        self.buffer.drain(0..len).collect()
45    }
46
47    /// The associated iterator call 'next' fills the buffer and returns the
48    /// individual byte-by-byte values. This function returns the entire read buffer.
49    pub fn consume_read_buffer(&mut self) -> VecDeque<u8> {
50        core::mem::take(&mut self.buffer)
51    }
52
53    /// Removes the specified range and throws it away.
54    pub fn drain<R: RangeBounds<usize>>(&mut self, range: R) {
55        self.buffer.drain(range);
56    }
57}
58
59impl<T: Read> Read for Buffer<T> {
60    fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
61        if self.buffer.is_empty() {
62            let mut buf: [u8; 4096] = [0; 4096];
63            let read = self.reader.read(&mut buf)?;
64            self.buffer.extend(buf.get(0..read).unwrap_or_default());
65        }
66        let read = self.buffer.read(buf)?;
67        Ok(read)
68    }
69}
70
71impl<T: Read> Iterator for Buffer<T> {
72    type Item = u8;
73
74    fn next(&mut self) -> Option<Self::Item> {
75        let mut buf: [u8; 1] = [0; 1];
76        let Ok(val) = self.reader.read(&mut buf) else {
77            return None;
78        };
79        if val == 1 {
80            self.buffer.push_back(buf[0]);
81            return Some(buf[0]);
82        }
83        None
84    }
85}
86
87impl<T: Read> BufRead for Buffer<T> {
88    fn fill_buf(&mut self) -> std::io::Result<&[u8]> {
89        let buf = self.reader.fill_buf()?;
90        let len = buf.len();
91        self.buffer.extend(buf.iter());
92        self.reader.consume(len);
93        Ok(self.buffer.make_contiguous())
94    }
95
96    fn consume(&mut self, amt: usize) {
97        self.consume_read_buffer_up_to(amt);
98    }
99}