use std::borrow::Cow;
use std::fmt;
#[derive(Clone, Debug, Eq, PartialEq, Hash, Default)]
pub enum MetricUnit {
Duration(DurationUnit),
Information(InformationUnit),
Fraction(FractionUnit),
Custom(Cow<'static, str>),
#[default]
None,
}
impl MetricUnit {
pub fn is_none(&self) -> bool {
matches!(self, Self::None)
}
}
impl fmt::Display for MetricUnit {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
MetricUnit::Duration(u) => u.fmt(f),
MetricUnit::Information(u) => u.fmt(f),
MetricUnit::Fraction(u) => u.fmt(f),
MetricUnit::Custom(u) => u.fmt(f),
MetricUnit::None => f.write_str("none"),
}
}
}
impl std::str::FromStr for MetricUnit {
type Err = ParseMetricUnitError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
Ok(match s {
"nanosecond" | "ns" => Self::Duration(DurationUnit::NanoSecond),
"microsecond" => Self::Duration(DurationUnit::MicroSecond),
"millisecond" | "ms" => Self::Duration(DurationUnit::MilliSecond),
"second" | "s" => Self::Duration(DurationUnit::Second),
"minute" => Self::Duration(DurationUnit::Minute),
"hour" => Self::Duration(DurationUnit::Hour),
"day" => Self::Duration(DurationUnit::Day),
"week" => Self::Duration(DurationUnit::Week),
"bit" => Self::Information(InformationUnit::Bit),
"byte" => Self::Information(InformationUnit::Byte),
"kilobyte" => Self::Information(InformationUnit::KiloByte),
"kibibyte" => Self::Information(InformationUnit::KibiByte),
"megabyte" => Self::Information(InformationUnit::MegaByte),
"mebibyte" => Self::Information(InformationUnit::MebiByte),
"gigabyte" => Self::Information(InformationUnit::GigaByte),
"gibibyte" => Self::Information(InformationUnit::GibiByte),
"terabyte" => Self::Information(InformationUnit::TeraByte),
"tebibyte" => Self::Information(InformationUnit::TebiByte),
"petabyte" => Self::Information(InformationUnit::PetaByte),
"pebibyte" => Self::Information(InformationUnit::PebiByte),
"exabyte" => Self::Information(InformationUnit::ExaByte),
"exbibyte" => Self::Information(InformationUnit::ExbiByte),
"ratio" => Self::Fraction(FractionUnit::Ratio),
"percent" => Self::Fraction(FractionUnit::Percent),
"" | "none" => Self::None,
_ => Self::Custom(s.to_owned().into()),
})
}
}
impl From<DurationUnit> for MetricUnit {
fn from(unit: DurationUnit) -> Self {
Self::Duration(unit)
}
}
impl From<InformationUnit> for MetricUnit {
fn from(unit: InformationUnit) -> Self {
Self::Information(unit)
}
}
impl From<FractionUnit> for MetricUnit {
fn from(unit: FractionUnit) -> Self {
Self::Fraction(unit)
}
}
impl From<&'static str> for MetricUnit {
fn from(unit: &'static str) -> Self {
Self::Custom(unit.into())
}
}
impl From<String> for MetricUnit {
fn from(unit: String) -> Self {
Self::Custom(unit.into())
}
}
impl From<Cow<'static, str>> for MetricUnit {
fn from(unit: Cow<'static, str>) -> Self {
Self::Custom(unit)
}
}
impl From<Option<String>> for MetricUnit {
fn from(unit: Option<String>) -> Self {
unit.map_or_else(|| Self::None, |u| Self::Custom(u.into()))
}
}
#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
pub enum DurationUnit {
NanoSecond,
MicroSecond,
MilliSecond,
Second,
Minute,
Hour,
Day,
Week,
}
impl Default for DurationUnit {
fn default() -> Self {
Self::MilliSecond
}
}
impl fmt::Display for DurationUnit {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::NanoSecond => f.write_str("nanosecond"),
Self::MicroSecond => f.write_str("microsecond"),
Self::MilliSecond => f.write_str("millisecond"),
Self::Second => f.write_str("second"),
Self::Minute => f.write_str("minute"),
Self::Hour => f.write_str("hour"),
Self::Day => f.write_str("day"),
Self::Week => f.write_str("week"),
}
}
}
#[derive(Clone, Copy, Debug)]
pub struct ParseMetricUnitError(());
#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
pub enum InformationUnit {
Bit,
Byte,
KiloByte,
KibiByte,
MegaByte,
MebiByte,
GigaByte,
GibiByte,
TeraByte,
TebiByte,
PetaByte,
PebiByte,
ExaByte,
ExbiByte,
}
impl Default for InformationUnit {
fn default() -> Self {
Self::Byte
}
}
impl fmt::Display for InformationUnit {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Bit => f.write_str("bit"),
Self::Byte => f.write_str("byte"),
Self::KiloByte => f.write_str("kilobyte"),
Self::KibiByte => f.write_str("kibibyte"),
Self::MegaByte => f.write_str("megabyte"),
Self::MebiByte => f.write_str("mebibyte"),
Self::GigaByte => f.write_str("gigabyte"),
Self::GibiByte => f.write_str("gibibyte"),
Self::TeraByte => f.write_str("terabyte"),
Self::TebiByte => f.write_str("tebibyte"),
Self::PetaByte => f.write_str("petabyte"),
Self::PebiByte => f.write_str("pebibyte"),
Self::ExaByte => f.write_str("exabyte"),
Self::ExbiByte => f.write_str("exbibyte"),
}
}
}
#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
pub enum FractionUnit {
Ratio,
Percent,
}
impl Default for FractionUnit {
fn default() -> Self {
Self::Ratio
}
}
impl fmt::Display for FractionUnit {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Ratio => f.write_str("ratio"),
Self::Percent => f.write_str("percent"),
}
}
}