use std::io::Write;
#[derive(Clone, PartialEq, Eq, Debug)]
pub struct FileProgress {
pub bytes_finished: u64,
pub bytes_total: u64,
}
pub(crate) struct ProgressWriter<W: Write, F: FnMut(&FileProgress)> {
progress: FileProgress,
inner: W,
progress_report_byte_interval: u64,
bytes_written_since_last_progress_report: u64,
handler: F,
}
impl<W: Write, F: FnMut(&FileProgress)> ProgressWriter<W, F> {
pub fn new(inner: W, handler: F, progress_update_byte_interval: u64, bytes_total: u64) -> Self {
Self {
progress: FileProgress {
bytes_finished: 0,
bytes_total,
},
inner,
progress_report_byte_interval: progress_update_byte_interval,
bytes_written_since_last_progress_report: 0,
handler,
}
}
pub fn into_inner(self) -> (W, FileProgress, F) {
(self.inner, self.progress, self.handler)
}
}
impl<W: Write, F: FnMut(&FileProgress)> Write for ProgressWriter<W, F> {
fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
let inner_write_result = self.inner.write(buf);
if let Ok(bytes_written) = &inner_write_result {
self.progress.bytes_finished += *bytes_written as u64;
self.bytes_written_since_last_progress_report += *bytes_written as u64;
}
if self.bytes_written_since_last_progress_report > self.progress_report_byte_interval {
(self.handler)(&self.progress);
self.bytes_written_since_last_progress_report = 0;
}
inner_write_result
}
fn flush(&mut self) -> std::io::Result<()> {
self.inner.flush()
}
}