chiark / gitweb /
progress: provide ReadOriginator (untested as yet)
authorIan Jackson <ijackson@chiark.greenend.org.uk>
Fri, 14 May 2021 23:26:42 +0000 (00:26 +0100)
committerIan Jackson <ijackson@chiark.greenend.org.uk>
Sat, 15 May 2021 00:15:22 +0000 (01:15 +0100)
Signed-off-by: Ian Jackson <ijackson@chiark.greenend.org.uk>
src/progress.rs

index 3c0ae81f541ff104fdd8426d274dbb6f74d0e3aa..7c7e5a13b717c52792b7569b928ed02fcbc8056b 100644 (file)
@@ -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<Count<'p>>
+  {
+    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::<String>()
+        .chars().rev()
+        .collect::<String>()
+    };
+    let desc = format!("{} / {}", m(c), m(t));
+    self.orig.item(self.counter, desc);
+    self.last_report = self.counter;
+  }
+}
+
+impl<R:Read> 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
+  }
+}