use std::io::BufReader;
use std::io::Error;
use std::io::Read;
use ringbuffer::AllocRingBuffer;
use ringbuffer::RingBuffer;
pub struct ByteReader<R: Read> {
reader: BufReader<R>,
input_byte_counter: u64,
peeked_byte: Option<u8>,
last_byte: Option<u8>,
captured_bytes: AllocRingBuffer<u8>,
}
impl<R: Read> ByteReader<R> {
pub fn new(reader: R) -> Self {
Self {
reader: BufReader::new(reader),
input_byte_counter: 0,
peeked_byte: None,
last_byte: None,
captured_bytes: AllocRingBuffer::new(1024),
}
}
pub fn read_byte(&mut self) -> Result<u8, Error> {
if let Some(byte) = self.peeked_byte.take() {
return Ok(byte);
}
let mut byte = [0; 1];
self.reader.read_exact(&mut byte)?;
self.input_byte_counter += 1;
let byte = byte[0];
self.last_byte = Some(byte);
self.captured_bytes.push(byte);
Ok(byte)
}
pub fn peek_byte(&mut self) -> Result<u8, Error> {
let byte = if let Some(byte) = self.peeked_byte {
byte
} else {
let byte = self.read_byte()?;
self.peeked_byte = Some(byte);
byte
};
Ok(byte)
}
pub fn input_byte_counter(&self) -> u64 {
self.input_byte_counter
}
pub fn captured_bytes(&self) -> Vec<u8> {
self.captured_bytes.to_vec()
}
pub fn last_byte(&self) -> Option<u8> {
self.last_byte
}
}
#[cfg(test)]
mod tests {
mod for_reading {
use crate::rw::byte_reader::ByteReader;
#[test]
fn it_should_read_one_byte_from_the_input_consuming_it() {
let input = vec![b'l', b'e'];
let mut byte_reader = ByteReader::new(input.as_slice());
assert_eq!(byte_reader.read_byte().unwrap(), b'l');
assert_eq!(byte_reader.read_byte().unwrap(), b'e');
}
#[test]
fn it_should_fail_when_there_are_no_more_bytes_to_read() {
let input = vec![b'l', b'e'];
let mut byte_reader = ByteReader::new(input.as_slice());
assert_eq!(byte_reader.read_byte().unwrap(), b'l');
assert_eq!(byte_reader.read_byte().unwrap(), b'e');
assert!(byte_reader.read_byte().is_err());
}
#[test]
fn it_should_increase_the_input_byte_counter_by_one_when_reading_a_new_byte() {
let input = vec![b'l'];
let mut byte_reader = ByteReader::new(input.as_slice());
assert_eq!(byte_reader.read_byte().unwrap(), b'l');
assert_eq!(byte_reader.input_byte_counter(), 1);
}
#[test]
fn it_should_return_the_last_read_byte() {
let input = vec![b'l', b'e'];
let mut byte_reader = ByteReader::new(input.as_slice());
byte_reader.read_byte().unwrap();
byte_reader.read_byte().unwrap();
assert_eq!(byte_reader.last_byte(), Some(b'e'));
}
}
mod for_peeking {
use crate::rw::byte_reader::ByteReader;
#[test]
fn it_should_allow_peeking_one_byte_from_the_input_without_consuming_it() {
let input = vec![b'l'];
let mut byte_reader = ByteReader::new(input.as_slice());
assert_eq!(byte_reader.peek_byte().unwrap(), b'l');
assert_eq!(byte_reader.peek_byte().unwrap(), b'l');
}
#[test]
fn when_reading_a_byte_it_should_use_a_peeked_one_if_there_is() {
let input = vec![b'l'];
let mut byte_reader = ByteReader::new(input.as_slice());
assert_eq!(byte_reader.peek_byte().unwrap(), b'l');
assert_eq!(byte_reader.read_byte().unwrap(), b'l');
}
#[test]
fn when_reading_a_byte_it_should_use_a_peeked_one_and_discard_it_after_using_it() {
let input = vec![b'l'];
let mut byte_reader = ByteReader::new(input.as_slice());
assert_eq!(byte_reader.peek_byte().unwrap(), b'l'); assert_eq!(byte_reader.read_byte().unwrap(), b'l'); assert!(byte_reader.peek_byte().is_err()); }
#[test]
fn it_should_increase_the_input_byte_counter_the_first_time_it_peeks_a_new_byte() {
let input = vec![b'l'];
let mut byte_reader = ByteReader::new(input.as_slice());
assert_eq!(byte_reader.peek_byte().unwrap(), b'l');
assert_eq!(byte_reader.input_byte_counter(), 1);
}
#[test]
fn it_should_not_increase_the_input_byte_counter_when_peeking_a_cached_peeked_byte() {
let input = vec![b'l'];
let mut byte_reader = ByteReader::new(input.as_slice());
assert_eq!(byte_reader.peek_byte().unwrap(), b'l');
assert_eq!(byte_reader.input_byte_counter(), 1);
assert_eq!(byte_reader.peek_byte().unwrap(), b'l');
assert_eq!(byte_reader.input_byte_counter(), 1);
}
}
mod for_capturing {
use crate::rw::byte_reader::ByteReader;
#[test]
fn it_should_capture_the_latest_read_byte() {
let input = vec![b'a'];
let mut byte_reader = ByteReader::new(input.as_slice());
byte_reader.read_byte().unwrap();
assert_eq!(byte_reader.captured_bytes(), input);
}
#[test]
fn it_should_capture_1024_bytes_at_the_most() {
let mut part1 = vec![b'a'; 1024];
let part2 = vec![b'b'; 1024];
part1.extend_from_slice(&part2);
let mut byte_reader = ByteReader::new(part1.as_slice());
for _i in 1..=1024 * 2 {
byte_reader.read_byte().unwrap();
}
assert_eq!(byte_reader.captured_bytes(), part2);
}
}
}