use core::fmt;
use std::{
io::{Seek, Write},
thread,
time::Duration,
};
pub struct DelayWriter<W: Write> {
inner: W,
delay: Duration,
}
impl<W: Write> DelayWriter<W> {
pub const fn new(writer: W, delay: Duration) -> Self {
Self {
inner: writer,
delay,
}
}
}
impl<W: Write> Write for DelayWriter<W> {
fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
for (index, line) in buf.split(|byte| *byte == b'\n').enumerate() {
if index != 0 {
self.inner.write_all(&[b'\n'])?;
}
self.inner.write_all(line)?;
thread::sleep(self.delay);
}
Ok(buf.len())
}
fn flush(&mut self) -> std::io::Result<()> {
self.inner.flush()
}
}
impl<W: Write + fmt::Debug> fmt::Debug for DelayWriter<W> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("DelayWriter")
.field("inner", &self.inner)
.field("delay", &self.delay)
.finish()
}
}
impl<W: Write + Seek> Seek for DelayWriter<W> {
fn seek(&mut self, pos: std::io::SeekFrom) -> std::io::Result<u64> {
self.inner.seek(pos)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn new() {
let out = std::io::stdout();
let writer = DelayWriter::new(out, Duration::from_millis(500));
assert_eq!(Duration::from_millis(500), writer.delay);
}
#[test]
fn write() {
let mut buf = Vec::new();
let mut writer = DelayWriter::new(&mut buf, Duration::from_millis(500));
_ = writer.write(b"Hello\nWorld");
assert_eq!("Hello\nWorld", String::from_utf8(buf).unwrap());
}
#[test]
fn bytes_written() {
let mut buf = Vec::new();
let mut writer = DelayWriter::new(&mut buf, Duration::from_millis(500));
let result = writer.write(b"Hello\nWorld");
assert_eq!(11, result.unwrap());
}
}