irox_units/units/
datasize.rsuse crate::units::Unit;
use core::fmt::{Display, Formatter};
use super::FromUnits;
#[allow(clippy::cast_possible_truncation)]
#[allow(clippy::integer_division)]
#[derive(Debug, Clone, Copy, Default, Eq, PartialEq)]
pub enum DataSizeUnits {
#[default]
Bytes,
Kilobytes,
Megabytes,
Gigabytes,
Terabytes,
Petabytes,
}
macro_rules! from_units_datasize {
($type:ident) => {
#[allow(clippy::integer_division)]
impl crate::units::FromUnits<$type> for DataSizeUnits {
fn from(&self, value: $type, units: Self) -> $type {
match self {
DataSizeUnits::Bytes => match units {
DataSizeUnits::Bytes => value,
DataSizeUnits::Kilobytes => value * KB_TO_BYTES as $type,
DataSizeUnits::Megabytes => value * MB_TO_BYTES as $type,
DataSizeUnits::Gigabytes => value * GB_TO_BYTES as $type,
DataSizeUnits::Terabytes => value * TB_TO_BYTES as $type,
DataSizeUnits::Petabytes => value * PB_TO_BYTES as $type,
},
DataSizeUnits::Kilobytes => match units {
DataSizeUnits::Bytes => value / KB_TO_BYTES as $type,
DataSizeUnits::Kilobytes => value,
DataSizeUnits::Megabytes => value * KB_TO_BYTES as $type,
DataSizeUnits::Gigabytes => value * MB_TO_BYTES as $type,
DataSizeUnits::Terabytes => value * GB_TO_BYTES as $type,
DataSizeUnits::Petabytes => value * TB_TO_BYTES as $type,
},
DataSizeUnits::Megabytes => match units {
DataSizeUnits::Bytes => value / MB_TO_BYTES as $type,
DataSizeUnits::Kilobytes => value / KB_TO_BYTES as $type,
DataSizeUnits::Megabytes => value,
DataSizeUnits::Gigabytes => value * KB_TO_BYTES as $type,
DataSizeUnits::Terabytes => value * MB_TO_BYTES as $type,
DataSizeUnits::Petabytes => value * GB_TO_BYTES as $type,
},
DataSizeUnits::Gigabytes => match units {
DataSizeUnits::Bytes => value / GB_TO_BYTES as $type,
DataSizeUnits::Kilobytes => value / MB_TO_BYTES as $type,
DataSizeUnits::Megabytes => value / KB_TO_BYTES as $type,
DataSizeUnits::Gigabytes => value,
DataSizeUnits::Terabytes => value * KB_TO_BYTES as $type,
DataSizeUnits::Petabytes => value * MB_TO_BYTES as $type,
},
DataSizeUnits::Terabytes => match units {
DataSizeUnits::Bytes => value / TB_TO_BYTES as $type,
DataSizeUnits::Kilobytes => value / GB_TO_BYTES as $type,
DataSizeUnits::Megabytes => value / MB_TO_BYTES as $type,
DataSizeUnits::Gigabytes => value / KB_TO_BYTES as $type,
DataSizeUnits::Terabytes => value,
DataSizeUnits::Petabytes => value * KB_TO_BYTES as $type,
},
DataSizeUnits::Petabytes => match units {
DataSizeUnits::Bytes => value / PB_TO_BYTES as $type,
DataSizeUnits::Kilobytes => value / TB_TO_BYTES as $type,
DataSizeUnits::Megabytes => value / GB_TO_BYTES as $type,
DataSizeUnits::Gigabytes => value / MB_TO_BYTES as $type,
DataSizeUnits::Terabytes => value / KB_TO_BYTES as $type,
DataSizeUnits::Petabytes => value,
},
}
}
}
};
}
from_units_datasize!(f32);
from_units_datasize!(f64);
from_units_datasize!(i64);
from_units_datasize!(u64);
from_units_datasize!(usize);
basic_unit!(DataSize, DataSizeUnits, Bytes);
impl DataSize {
#[must_use]
pub fn new_bytes(&self, value: u64) -> DataSize {
Self::new(value as f64, DataSizeUnits::Bytes)
}
#[must_use]
pub fn as_bytes(&self) -> u64 {
match self.units {
DataSizeUnits::Bytes => self.value as u64,
DataSizeUnits::Kilobytes => (self.value * KB_TO_BYTES as f64) as u64,
DataSizeUnits::Megabytes => (self.value * MB_TO_BYTES as f64) as u64,
DataSizeUnits::Gigabytes => (self.value * GB_TO_BYTES as f64) as u64,
DataSizeUnits::Terabytes => (self.value * TB_TO_BYTES as f64) as u64,
DataSizeUnits::Petabytes => (self.value * PB_TO_BYTES as f64) as u64,
}
}
}
impl Display for DataSize {
fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
let bytes = self.as_bytes();
let frac = f.precision().unwrap_or(3);
if bytes < KB_TO_BYTES {
return write!(f, "{bytes} bytes");
} else if bytes < MB_TO_BYTES {
let val = bytes as f64 / KB_TO_BYTES as f64;
return write!(f, "{val:.frac$} KB");
} else if bytes < GB_TO_BYTES {
let val = bytes as f64 / MB_TO_BYTES as f64;
return write!(f, "{val:.frac$} MB");
} else if bytes < TB_TO_BYTES {
let val = bytes as f64 / GB_TO_BYTES as f64;
return write!(f, "{val:.frac$} GB");
} else if bytes < PB_TO_BYTES {
let val = bytes as f64 / TB_TO_BYTES as f64;
return write!(f, "{val:.frac$} TB");
}
let val = bytes as f64 / PB_TO_BYTES as f64;
write!(f, "{val:.frac$} PB")
}
}
pub const KB_TO_BYTES: u64 = 1000;
pub const MB_TO_BYTES: u64 = KB_TO_BYTES * 1000;
pub const GB_TO_BYTES: u64 = MB_TO_BYTES * 1000;
pub const TB_TO_BYTES: u64 = GB_TO_BYTES * 1000;
pub const PB_TO_BYTES: u64 = TB_TO_BYTES * 1000;