chiark / gitweb /
progress: Allow ProgressInfo's Count to contain only a proportion
authorIan Jackson <ijackson@chiark.greenend.org.uk>
Sun, 15 May 2022 20:21:28 +0000 (21:21 +0100)
committerIan Jackson <ijackson@chiark.greenend.org.uk>
Sun, 15 May 2022 23:26:51 +0000 (00:26 +0100)
We're going to introduce a thing that will use this.

Signed-off-by: Ian Jackson <ijackson@chiark.greenend.org.uk>
Cargo.lock
Cargo.toml
src/crates.rs
src/imports.rs
support/Cargo.toml
support/crates.rs
support/imports.rs
support/progress.rs
support/termprogress.rs

index 1adc166b0d40e3d61428b494acd6c9eab4cfbf93..b1cb79158dff6c87a24f22c58a69996c4c7c4fc9 100644 (file)
@@ -2683,7 +2683,6 @@ dependencies = [
  "crossbeam-utils",
  "delegate",
  "downcast-rs",
- "educe",
  "either",
  "enum-map",
  "enum_dispatch",
@@ -2820,6 +2819,7 @@ dependencies = [
  "console",
  "derive-into-owned",
  "digest 0.10.3",
+ "educe",
  "fehler",
  "flexi_logger",
  "fs2",
index fc7fa67bd4020da429d039a24905dbc33e00a862..4471bd25db451372bd979d5233adb96eca1e0fcd 100644 (file)
@@ -39,7 +39,6 @@ cast_trait_object="0.1"
 crossbeam-utils="0.8"
 delegate="0.6"
 downcast-rs="1"
-educe="0.4"
 either="1"
 enum_dispatch="0.3.5"
 env_logger="0.9"
index 00f0b7ce44bcaf7474e7cd5cfc252bc400cb95ea..8d5b6e24d78ae8e71331e1776031319dda93e542 100644 (file)
@@ -11,7 +11,6 @@ pub use base64;
 pub use boolinator;
 pub use cast_trait_object;
 pub use delegate;
-pub use educe;
 pub use either;
 pub use env_logger;
 pub use glob;
index a948fb83b18532cffc8d75dbf8d6f166bae9d982..7c8f9d5b07884682a0894adae419bd4da531fa29 100644 (file)
@@ -35,7 +35,6 @@ pub use cast_trait_object::{dyn_upcast, DynCastExt};
 pub use const_default::ConstDefault;
 pub use delegate::delegate;
 pub use downcast_rs::{impl_downcast, Downcast};
-pub use educe::Educe;
 pub use either::{Either, Left, Right};
 pub use enum_dispatch::enum_dispatch;
 pub use enum_map::{Enum, EnumMap};
index 8fe39eabff8aca303da8ea2805f735aa1c624bae..ae1b0fa55a21566e17fd103912c228f36eb13533 100644 (file)
@@ -33,6 +33,7 @@ chrono-tz="0.6"
 console="0.15"
 derive-into-owned="0.2"
 digest="0.10"
+educe="0.4"
 fehler="1"
 fs2="0.4"
 lazy_static="1"
index 1e0778829841885ae0e900453c62cd2e14907bd4..17080c7546b624f59ee0c34fa2a5e0f1c1f2bdc4 100644 (file)
@@ -10,6 +10,7 @@ pub use anyhow;
 pub use chrono;
 pub use chrono_tz;
 pub use digest;
+pub use educe;
 pub use flexi_logger;
 pub use fs2;
 pub use lazy_static;
index 4b2b7968c63347b31fc4af675bac8b6cd7f2755a..2202a7abfcda1582f1a968d92187c4913ba57016 100644 (file)
@@ -75,6 +75,7 @@ pub use crate::authproofs::AuthorisationSuperuser;
 pub use crate::childio;
 pub use crate::config::*;
 pub use crate::debugmutex::DebugIdentify;
+pub use educe::Educe;
 pub use crate::digestrw::{self, *};
 pub use crate::fake_rng::*;
 pub use crate::fake_time::*;
index d71c82bd0c42ce1cec229db527157008b54e39fc..163eafa506cd3a32699e520692f523779b553dfc 100644 (file)
@@ -12,11 +12,33 @@ pub struct ProgressInfo<'pi> {
 
 #[derive(Debug,Clone,Serialize,Deserialize,IntoOwned)]
 pub struct Count<'pi> {
-  pub i: usize,
-  pub n: usize,
+  pub value: Value,
   pub desc: Cow<'pi, str>,
 }
 
+#[derive(Debug,Clone,Serialize,Deserialize,IntoOwned)]
+#[derive(Educe)]
+#[educe(Default)]
+pub enum Value {
+  #[educe(Default)] Exact {
+    i: usize,
+    n: usize,
+  },
+  Fraction {
+    f: f32, // [0..1]
+  }
+}
+
+impl Value {
+  pub fn fraction(&self) -> f32 {
+    match self {
+      &Value::Exact{ i:_, n } if n == 0 => 0.,
+      &Value::Exact{ i, n } => (i as f32) / (n as f32),
+      &Value::Fraction{ f } => f,
+    }
+  }
+}
+
 pub trait Originator {
   fn report(&mut self, info: ProgressInfo<'_>);
   fn phase_begin_(&mut self, phase: Count<'_>, len: usize);
@@ -31,12 +53,14 @@ pub struct ResponseOriginator<'c,'w,W,F> where W: Write {
 }
 impl<'c,'w,W,F> ResponseOriginator<'c,'w,W,F> where W: Write {
   pub fn new(chan: &'c mut ResponseWriter<'w,W>,
-             formatter: F) -> Self { Self {
-    chan,
-    phase: Count { i:0, n:0, desc: Cow::Borrowed("") },
-    len: 0,
-    formatter,
-  } }
+             formatter: F) -> Self {
+    Self {
+      chan,
+      phase: Count { value: default(), desc: Cow::Borrowed("") },
+      len: 0,
+      formatter,
+    }
+  }
 }
 
 impl<W,F,M> Originator for ResponseOriginator<'_,'_,W,F>
@@ -53,9 +77,10 @@ where W: Write,
     self.len = len;
   }
   fn item_(&mut self, item: usize, desc: Cow<'_, str>) {
+    let value = Value::Exact { i: item, n: self.len };
     self.report(ProgressInfo {
       phase: self.phase.clone(),
-      item: Count { i: item, n: self.len, desc }
+      item: Count { value, desc }
     })
   }
 }
