codeq/
offset_reader.rs

1use std::io;
2
3/// A reader that tracks the number of bytes read.
4///
5/// This reader wraps any type implementing [`io::Read`] and transparently tracks
6/// the number of bytes read through it. The current offset can be retrieved using
7/// the [`offset()`](Self::offset) method.
8///
9/// Example:
10/// ```rust
11/// # use std::io::Read;
12/// # use codeq::OffsetReader;
13///
14/// let data = b"hello";
15/// let mut reader = OffsetReader::new(data.as_ref());
16/// let mut buf = [0; 3];
17/// reader.read_exact(&mut buf).unwrap();
18/// assert_eq!(reader.offset(), 3);
19/// ```
20pub struct OffsetReader<R> {
21    inner: R,
22    offset: usize,
23}
24
25impl<R: io::Read> OffsetReader<R> {
26    /// Creates a new `OffsetReader` wrapping the provided reader.
27    pub fn new(inner: R) -> Self {
28        Self { inner, offset: 0 }
29    }
30
31    /// Returns the current offset of the reader.
32    ///
33    /// # Returns
34    /// The current offset in bytes
35    pub fn offset(&self) -> usize {
36        self.offset
37    }
38}
39
40impl<R: io::Read> io::Read for OffsetReader<R> {
41    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
42        let n = self.inner.read(buf)?;
43        self.offset += n;
44        Ok(n)
45    }
46}
47
48#[cfg(test)]
49mod tests {
50    use std::io;
51    use std::io::Read;
52
53    use crate::offset_reader::OffsetReader;
54
55    #[test]
56    fn test_offset_reader() -> Result<(), io::Error> {
57        let data = b"hello";
58        let mut reader = OffsetReader::new(data.as_ref());
59        let mut buf = [0; 3];
60        reader.read_exact(&mut buf)?;
61        assert_eq!(reader.offset(), 3);
62
63        let mut buf = [0; 2];
64        reader.read_exact(&mut buf)?;
65        assert_eq!(reader.offset(), 5);
66
67        Ok(())
68    }
69}