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}