use std::{num::NonZeroU32, str::FromStr};
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub enum SpeedRateUnit {
Kilobyte,
Megabyte,
Gigabyte,
}
impl SpeedRateUnit {
pub const fn multiplier(&self) -> NonZeroU32 {
match self {
SpeedRateUnit::Kilobyte => NonZeroU32::new(1).expect("Is always non-zero"),
SpeedRateUnit::Megabyte => NonZeroU32::new(1024).expect("Is always non-zero"),
SpeedRateUnit::Gigabyte => NonZeroU32::new(1024 * 1024).expect("Is always non-zero"),
}
}
}
impl std::fmt::Display for SpeedRateUnit {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(
f,
"{}",
match self {
SpeedRateUnit::Kilobyte => "kb",
SpeedRateUnit::Megabyte => "mb",
SpeedRateUnit::Gigabyte => "gb",
}
)
}
}
impl FromStr for SpeedRateUnit {
type Err = String;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s.to_lowercase().as_str() {
"kb" => Ok(SpeedRateUnit::Kilobyte),
"mb" => Ok(SpeedRateUnit::Megabyte),
"gb" => Ok(SpeedRateUnit::Gigabyte),
_ => Err(format!("Invalid speedrate unit: {}", s)),
}
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub enum RateUnit {
Request,
SpeedRateUnit(SpeedRateUnit),
}
impl RateUnit {
pub fn is_speed_rate_unit(&self) -> bool {
matches!(self, RateUnit::SpeedRateUnit(_))
}
}
impl std::fmt::Display for RateUnit {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(
f,
"{}",
match self {
RateUnit::Request => "r".to_string(),
RateUnit::SpeedRateUnit(unit) => unit.to_string(),
}
)
}
}
impl FromStr for RateUnit {
type Err = String;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s.to_lowercase().as_str() {
"r" => Ok(RateUnit::Request),
other => match SpeedRateUnit::from_str(other) {
Ok(unit) => Ok(RateUnit::SpeedRateUnit(unit)),
Err(_) => Err(format!("Invalid rate unit: {}", s)),
},
}
}
}
impl RateUnit {
pub const fn multiplier(&self) -> NonZeroU32 {
match self {
RateUnit::Request => NonZeroU32::new(1).expect("Is always non-zero"),
RateUnit::SpeedRateUnit(unit) => unit.multiplier(),
}
}
}