summaryrefslogtreecommitdiffstats
path: root/vendor/prodash/src/unit/traits.rs
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/prodash/src/unit/traits.rs')
-rw-r--r--vendor/prodash/src/unit/traits.rs93
1 files changed, 93 insertions, 0 deletions
diff --git a/vendor/prodash/src/unit/traits.rs b/vendor/prodash/src/unit/traits.rs
new file mode 100644
index 000000000..33b529e4a
--- /dev/null
+++ b/vendor/prodash/src/unit/traits.rs
@@ -0,0 +1,93 @@
+use std::{fmt, hash::Hasher};
+
+use crate::{progress::Step, unit::display};
+
+/// A trait to encapsulate all capabilities needed to display a value with unit within a renderer.
+pub trait DisplayValue {
+ /// Display the absolute `value` representing the current progress of an operation and write it to `w`.
+ ///
+ /// The `upper` bound is possibly provided when known to add context, even though it is not to be output
+ /// as part of this method call.
+ fn display_current_value(&self, w: &mut dyn fmt::Write, value: Step, _upper: Option<Step>) -> fmt::Result {
+ fmt::write(w, format_args!("{}", value))
+ }
+ /// Emit a token to separate two values.
+ ///
+ /// The `value` and its `upper` bound are provided to add context, even though it is not to be output
+ /// as part of this method call.
+ fn separator(&self, w: &mut dyn fmt::Write, _value: Step, _upper: Option<Step>) -> fmt::Result {
+ w.write_str("/")
+ }
+
+ /// Emit the `upper_bound` to `w`.
+ ///
+ /// The `value` is provided to add context, even though it is not to be output as part of this method call.
+ fn display_upper_bound(&self, w: &mut dyn fmt::Write, upper_bound: Step, _value: Step) -> fmt::Result {
+ fmt::write(w, format_args!("{}", upper_bound))
+ }
+
+ /// A way to hash our state without using generics.
+ ///
+ /// This helps to determine quickly if something changed.
+ fn dyn_hash(&self, state: &mut dyn std::hash::Hasher);
+
+ /// Emit the unit of `value` to `w`.
+ ///
+ /// The `value` is provided to add context, even though it is not to be output as part of this method call.
+ fn display_unit(&self, w: &mut dyn fmt::Write, value: Step) -> fmt::Result;
+
+ /// Emit `percentage` to `w`.
+ fn display_percentage(&self, w: &mut dyn fmt::Write, percentage: f64) -> fmt::Result {
+ w.write_fmt(format_args!("[{}%]", percentage as usize))
+ }
+
+ /// Emit the `throughput` of an operation to `w`.
+ fn display_throughput(&self, w: &mut dyn fmt::Write, throughput: &display::Throughput) -> fmt::Result {
+ let (fraction, unit) = self.fraction_and_time_unit(throughput.timespan);
+ w.write_char('|')?;
+ self.display_current_value(w, throughput.value_change_in_timespan, None)?;
+ w.write_char('/')?;
+ match fraction {
+ Some(fraction) => w.write_fmt(format_args!("{}", fraction)),
+ None => Ok(()),
+ }?;
+ w.write_fmt(format_args!("{}|", unit))
+ }
+
+ /// Given a `timespan`, return a fraction of the timespan based on the given unit, i.e. `(possible fraction, unit`).
+ fn fraction_and_time_unit(&self, timespan: std::time::Duration) -> (Option<f64>, &'static str) {
+ fn skip_one(v: f64) -> Option<f64> {
+ if (v - 1.0).abs() < f64::EPSILON {
+ None
+ } else {
+ Some(v)
+ }
+ }
+ const HOUR_IN_SECS: u64 = 60 * 60;
+ let secs = timespan.as_secs();
+ let h = secs / HOUR_IN_SECS;
+ if h > 0 {
+ return (skip_one(secs as f64 / HOUR_IN_SECS as f64), "h");
+ }
+ const MINUTES_IN_SECS: u64 = 60;
+ let m = secs / MINUTES_IN_SECS;
+ if m > 0 {
+ return (skip_one(secs as f64 / MINUTES_IN_SECS as f64), "m");
+ }
+ if secs > 0 {
+ return (skip_one(secs as f64), "s");
+ }
+
+ (skip_one(timespan.as_millis() as f64), "ms")
+ }
+}
+
+impl DisplayValue for &'static str {
+ fn dyn_hash(&self, state: &mut dyn Hasher) {
+ state.write(self.as_bytes())
+ }
+
+ fn display_unit(&self, w: &mut dyn fmt::Write, _value: usize) -> fmt::Result {
+ w.write_fmt(format_args!("{}", self))
+ }
+}