1use std::{fmt, ops::Deref, sync::Arc};
2
3use crate::progress::Step;
4
5#[cfg(feature = "unit-bytes")]
6mod bytes;
7#[cfg(feature = "unit-bytes")]
8pub use bytes::Bytes;
9
10#[cfg(feature = "unit-duration")]
11mod duration;
12#[cfg(feature = "unit-duration")]
13pub use duration::Duration;
14
15#[cfg(feature = "unit-human")]
16pub mod human;
18#[cfg(feature = "unit-human")]
19#[doc(inline)]
20pub use human::Human;
21
22mod range;
23pub use range::Range;
24
25mod traits;
26pub use traits::DisplayValue;
27
28pub mod display;
30
31#[derive(Debug, Clone, Hash)]
33pub struct Unit {
34 kind: Kind,
35 mode: Option<display::Mode>,
36}
37
38#[derive(Clone)]
40pub enum Kind {
41 Label(&'static str),
43 Dynamic(Arc<dyn DisplayValue + Send + Sync>),
45}
46
47impl std::hash::Hash for Kind {
48 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
49 match self {
50 Kind::Label(s) => {
51 0.hash(state);
52 s.dyn_hash(state)
53 }
54 Kind::Dynamic(label) => {
55 1.hash(state);
56 label.dyn_hash(state);
57 }
58 }
59 }
60}
61
62impl fmt::Debug for Kind {
63 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
64 match self {
65 Kind::Label(name) => f.write_fmt(format_args!("Unit::Label({:?})", name)),
66 Kind::Dynamic(_) => f.write_fmt(format_args!("Unit::Dynamic(..)")),
67 }
68 }
69}
70
71impl From<&'static str> for Unit {
72 fn from(v: &'static str) -> Self {
73 label(v)
74 }
75}
76
77pub fn label(label: &'static str) -> Unit {
79 Unit {
80 kind: Kind::Label(label),
81 mode: None,
82 }
83}
84
85pub fn label_and_mode(label: &'static str, mode: display::Mode) -> Unit {
87 Unit {
88 kind: Kind::Label(label),
89 mode: Some(mode),
90 }
91}
92
93pub fn dynamic(label: impl DisplayValue + Send + Sync + 'static) -> Unit {
95 Unit {
96 kind: Kind::Dynamic(Arc::new(label)),
97 mode: None,
98 }
99}
100
101pub fn dynamic_and_mode(label: impl DisplayValue + Send + Sync + 'static, mode: display::Mode) -> Unit {
103 Unit {
104 kind: Kind::Dynamic(Arc::new(label)),
105 mode: Some(mode),
106 }
107}
108
109impl Unit {
111 pub fn display(
119 &self,
120 current_value: Step,
121 upper_bound: Option<Step>,
122 throughput: impl Into<Option<display::Throughput>>,
123 ) -> display::UnitDisplay {
124 display::UnitDisplay {
125 current_value,
126 upper_bound,
127 throughput: throughput.into(),
128 parent: self,
129 display: display::What::ValuesAndUnit,
130 }
131 }
132
133 pub fn as_display_value(&self) -> &dyn DisplayValue {
135 match self.kind {
136 Kind::Label(ref unit) => unit,
137 Kind::Dynamic(ref unit) => unit.deref(),
138 }
139 }
140}