#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct ByteSize(u64);
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct Bytes(u64);
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct Mebibytes(u32);
pub trait SizeExt {
fn bytes(self) -> ByteSize;
fn kib(self) -> ByteSize;
fn mib(self) -> ByteSize;
fn gib(self) -> ByteSize;
}
impl ByteSize {
pub fn as_bytes(self) -> u64 {
self.0
}
pub fn as_mib(self) -> u32 {
(self.0 / (1024 * 1024)) as u32
}
}
impl Bytes {
pub fn as_u64(self) -> u64 {
self.0
}
}
impl Mebibytes {
pub fn as_u32(self) -> u32 {
self.0
}
}
impl From<ByteSize> for Bytes {
fn from(bs: ByteSize) -> Self {
Self(bs.0)
}
}
impl From<ByteSize> for Mebibytes {
fn from(bs: ByteSize) -> Self {
Self((bs.0 / (1024 * 1024)) as u32)
}
}
impl From<u64> for Bytes {
fn from(v: u64) -> Self {
Self(v)
}
}
impl From<u32> for Mebibytes {
fn from(v: u32) -> Self {
Self(v)
}
}
macro_rules! impl_size_ext {
($($t:ty),*) => {
$(
impl SizeExt for $t {
fn bytes(self) -> ByteSize { ByteSize(self as u64) }
fn kib(self) -> ByteSize { ByteSize(self as u64 * 1024) }
fn mib(self) -> ByteSize { ByteSize(self as u64 * 1024 * 1024) }
fn gib(self) -> ByteSize { ByteSize(self as u64 * 1024 * 1024 * 1024) }
}
)*
};
}
impl_size_ext!(u8, u16, u32, u64, usize, i32);
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_size_ext_helpers() {
assert_eq!(1u64.kib().as_bytes(), 1024);
assert_eq!(1u64.mib().as_bytes(), 1024 * 1024);
assert_eq!(1u64.gib().as_bytes(), 1024 * 1024 * 1024);
assert_eq!(512u64.mib().as_bytes(), 512 * 1024 * 1024);
assert_eq!(64i32.mib().as_bytes(), 64 * 1024 * 1024);
}
#[test]
fn test_bytesize_to_mebibytes() {
let mib: Mebibytes = 512.mib().into();
assert_eq!(mib.as_u32(), 512);
let mib: Mebibytes = 1.gib().into();
assert_eq!(mib.as_u32(), 1024);
}
#[test]
fn test_bytesize_to_bytes() {
let b: Bytes = 64.mib().into();
assert_eq!(b.as_u64(), 64 * 1024 * 1024);
}
#[test]
fn test_bare_u32_to_mebibytes() {
let mib: Mebibytes = 512u32.into();
assert_eq!(mib.as_u32(), 512);
}
#[test]
fn test_bare_u64_to_bytes() {
let b: Bytes = 4096u64.into();
assert_eq!(b.as_u64(), 4096);
}
#[test]
fn test_truncation() {
let bs = ByteSize(1024 * 1024 + 512 * 1024);
let mib: Mebibytes = bs.into();
assert_eq!(mib.as_u32(), 1);
}
#[test]
fn test_bytes_helper() {
assert_eq!(4096.bytes().as_bytes(), 4096);
}
}