@@ -70,9 +95,12 @@ impl Originator for () {
 pub trait Enum: EnumCount + ToPrimitive + EnumMessage { }
 impl<T> From<T> for Count<'static> where T: Enum {
   fn from(t: T) -> Count<'static> {
-    Count {
+    let value = Value::Exact { 
       i: t.to_usize().unwrap(),
       n: T::COUNT - 1,
+    };
+    Count {
+      value,
       // Show be Borrowed  https://github.com/Peternator7/strum/issues/159
       desc: Cow::Owned(t.get_message().unwrap_or("...").to_owned()),
     }
@@ -80,16 +108,16 @@ impl<T> From<T> for Count<'static> where T: Enum {
 }
 impl<'t> From<&'t str> for Count<'t> {
   fn from(s: &'t str) -> Count<'t> {
-    Count { i:0, n:0, desc: Cow::Borrowed(s) }
+    Count { value: default(), desc: Cow::Borrowed(s) }
   }
 }
 impl From<String> for Count<'static> {
   fn from(s: String) -> Count<'static> {
-    Count { i:0, n:0, desc: Cow::Owned(s) }
+    Count { value: default(), desc: Cow::Owned(s) }
   }
 }
 impl<'t> From<()> for Count<'t> { fn from(_:()) -> Count<'t> {
-    Count { i:0, n:0, desc: Cow::Borrowed("") }
+    Count { value: default(), desc: Cow::Borrowed("") }
 } }
 
 #[ext(pub, name=OriginatorExt)]
index d56c01f95f2b50d3ae7fbee320e3218ada6493bd..7864d24d281ef8e509ebf84ea77d3d67fb3f30c2 100644 (file)
@@ -120,12 +120,10 @@ impl TermReporter {
 
   fn bar(&self, out: &mut String, fwidth: Col, info: &progress::Count) {
     let desc = console::strip_ansi_codes(&info.desc);
-    let w_change = if info.n == 0 { 0 } else {
-      min(
-        ((info.i as f32) / (info.n as f32) * (fwidth as f32)) as Col,
-        fwidth // just in case
-      )
-    };
+    let w_change = min(
+      (info.value.fraction() * (fwidth as f32)) as Col,
+      fwidth // just in case
+    );
     let mut desc = desc
       .chars()
       .chain(iter::repeat(' '))
@@ -166,7 +164,7 @@ impl Drop for TermReporter {
 pub struct Nest {
   outer_n: usize,
   outer_i: usize,
-  inner_last_phase: usize,
+  inner_last_frac: f32,
   actual_reporter: Box<dyn Reporter>,
 }
 
@@ -177,17 +175,20 @@ impl Nest {
     actual_reporter,
     outer_n: outer_count,
     outer_i: 0,
-    inner_last_phase: 0,
+    inner_last_frac: 0.,
   } }
 }
 
 impl Reporter for Nest {
   fn report(&mut self, inner_pi: &ProgressInfo<'_>) {
+    use progress::Value;
+
     // Autodetect new outer phase item, when inner pahse rewinds
-    if inner_pi.phase.i < self.inner_last_phase {
+    let inner_frac = inner_pi.phase.value.fraction();
+    if inner_frac < self.inner_last_frac {
       self.outer_i += 1;
     }
-    self.inner_last_phase = inner_pi.phase.i;
+    self.inner_last_frac = inner_frac;
 
     let desc = if self.outer_n > 1 {
       format!("{}/{} {}", self.outer_i, self.outer_n,
@@ -196,10 +197,19 @@ impl Reporter for Nest {
       inner_pi.phase.desc.clone()
     };
 
+    let outer_value = match inner_pi.phase.value {
+      Value::Exact { i, n } => Value::Exact {
+        i: i + n * self.outer_i,
+        n:     n * self.outer_n,
+      },
+      Value::Fraction { f } => Value::Fraction {
+        f: f * (1.0 / self.outer_n as f32)
+           + Value::Exact { i: self.outer_i, n: self.outer_n }.fraction(),
+      },
+    };
     let outer_phase = progress::Count {
-      i: inner_pi.phase.i + inner_pi.phase.n * self.outer_i,
-      n:                    inner_pi.phase.n * self.outer_n,
       desc,
+      value: outer_value,
     };
 
     let outer_pi = ProgressInfo {