mod size;
#[derive(Debug,Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash, Default)]
pub struct ByteSize(u64);
const B: u64 = 1;
const KB: u64 = 1000;
const MB: u64 = KB.pow(2);
const GB: u64 = KB.pow(3);
const TB: u64 = KB.pow(4);
const PB: u64 = KB.pow(5);
const KIB: u64 = 1024;
const MIB: u64 = KIB.pow(2);
const GIB: u64 = KIB.pow(3);
const TIB: u64 = KIB.pow(4);
const PIB: u64 = KIB.pow(5);
enum ByteUnit {
KB,
MB,
GB,
TB,
PB,
KiB,
MiB,
GiB,
TiB,
PiB,
B,
IB,
}
pub struct ByteSizeUnit {
size: f64,
unit: ByteUnit,
}
impl ByteSize {
pub fn from_str(str: &str) -> Result<Self, String> {
let mut index = 0;
for (i, &byte) in str.as_bytes().iter().enumerate() {
if !(byte >= b'0' && byte <= b'9' || byte == b'.') {
index = i;
break;
}
}
let num = match str[..index].parse::<f64>() {
Ok(num) => { num }
Err(_) => {
return Err(format!("解析错误:{}", str));
}
};
let unit = Self::parse_unit(&str[index..].trim())?;
Ok(Self((num * unit as f64) as u64))
}
pub fn to_size(&self) -> u64 {
return self.0;
}
fn parse_unit(unit: &str) -> Result<u64, String> {
return match unit.to_uppercase().as_str() {
"PB" => { Ok(PB) }
"TB" => { Ok(TB) }
"GB" => { Ok(GB) }
"MB" => { Ok(MB) }
"KB" => { Ok(KB) }
"PIB" => { Ok(PIB) }
"TIB" => { Ok(TIB) }
"GIB" => { Ok(GIB) }
"MIB" => { Ok(MIB) }
"KIB" => { Ok(KIB) }
"IB" | "B" => { Ok(B) }
_ => { Err(format!("单位解析错误:{}", unit.to_string())) }
};
}
}
impl ByteSize {
pub fn pib(size: f64) -> Self {
Self((size * PIB as f64) as u64)
}
pub fn tib(size: f64) -> Self {
Self((size * TIB as f64) as u64)
}
pub fn gib(size: f64) -> Self {
Self((size * GIB as f64) as u64)
}
pub fn mib(size: f64) -> Self {
Self((size * MIB as f64) as u64)
}
pub fn kib(size: f64) -> Self {
Self((size * KIB as f64) as u64)
}
pub fn pb(size: f64) -> Self {
Self((size * PB as f64) as u64)
}
pub fn tb(size: f64) -> Self {
Self((size * TB as f64) as u64)
}
pub fn gb(size: f64) -> Self {
Self((size * GB as f64) as u64)
}
pub fn mb(size: f64) -> Self {
Self((size * MB as f64) as u64)
}
pub fn kb(size: f64) -> Self {
Self((size * KB as f64) as u64)
}
pub fn b(size: f64) -> Self {
Self(size as u64)
}
pub fn ib(size: f64) -> Self {
Self(size as u64)
}
}
impl ByteSize {
pub fn to_pib(&self) -> ByteSizeUnit {
ByteSizeUnit {
size: self.to_size() as f64 / PIB as f64,
unit: ByteUnit::PiB,
}
}
pub fn to_tib(&self) -> ByteSizeUnit {
ByteSizeUnit {
size: self.to_size() as f64 / TIB as f64,
unit: ByteUnit::TiB,
}
}
pub fn to_gib(&self) -> ByteSizeUnit {
ByteSizeUnit {
size: self.to_size() as f64 / GIB as f64,
unit: ByteUnit::GiB,
}
}
pub fn to_mib(&self) -> ByteSizeUnit {
ByteSizeUnit {
size: self.to_size() as f64 / MIB as f64,
unit: ByteUnit::MiB,
}
}
pub fn to_kib(&self) -> ByteSizeUnit {
ByteSizeUnit {
size: self.to_size() as f64 / KIB as f64,
unit: ByteUnit::KiB,
}
}
pub fn to_ib(&self) -> ByteSizeUnit {
ByteSizeUnit {
size: self.to_size() as f64,
unit: ByteUnit::IB,
}
}
pub fn to_pb(&self) -> ByteSizeUnit {
ByteSizeUnit {
size: self.to_size() as f64 / PB as f64,
unit: ByteUnit::PB,
}
}
pub fn to_tb(&self) -> ByteSizeUnit {
ByteSizeUnit {
size: self.to_size() as f64 / TB as f64,
unit: ByteUnit::TB,
}
}
pub fn to_gb(&self) -> ByteSizeUnit {
ByteSizeUnit {
size: self.to_size() as f64 / GB as f64,
unit: ByteUnit::GB,
}
}
pub fn to_mb(&self) -> ByteSizeUnit {
ByteSizeUnit {
size: self.to_size() as f64 / MB as f64,
unit: ByteUnit::MB,
}
}
pub fn to_kb(&self) -> ByteSizeUnit {
ByteSizeUnit {
size: self.to_size() as f64 / KB as f64,
unit: ByteUnit::KB,
}
}
pub fn to_b(&self) -> ByteSizeUnit {
ByteSizeUnit {
size: self.to_size() as f64,
unit: ByteUnit::B,
}
}
}
impl ToString for ByteSizeUnit {
fn to_string(&self) -> String {
let unit = match self.unit {
ByteUnit::KB => { "KB" }
ByteUnit::MB => { "MB" }
ByteUnit::GB => { "GB" }
ByteUnit::TB => { "TB" }
ByteUnit::PB => { "PB" }
ByteUnit::KiB => { "KiB" }
ByteUnit::MiB => { "MiB" }
ByteUnit::GiB => { "GiB" }
ByteUnit::TiB => { "TiB" }
ByteUnit::PiB => { "PiB" }
ByteUnit::B => { "B" }
ByteUnit::IB => { "iB" }
};
format!("{} {}", self.size, unit)
}
}
impl ByteSizeUnit {
pub fn to_bytes_size(&self) -> ByteSize {
let num: u64 = match self.unit {
ByteUnit::KB => { (self.size * KB as f64) as u64 }
ByteUnit::MB => { (self.size * MB as f64) as u64 }
ByteUnit::GB => { (self.size * GB as f64) as u64 }
ByteUnit::TB => { (self.size * TB as f64) as u64 }
ByteUnit::PB => { (self.size * PB as f64) as u64 }
ByteUnit::KiB => { (self.size * KIB as f64) as u64 }
ByteUnit::MiB => { (self.size * MIB as f64) as u64 }
ByteUnit::GiB => { (self.size * GIB as f64) as u64 }
ByteUnit::TiB => { (self.size * TIB as f64) as u64 }
ByteUnit::PiB => { (self.size * PIB as f64) as u64 }
ByteUnit::B => { self.size as u64 }
ByteUnit::IB => { self.size as u64 }
};
ByteSize(num)
}
}
pub trait Calculate {
fn add(&self, a: Self) -> Option<ByteSize>;
fn sub(&self, r: Self) -> Option<ByteSize>;
}
pub fn add<T: Calculate>(s: T, a: T) -> Option<ByteSize> {
return s.add(a);
}
pub fn sub<T: Calculate>(s: T, a: T) -> Option<ByteSize> {
return s.add(a);
}
impl Calculate for ByteSizeUnit {
fn add(&self, a: Self) -> Option<ByteSize> {
let s = self.to_bytes_size().to_size().checked_add(a.to_bytes_size().to_size())?;
Some(ByteSize(s))
}
fn sub(&self, r: Self) -> Option<ByteSize> {
let s = self.to_bytes_size().to_size().checked_sub(r.to_bytes_size().to_size())?;
Some(ByteSize(s))
}
}
impl Calculate for ByteSize {
fn add(&self, a: Self) -> Option<ByteSize> {
let s = self.to_size().checked_add(a.to_size())?;
Some(ByteSize(s))
}
fn sub(&self, r: Self) -> Option<ByteSize> {
let s = self.to_size().checked_sub(r.to_size())?;
Some(ByteSize(s))
}
}