use std::io;
use std::io::Read;
pub struct AtomicReader<'a> {
buf: Vec<u8>,
reader: &'a mut dyn Read,
}
impl<'a> AtomicReader<'a> {
#[must_use]
pub fn new(reader: &mut dyn Read) -> AtomicReader<'_> {
AtomicReader {
buf: Vec::new(),
reader,
}
}
}
impl<'a> Read for AtomicReader<'a> {
fn read(&mut self, out: &mut [u8]) -> io::Result<usize> {
let buf_len = self.buf.len();
let out_len = out.len();
if buf_len >= out_len {
out.copy_from_slice(&self.buf[0..out_len]);
self.buf = self.buf[out_len..].to_vec();
Ok(out_len)
} else if buf_len > 0 {
out[0..buf_len].copy_from_slice(&self.buf);
let size = self.reader.read(&mut out[buf_len..])?;
if size == 0 {
Err(io::Error::new(io::ErrorKind::NotConnected, "Disconnected"))
} else if buf_len + size < out_len {
self.buf.extend_from_slice(&out[buf_len..buf_len + size]);
Err(io::Error::new(io::ErrorKind::TimedOut, "Incomplete read"))
} else {
self.buf.clear();
Ok(out_len)
}
} else {
let size = self.reader.read(out)?;
if size == 0 {
Err(io::Error::new(io::ErrorKind::NotConnected, "Disconnected"))
} else if size < out_len {
self.buf.extend_from_slice(&out[0..size]);
Err(io::Error::new(io::ErrorKind::TimedOut, "Incomplete read"))
} else {
Ok(out_len)
}
}
}
}
#[cfg(test)]
mod test {
use super::*;
use pretty_assertions::assert_eq;
use std::io::Cursor;
#[test]
fn read() {
let mut o = [0; 10];
let v = vec![0; 10];
let mut c = Cursor::new(&v);
let mut r = AtomicReader::new(&mut c);
assert_eq!(r.read(&mut o).unwrap(), 10);
let v = vec![0; 12];
let mut c = Cursor::new(&v);
let mut r = AtomicReader::new(&mut c);
assert_eq!(r.read(&mut o).unwrap(), 10);
let v = vec![0; 0];
let mut c = Cursor::new(&v);
let mut r = AtomicReader::new(&mut c);
r.buf = vec![1; 10];
assert_eq!(r.read(&mut o).unwrap(), 10);
assert_eq!(r.buf.len(), 0);
let v = vec![0; 6];
let mut c = Cursor::new(&v);
let mut r = AtomicReader::new(&mut c);
r.buf = vec![1; 4];
assert_eq!(r.read(&mut o).unwrap(), 10);
assert_eq!(o, [1, 1, 1, 1, 0, 0, 0, 0, 0, 0]);
let v = vec![0; 0];
let mut c = Cursor::new(&v);
let mut r = AtomicReader::new(&mut c);
assert!(r.read(&mut o).is_err());
let v = vec![0; 9];
let mut c = Cursor::new(&v);
let mut r = AtomicReader::new(&mut c);
assert!(r.read(&mut o).is_err());
assert_eq!(r.buf.len(), 9);
let v = vec![0; 0];
let mut c = Cursor::new(&v);
let mut r = AtomicReader::new(&mut c);
r.buf = vec![1; 9];
assert!(r.read(&mut o).is_err());
assert_eq!(r.buf.len(), 9);
let v = vec![0; 6];
let mut c = Cursor::new(&v);
let mut r = AtomicReader::new(&mut c);
r.buf = vec![1; 3];
assert!(r.read(&mut o).is_err());
assert_eq!(r.buf.len(), 9);
}
}