use binread::io::{Cursor, Error, ErrorKind, Read, Result};
#[derive(Debug)]
struct MalfunctioningEddie<'data> {
error: Option<Error>,
data: Cursor<&'data [u8]>,
}
impl<'data> MalfunctioningEddie<'data> {
fn new(data: &'data [u8]) -> Self {
Self {
error: None,
data: Cursor::new(data),
}
}
fn trigger_fatal_error(&mut self) {
self.error = Some(Error::new(ErrorKind::BrokenPipe, ""));
}
fn trigger_non_fatal_error(&mut self) {
self.error = Some(Error::new(ErrorKind::Interrupted, ""));
}
}
impl Read for MalfunctioningEddie<'_> {
fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
if let Some(error) = self.error.take() {
Err(error)
} else {
self.data.read(buf)
}
}
}
#[test]
fn bytes() {
let mut cursor = MalfunctioningEddie::new(b"\0\x01\x02\x03\x04\x05");
{
let mut bytes = cursor.by_ref().bytes();
assert!(matches!(bytes.next(), Some(Ok(0))));
assert!(matches!(bytes.next(), Some(Ok(1))));
}
cursor.trigger_non_fatal_error();
{
let mut bytes = cursor.by_ref().bytes();
assert!(matches!(bytes.next(), Some(Ok(2))));
}
let mut raw_read_data = [0u8; 2];
assert_eq!(cursor.read(&mut raw_read_data).unwrap(), 2);
assert_eq!(raw_read_data, [3, 4]);
cursor.trigger_fatal_error();
let mut bytes = cursor.bytes();
assert_eq!(
bytes.next().unwrap().unwrap_err().kind(),
ErrorKind::BrokenPipe
);
}
#[test]
fn read_exact() {
let mut cursor = MalfunctioningEddie::new(b"\0\x01\x02\x03\x04\x05");
let mut raw_read_data = [0u8; 2];
cursor.read_exact(&mut raw_read_data).unwrap();
assert_eq!(raw_read_data, [0, 1]);
cursor.trigger_non_fatal_error();
cursor.read_exact(&mut raw_read_data).unwrap();
assert_eq!(raw_read_data, [2, 3]);
cursor.trigger_fatal_error();
assert_eq!(
cursor.read_exact(&mut raw_read_data).unwrap_err().kind(),
ErrorKind::BrokenPipe
);
cursor.by_ref().read_exact(&mut raw_read_data).unwrap();
assert_eq!(raw_read_data, [4, 5]);
assert_eq!(
cursor.read_exact(&mut raw_read_data).unwrap_err().kind(),
ErrorKind::UnexpectedEof
);
}