// This file is port from https://github.com/bytesize-rs/bytesize/blob/7467a23df30bc1fee48326e0fa6c063fc85676a2/src/lib.rs
// Copyright Apache-2.0 January 2004 The bytesize Authors. All rights reserved.
///| `ByteSize` is a semantic wrapper for byte count representations.
///|
/// Number of bytes in 1 kilobyte.
pub const KB : UInt64 = 1_000
///|
/// Number of bytes in 1 megabyte.
pub const MB : UInt64 = 1_000_000
///|
/// Number of bytes in 1 gigabyte.
pub const GB : UInt64 = 1_000_000_000
///|
/// Number of bytes in 1 terabyte.
pub const TB : UInt64 = 1_000_000_000_000
///|
/// Number of bytes in 1 petabyte.
pub const PB : UInt64 = 1_000_000_000_000_000
///|
/// Number of bytes in 1 kibibyte.
pub const KIB : UInt64 = 1_024
///|
/// Number of bytes in 1 mebibyte.
pub const MIB : UInt64 = 1_048_576
///|
/// Number of bytes in 1 gibibyte.
pub const GIB : UInt64 = 1_073_741_824
///|
/// Number of bytes in 1 tebibyte.
pub const TIB : UInt64 = 1_099_511_627_776
///|
/// Number of bytes in 1 pebibyte.
pub const PIB : UInt64 = 1_125_899_906_842_624
///|
/// IEC (binary) units.
///
/// See .
const UNITS_IEC : String = "KMGTPE"
///|
/// SI (decimal) units.
///
/// See .
const UNITS_SI : String = "kMGTPE"
///|
/// `ln(1024) ~= 6.931`
const LN_KIB : Double = 6.931_471_805_599_453
///|
/// `ln(1000) ~= 6.908`
const LN_KB : Double = 6.907_755_278_982_137
///|
/// Converts a quantity of kilobytes to bytes.
pub fn kb(size : UInt64) -> UInt64 {
size * KB
}
///|
/// Converts a quantity of kibibytes to bytes.
pub fn kib(size : UInt64) -> UInt64 {
size * KIB
}
///|
/// Converts a quantity of megabytes to bytes.
pub fn mb(size : UInt64) -> UInt64 {
size * MB
}
///|
/// Converts a quantity of mebibytes to bytes.
pub fn mib(size : UInt64) -> UInt64 {
size * MIB
}
///|
/// Converts a quantity of gigabytes to bytes.
pub fn gb(size : UInt64) -> UInt64 {
size * GB
}
///|
/// Converts a quantity of gibibytes to bytes.
pub fn gib(size : UInt64) -> UInt64 {
size * GIB
}
///|
/// Converts a quantity of terabytes to bytes.
pub fn tb(size : UInt64) -> UInt64 {
size * TB
}
///|
/// Converts a quantity of tebibytes to bytes.
pub fn tib(size : UInt64) -> UInt64 {
size * TIB
}
///|
/// Converts a quantity of petabytes to bytes.
pub fn pb(size : UInt64) -> UInt64 {
size * PB
}
///|
/// Converts a quantity of pebibytes to bytes.
pub fn pib(size : UInt64) -> UInt64 {
size * PIB
}
///|
/// Byte size representation.
pub struct ByteSize {
size : UInt64
} derive(Show, Eq, Compare, Hash, Default)
///|
/// Constructs a byte size wrapper from a quantity of bytes.
pub fn ByteSize::b(size : UInt64) -> ByteSize {
ByteSize::{ size, }
}
///|
/// Constructs a byte size wrapper from a quantity of kilobytes.
///
/// ## example
/// ```moonbit nocheck
/// let size = ByteSize::kb(1)
/// assert_eq(size.as_u64(), 1000UL)
/// assert_true(@bytesize.ByteSize::kib(4) > @bytesize.ByteSize::kb(4))
/// ```
pub fn ByteSize::kb(size : UInt64) -> ByteSize {
ByteSize::{ size: size * KB }
}
///|
/// Constructs a byte size wrapper from a quantity of kibibytes.
pub fn ByteSize::kib(size : UInt64) -> ByteSize {
ByteSize::{ size: size * KIB }
}
///|
/// Constructs a byte size wrapper from a quantity of megabytes.
pub fn ByteSize::mb(size : UInt64) -> ByteSize {
ByteSize::{ size: size * MB }
}
///|
/// Constructs a byte size wrapper from a quantity of mebibytes.
pub fn ByteSize::mib(size : UInt64) -> ByteSize {
ByteSize::{ size: size * MIB }
}
///|
/// Constructs a byte size wrapper from a quantity of gigabytes.
pub fn ByteSize::gb(size : UInt64) -> ByteSize {
ByteSize::{ size: size * GB }
}
///|
/// Constructs a byte size wrapper from a quantity of gibibytes.
pub fn ByteSize::gib(size : UInt64) -> ByteSize {
ByteSize::{ size: size * GIB }
}
///|
/// Constructs a byte size wrapper from a quantity of terabytes.
pub fn ByteSize::tb(size : UInt64) -> ByteSize {
ByteSize::{ size: size * TB }
}
///|
/// Constructs a byte size wrapper from a quantity of tebibytes.
pub fn ByteSize::tib(size : UInt64) -> ByteSize {
ByteSize::{ size: size * TIB }
}
///|
/// Constructs a byte size wrapper from a quantity of petabytes.
pub fn ByteSize::pb(size : UInt64) -> ByteSize {
ByteSize::{ size: size * PB }
}
///|
/// Constructs a byte size wrapper from a quantity of pebibytes.
pub fn ByteSize::pib(size : UInt64) -> ByteSize {
ByteSize::{ size: size * PIB }
}
///|
/// Returns byte count.
pub fn ByteSize::as_u64(self : ByteSize) -> UInt64 {
self.size
}
///|
/// Returns a formatting display wrapper.
pub fn ByteSize::display(self : ByteSize) -> Display {
Display::new(self.size)
}
///|
/// Convert ByteSize to string using default IEC format.
pub fn ByteSize::to_string(self : ByteSize) -> String {
self.display().to_string()
}
///|
/// Debug representation showing both formatted size and raw bytes.
pub fn ByteSize::debug_string(self : ByteSize) -> String {
"\{self.to_string()} (\{self.size} bytes)"
}
///|
/// Addition: ByteSize + ByteSize = ByteSize
impl Add for ByteSize with add(self, rhs : ByteSize) -> ByteSize {
ByteSize::{ size: rhs.size + self.size }
}
///|
/// Subtraction: ByteSize - ByteSize = ByteSize
impl Sub for ByteSize with sub(self, rhs : ByteSize) -> ByteSize {
ByteSize::{ size: self.size - rhs.size }
}
///|
/// Multiplication: ByteSize * ByteSize = ByteSize
impl Mul for ByteSize with mul(self, rhs : ByteSize) -> ByteSize {
ByteSize::{ size: rhs.size * self.size }
}
///|
test "test_arithmetic_op" {
let x = ByteSize::mb(1)
let y = ByteSize::kb(100)
assert_eq((x + y).as_u64(), 1_100_000UL)
assert_eq((x - y).as_u64(), 900_000UL)
assert_eq((x + ByteSize::b(100_000UL)).as_u64(), 1_100_000UL)
assert_eq((x * ByteSize::b(2UL)).as_u64(), 2_000_000UL)
// Test commutative operations
assert_eq((ByteSize::b(2UL) * x).as_u64(), 2_000_000UL)
assert_eq((ByteSize::b(100_000UL) + x).as_u64(), 1_100_000UL)
}
///|
test "test_arithmetic_primitives" {
let x = ByteSize::mb(1)
assert_eq((x + ByteSize::b(1_000_000)).as_u64(), 2_000_000UL)
assert_eq((x + ByteSize::b(1_000)).as_u64(), 1_001_000UL)
assert_eq((x - ByteSize::b(1_000_000)).as_u64(), 0UL)
assert_eq((x - ByteSize::b(1_000)).as_u64(), 999_000UL)
// Test with different integer types
assert_eq((x + ByteSize::b(1000000)).as_u64(), 2_000_000UL)
assert_eq((x + ByteSize::b(1000)).as_u64(), 1_001_000UL)
}
///|
test "test_comparison" {
assert_true(ByteSize::mb(1) == ByteSize::kb(1000))
assert_true(ByteSize::mib(1) == ByteSize::kib(1024))
assert_true(ByteSize::mb(1) != ByteSize::kib(1024))
assert_true(ByteSize::mb(1) < ByteSize::kib(1024))
assert_true(ByteSize::b(0) < ByteSize::tib(1))
}
///|
test "test_display" {
assert_eq("215 B", ByteSize::b(215).to_string())
assert_eq("1 KiB", ByteSize::kib(1).to_string())
assert_eq("301 KiB", ByteSize::kib(301).to_string())
assert_eq("419 MiB", ByteSize::mib(419).to_string())
assert_eq("518 GiB", ByteSize::gib(518).to_string())
assert_eq("815 TiB", ByteSize::tib(815).to_string())
assert_eq("609 PiB", ByteSize::pib(609).to_string())
}
///|
test "test_display_formats" {
let size = ByteSize::mb(1)
// Test different format styles
assert_eq(size.display().si().to_string(), "1 MB")
assert_eq(size.display().si_short().to_string(), "1M")
}
///|
test "test_default" {
let default_size = ByteSize::{ size: 0UL }
assert_eq(ByteSize::b(0), default_size)
}
///|
test "test_constructor_consistency" {
// Test that constructors work correctly
assert_eq(ByteSize::kb(1).as_u64(), KB)
assert_eq(ByteSize::kib(1).as_u64(), KIB)
assert_eq(ByteSize::mb(1).as_u64(), MB)
assert_eq(ByteSize::mib(1).as_u64(), MIB)
assert_eq(ByteSize::gb(1).as_u64(), GB)
assert_eq(ByteSize::gib(1).as_u64(), GIB)
assert_eq(ByteSize::tb(1).as_u64(), TB)
assert_eq(ByteSize::tib(1).as_u64(), TIB)
assert_eq(ByteSize::pb(1).as_u64(), PB)
assert_eq(ByteSize::pib(1).as_u64(), PIB)
}
///|
test "test_large_values" {
let large_size = ByteSize::tb(5)
let another_large = ByteSize::pb(1)
assert_true(large_size < another_large)
assert_eq((large_size + ByteSize::gb(500)).as_u64(), 5_500_000_000_000UL)
}
///|
test "test_zero_and_small_values" {
let zero = ByteSize::b(0)
let one_byte = ByteSize::b(1)
let small = ByteSize::b(512)
assert_true(zero < one_byte)
assert_true(one_byte < small)
assert_eq((small + one_byte).as_u64(), 513UL)
assert_eq((small - one_byte).as_u64(), 511UL)
}
///|
test "test_edge_cases" {
// Test edge cases and boundary conditions
let max_kb = ByteSize::b(1023)
let min_kib = ByteSize::kib(1)
// 1023 KB should be less than 1 KiB
assert_true(max_kb < min_kib)
// Test multiplication doesn't overflow with reasonable values
let result = ByteSize::mb(1000) * ByteSize::b(2UL)
assert_eq(result.as_u64(), 2_000_000_000UL)
}
///|
test "test_default_method" {
let default_size = ByteSize::default()
assert_eq(default_size, ByteSize::b(0))
}