use std::io::{ErrorKind, Read};
use std::time::Instant;
use crate::util::ByteFormat;
pub(crate) struct DoggedReader<R> {
inner: R,
}
impl<R> DoggedReader<R> {
pub fn new(inner: R) -> Self {
Self { inner }
}
}
impl<R: Read> Read for DoggedReader<R> {
fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
loop {
match self.inner.read(buf) {
Ok(n) => return Ok(n),
Err(ref e) if e.kind() == ErrorKind::Interrupted => (),
Err(e) => return Err(e),
}
}
}
}
#[derive(Debug)]
pub(crate) struct VerboseReader<R> {
inner: R,
timeout: f32,
}
impl<R> VerboseReader<R> {
pub fn new(inner: R, timeout: u8) -> Self {
Self {
inner,
timeout: timeout as f32 * 0.1,
}
}
}
impl<R: Read> Read for VerboseReader<R> {
fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
let start_time = Instant::now();
let mut retries = 0;
let mut interrupts = 0;
loop {
#[allow(clippy::print_stdout)]
match self.inner.read(buf) {
Ok(0) => {
let duration = start_time.elapsed().as_secs_f32();
if duration < self.timeout {
retries += 1;
continue;
}
print!(
"read: 0 bytes, {:.1}s timeout, {} retries, {} interrupts\r\n",
duration, retries, interrupts
);
return Ok(0);
}
Ok(n) => {
print!(
"read: {:2} bytes, {} retries, {} interrupts, '{}'\r\n",
n,
retries,
interrupts,
ByteFormat::Nicely(&buf[..n])
);
return Ok(n);
}
Err(ref e) if e.kind() == ErrorKind::Interrupted => {
interrupts += 1;
}
Err(e) => {
print!(
"read: {:?}, {} retries, {} interrupts\r\n",
&e, retries, interrupts
);
return Err(e);
}
}
}
}
}