From: Ian Jackson Date: Fri, 14 May 2021 23:26:42 +0000 (+0100) Subject: progress: provide ReadOriginator (untested as yet) X-Git-Tag: otter-0.6.0~305 X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=commitdiff_plain;h=f15097cde389878822e4b7b26fb6f6aa16692015;p=otter.git progress: provide ReadOriginator (untested as yet) Signed-off-by: Ian Jackson --- diff --git a/src/progress.rs b/src/progress.rs index 3c0ae81f..7c7e5a13 100644 --- a/src/progress.rs +++ b/src/progress.rs @@ -107,3 +107,58 @@ impl &mut dyn Originator { self.item_(item, desc.into()) } } + +pub struct ReadOriginator<'oo,'o,R:Read> { + r: R, + total_len: usize, + orig: &'oo mut &'o mut dyn Originator, + // state: + counter: usize, + last_report: usize, +} + +impl<'oo,'o,R:Read> ReadOriginator<'oo,'o,R> { + pub fn new<'p,P>(orig: &'oo mut &'o mut dyn Originator, phase: P, + total_len: usize, r: R) -> Self + where P: Into> + { + orig.phase(phase, total_len); + let mut ro = ReadOriginator { + r, orig, total_len, + counter: 0, + last_report: 0, + }; + ro.report(); + ro + } + + fn report(&mut self) { + let t = self.total_len.to_string(); + let c = format!("{:>width$}", self.counter, width=t.len()); + let m = |s: String| { + izip!( iter::once("").chain(["",""," "].iter().cloned().cycle()), + s.chars().rev() ) + .map(|(s,c)| [s.chars().next(), Some(c)]) + .flatten() + .flatten() + .collect::() + .chars().rev() + .collect::() + }; + let desc = format!("{} / {}", m(c), m(t)); + self.orig.item(self.counter, desc); + self.last_report = self.counter; + } +} + +impl Read for ReadOriginator<'_,'_,R> { + #[throws(io::Error)] + fn read(&mut self, buf: &mut [u8]) -> usize { + let got = self.r.read(buf)?; + self.counter += got; + if self.counter - self.last_report > 10000 { + self.report(); + } + got + } +}