use std::str::FromStr;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
pub enum StorageUnit {
#[default]
Bytes,
Kilobytes,
Megabytes,
Gigabytes,
Terabytes,
Kibibytes,
Mebibytes,
Gibibytes,
Tebibytes,
}
impl StorageUnit {
pub fn units(&self, bytes: u64) -> f64 {
let bytes = bytes as f64;
match self {
Self::Bytes => bytes,
Self::Kilobytes => bytes / 1000.0,
Self::Megabytes => bytes / 1000000.0,
Self::Gigabytes => bytes / 1000000000.0,
Self::Terabytes => bytes / 1000000000000.0,
Self::Kibibytes => bytes / 1024.0,
Self::Mebibytes => bytes / 1048576.0,
Self::Gibibytes => bytes / 1073741824.0,
Self::Tebibytes => bytes / 1099511627776.0,
}
}
pub fn bytes(&self, num: u64) -> Option<u64> {
match self {
Self::Bytes => Some(num),
Self::Kilobytes => num.checked_mul(1000),
Self::Megabytes => num.checked_mul(1000000),
Self::Gigabytes => num.checked_mul(1000000000),
Self::Terabytes => num.checked_mul(1000000000000),
Self::Kibibytes => num.checked_mul(1024),
Self::Mebibytes => num.checked_mul(1048576),
Self::Gibibytes => num.checked_mul(1073741824),
Self::Tebibytes => num.checked_mul(1099511627776),
}
}
}
impl FromStr for StorageUnit {
type Err = ();
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
"B" => Ok(Self::Bytes),
"KB" | "K" => Ok(Self::Kilobytes),
"MB" | "M" => Ok(Self::Megabytes),
"GB" | "G" => Ok(Self::Gigabytes),
"TB" | "T" => Ok(Self::Terabytes),
"KiB" | "Ki" => Ok(Self::Kibibytes),
"MiB" | "Mi" => Ok(Self::Mebibytes),
"GiB" | "Gi" => Ok(Self::Gibibytes),
"TiB" | "Ti" => Ok(Self::Tebibytes),
_ => Err(()),
}
}
}
pub fn convert_unit_string(s: &str) -> Option<u64> {
let index = s.chars().position(|c| c.is_ascii_alphabetic())?;
let (n_str, unit_str) = s.split_at(index);
let n = n_str.trim().parse::<u64>().ok()?;
let unit = unit_str.trim().parse::<StorageUnit>().ok()?;
unit.bytes(n)
}