mod tests;
use std::fmt::Display;
use derive_more::{Add, Sub, Sum, AddAssign, SubAssign};
use humansize::{format_size, BaseUnit, FormatSizeOptions, Kilo};
const BITS_IN_BYTE: u64 = 8;
#[derive(
PartialEq, PartialOrd, Ord, Eq,
Clone, Copy, Hash, Debug, Default,
Add, Sub, Sum, AddAssign, SubAssign
)]
pub struct MemorySize {
size_bits: u64
}
impl MemorySize {
pub const fn new() -> Self {
MemorySize { size_bits: 0 }
}
pub const fn from_bytes(size_bytes: u64) -> MemorySize{
MemorySize{
size_bits: size_bytes.checked_mul(BITS_IN_BYTE).unwrap()
}
}
pub const fn from_bits(size_bits: u64) -> MemorySize {
MemorySize {
size_bits
}
}
pub const fn from_bits_ceil(bits: u64) -> MemorySize {
MemorySize {
size_bits: bits.div_ceil(BITS_IN_BYTE) * BITS_IN_BYTE
}
}
pub fn size_bytes(&self) -> u64 {
assert!(self.size_bits % BITS_IN_BYTE == 0);
self.size_bits / BITS_IN_BYTE
}
pub fn size_bits(&self) -> u64 {
self.size_bits
}
pub fn align_up(&self, alignment: &MemorySize) -> MemorySize {
if self.size_bits == 0 {return self.clone();}
if alignment.size_bits == 0 {return self.clone();}
let too_much = self.size_bits + alignment.size_bits - 1; let size_bits = (too_much / alignment.size_bits) * alignment.size_bits;
Self { size_bits }
}
}
impl Display for MemorySize {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let options = FormatSizeOptions::default()
.base_unit(BaseUnit::Byte)
.kilo(Kilo::Binary)
.decimal_places(2)
.space_after_value(true);
write!(f, "{}", format_size(self.size_bytes(), options))
}
}