use std::cmp::min;
use std::sync::{Arc, Mutex};
use crate::pipe::{prelude::*, PipeReader, PipeWriter};
pub struct ProgressPipe {
cur: u64,
len: u64,
reporter: Option<Arc<Mutex<dyn ProgressReporter>>>,
}
impl ProgressPipe {
pub fn new(cur: u64, len: u64, reporter: Option<Arc<Mutex<dyn ProgressReporter>>>) -> Self {
Self { cur, len, reporter }
}
pub fn zero(len: u64, reporter: Option<Arc<Mutex<dyn ProgressReporter>>>) -> Self {
Self::new(0, len, reporter)
}
}
impl Pipe for ProgressPipe {
type Reader = ProgressReader;
type Writer = ProgressWriter;
fn pipe(&mut self, input: &[u8]) -> (usize, Option<Vec<u8>>) {
let (len, data) = self.pipe_transparent(input);
self.cur = min(self.cur + len as u64, self.len);
if let Some(reporter) = self.reporter.as_mut() {
let progress = self.cur;
let _ = reporter.lock().map(|mut r| r.progress(progress));
}
(len, data)
}
}
pub type ProgressReader = PipeReader<ProgressPipe>;
pub type ProgressWriter = PipeWriter<ProgressPipe>;
impl PipeLen for ProgressReader {
fn len_in(&self) -> usize {
self.pipe.len as usize
}
fn len_out(&self) -> usize {
self.pipe.len as usize
}
}
impl PipeLen for ProgressWriter {
fn len_in(&self) -> usize {
self.pipe.len as usize
}
fn len_out(&self) -> usize {
self.pipe.len as usize
}
}
pub trait ProgressReporter: Send {
fn start(&mut self, total: u64);
fn progress(&mut self, progress: u64);
fn finish(&mut self);
}