#[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);
}
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>
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 }
})
}
}
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()),
}
}
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)]
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(' '))
pub struct Nest {
outer_n: usize,
outer_i: usize,
- inner_last_phase: usize,
+ inner_last_frac: f32,
actual_reporter: Box<dyn Reporter>,
}
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,
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 {