1use std::borrow::Cow;
4use std::fmt;
5
6#[derive(Clone, Debug, Eq, PartialEq, Hash, Default)]
16pub enum MetricUnit {
17 Duration(DurationUnit),
19 Information(InformationUnit),
21 Fraction(FractionUnit),
23 Custom(Cow<'static, str>),
25 #[default]
27 None,
28}
29
30impl MetricUnit {
31 pub fn is_none(&self) -> bool {
33 matches!(self, Self::None)
34 }
35}
36
37impl fmt::Display for MetricUnit {
38 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
39 match self {
40 MetricUnit::Duration(u) => u.fmt(f),
41 MetricUnit::Information(u) => u.fmt(f),
42 MetricUnit::Fraction(u) => u.fmt(f),
43 MetricUnit::Custom(u) => u.fmt(f),
44 MetricUnit::None => f.write_str("none"),
45 }
46 }
47}
48
49impl std::str::FromStr for MetricUnit {
50 type Err = ParseMetricUnitError;
51
52 fn from_str(s: &str) -> Result<Self, Self::Err> {
53 Ok(match s {
54 "nanosecond" | "ns" => Self::Duration(DurationUnit::NanoSecond),
55 "microsecond" => Self::Duration(DurationUnit::MicroSecond),
56 "millisecond" | "ms" => Self::Duration(DurationUnit::MilliSecond),
57 "second" | "s" => Self::Duration(DurationUnit::Second),
58 "minute" => Self::Duration(DurationUnit::Minute),
59 "hour" => Self::Duration(DurationUnit::Hour),
60 "day" => Self::Duration(DurationUnit::Day),
61 "week" => Self::Duration(DurationUnit::Week),
62
63 "bit" => Self::Information(InformationUnit::Bit),
64 "byte" => Self::Information(InformationUnit::Byte),
65 "kilobyte" => Self::Information(InformationUnit::KiloByte),
66 "kibibyte" => Self::Information(InformationUnit::KibiByte),
67 "megabyte" => Self::Information(InformationUnit::MegaByte),
68 "mebibyte" => Self::Information(InformationUnit::MebiByte),
69 "gigabyte" => Self::Information(InformationUnit::GigaByte),
70 "gibibyte" => Self::Information(InformationUnit::GibiByte),
71 "terabyte" => Self::Information(InformationUnit::TeraByte),
72 "tebibyte" => Self::Information(InformationUnit::TebiByte),
73 "petabyte" => Self::Information(InformationUnit::PetaByte),
74 "pebibyte" => Self::Information(InformationUnit::PebiByte),
75 "exabyte" => Self::Information(InformationUnit::ExaByte),
76 "exbibyte" => Self::Information(InformationUnit::ExbiByte),
77
78 "ratio" => Self::Fraction(FractionUnit::Ratio),
79 "percent" => Self::Fraction(FractionUnit::Percent),
80
81 "" | "none" => Self::None,
82 _ => Self::Custom(s.to_owned().into()),
83 })
84 }
85}
86
87impl From<DurationUnit> for MetricUnit {
88 fn from(unit: DurationUnit) -> Self {
89 Self::Duration(unit)
90 }
91}
92
93impl From<InformationUnit> for MetricUnit {
94 fn from(unit: InformationUnit) -> Self {
95 Self::Information(unit)
96 }
97}
98
99impl From<FractionUnit> for MetricUnit {
100 fn from(unit: FractionUnit) -> Self {
101 Self::Fraction(unit)
102 }
103}
104
105impl From<&'static str> for MetricUnit {
106 fn from(unit: &'static str) -> Self {
107 Self::Custom(unit.into())
108 }
109}
110
111impl From<String> for MetricUnit {
112 fn from(unit: String) -> Self {
113 Self::Custom(unit.into())
114 }
115}
116
117impl From<Cow<'static, str>> for MetricUnit {
118 fn from(unit: Cow<'static, str>) -> Self {
119 Self::Custom(unit)
120 }
121}
122
123impl From<Option<String>> for MetricUnit {
124 fn from(unit: Option<String>) -> Self {
125 unit.map_or_else(|| Self::None, |u| Self::Custom(u.into()))
126 }
127}
128
129#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
133pub enum DurationUnit {
134 NanoSecond,
136 MicroSecond,
138 MilliSecond,
140 Second,
142 Minute,
144 Hour,
146 Day,
148 Week,
150}
151
152impl Default for DurationUnit {
153 fn default() -> Self {
154 Self::MilliSecond
155 }
156}
157
158impl fmt::Display for DurationUnit {
159 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
160 match self {
161 Self::NanoSecond => f.write_str("nanosecond"),
162 Self::MicroSecond => f.write_str("microsecond"),
163 Self::MilliSecond => f.write_str("millisecond"),
164 Self::Second => f.write_str("second"),
165 Self::Minute => f.write_str("minute"),
166 Self::Hour => f.write_str("hour"),
167 Self::Day => f.write_str("day"),
168 Self::Week => f.write_str("week"),
169 }
170 }
171}
172
173#[derive(Clone, Copy, Debug)]
175pub struct ParseMetricUnitError(());
176
177#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
182pub enum InformationUnit {
183 Bit,
187 Byte,
189 KiloByte,
191 KibiByte,
193 MegaByte,
195 MebiByte,
197 GigaByte,
199 GibiByte,
201 TeraByte,
203 TebiByte,
205 PetaByte,
207 PebiByte,
209 ExaByte,
211 ExbiByte,
213}
214
215impl Default for InformationUnit {
216 fn default() -> Self {
217 Self::Byte
218 }
219}
220
221impl fmt::Display for InformationUnit {
222 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
223 match self {
224 Self::Bit => f.write_str("bit"),
225 Self::Byte => f.write_str("byte"),
226 Self::KiloByte => f.write_str("kilobyte"),
227 Self::KibiByte => f.write_str("kibibyte"),
228 Self::MegaByte => f.write_str("megabyte"),
229 Self::MebiByte => f.write_str("mebibyte"),
230 Self::GigaByte => f.write_str("gigabyte"),
231 Self::GibiByte => f.write_str("gibibyte"),
232 Self::TeraByte => f.write_str("terabyte"),
233 Self::TebiByte => f.write_str("tebibyte"),
234 Self::PetaByte => f.write_str("petabyte"),
235 Self::PebiByte => f.write_str("pebibyte"),
236 Self::ExaByte => f.write_str("exabyte"),
237 Self::ExbiByte => f.write_str("exbibyte"),
238 }
239 }
240}
241
242#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
246pub enum FractionUnit {
247 Ratio,
249 Percent,
251}
252
253impl Default for FractionUnit {
254 fn default() -> Self {
255 Self::Ratio
256 }
257}
258
259impl fmt::Display for FractionUnit {
260 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
261 match self {
262 Self::Ratio => f.write_str("ratio"),
263 Self::Percent => f.write_str("percent"),
264 }
265 }
266}