formatting: fix gibibytes vs gigabytes issue

This commit is contained in:
João M. Bezerra 2023-09-04 20:54:49 -03:00
parent 76116ed5ec
commit 693167e933

View File

@ -88,31 +88,35 @@ pub fn nice_directory_display(path: &Path) -> Cow<str> {
} }
/// Struct useful to printing bytes as kB, MB, GB, etc. /// Struct useful to printing bytes as kB, MB, GB, etc.
pub struct Bytes { pub struct Bytes(f64);
bytes: f64,
}
impl Bytes { impl Bytes {
const UNIT_PREFIXES: [&'static str; 6] = ["", "k", "M", "G", "T", "P"]; const UNIT_PREFIXES: [&'static str; 6] = ["", "ki", "Mi", "Gi", "Ti", "Pi"];
/// Create a new Bytes. /// Create a new Bytes.
pub fn new(bytes: u64) -> Self { pub fn new(bytes: u64) -> Self {
Self { bytes: bytes as f64 } Self(bytes as f64)
} }
} }
impl std::fmt::Display for Bytes { impl std::fmt::Display for Bytes {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let num = self.bytes; let &Self(num) = self;
debug_assert!(num >= 0.0); debug_assert!(num >= 0.0);
if num < 1_f64 { if num < 1_f64 {
return write!(f, "{} B", num); return write!(f, "{} B", num);
} }
let delimiter = 1000_f64; let delimiter = 1000_f64;
let exponent = cmp::min((num.ln() / 6.90775).floor() as i32, 4); let exponent = cmp::min((num.ln() / 6.90775).floor() as i32, 4);
write!(f, "{:.2} ", num / delimiter.powi(exponent))?; write!(
write!(f, "{}B", Bytes::UNIT_PREFIXES[exponent as usize]) f,
"{:.2} {}B",
num / delimiter.powi(exponent),
Bytes::UNIT_PREFIXES[exponent as usize]
)
} }
} }
@ -133,26 +137,30 @@ mod tests {
assert_eq!("0 B", format_bytes(0)); // This is weird assert_eq!("0 B", format_bytes(0)); // This is weird
assert_eq!("1.00 B", format_bytes(b)); assert_eq!("1.00 B", format_bytes(b));
assert_eq!("999.00 B", format_bytes(b * 999)); assert_eq!("999.00 B", format_bytes(b * 999));
assert_eq!("12.00 MB", format_bytes(mb * 12)); assert_eq!("12.00 MiB", format_bytes(mb * 12));
assert_eq!("123.00 MB", format_bytes(mb * 123)); assert_eq!("123.00 MiB", format_bytes(mb * 123));
assert_eq!("5.50 MB", format_bytes(mb * 5 + kb * 500)); assert_eq!("5.50 MiB", format_bytes(mb * 5 + kb * 500));
assert_eq!("7.54 GB", format_bytes(gb * 7 + 540 * mb)); assert_eq!("7.54 GiB", format_bytes(gb * 7 + 540 * mb));
assert_eq!("1.20 TB", format_bytes(gb * 1200)); assert_eq!("1.20 TiB", format_bytes(gb * 1200));
// bytes // bytes
assert_eq!("234.00 B", format_bytes(234)); assert_eq!("234.00 B", format_bytes(234));
assert_eq!("999.00 B", format_bytes(999)); assert_eq!("999.00 B", format_bytes(999));
// kilobytes // kilobytes
assert_eq!("2.23 kB", format_bytes(2234)); assert_eq!("2.23 kiB", format_bytes(2234));
assert_eq!("62.50 kB", format_bytes(62500)); assert_eq!("62.50 kiB", format_bytes(62500));
assert_eq!("329.99 kB", format_bytes(329990)); assert_eq!("329.99 kiB", format_bytes(329990));
// megabytes // megabytes
assert_eq!("2.75 MB", format_bytes(2750000)); assert_eq!("2.75 MiB", format_bytes(2750000));
assert_eq!("55.00 MB", format_bytes(55000000)); assert_eq!("55.00 MiB", format_bytes(55000000));
assert_eq!("987.65 MB", format_bytes(987654321)); assert_eq!("987.65 MiB", format_bytes(987654321));
// gigabytes // gigabytes
assert_eq!("5.28 GB", format_bytes(5280000000)); assert_eq!("5.28 GiB", format_bytes(5280000000));
assert_eq!("95.20 GB", format_bytes(95200000000)); assert_eq!("95.20 GiB", format_bytes(95200000000));
assert_eq!("302.00 GB", format_bytes(302000000000)); assert_eq!("302.00 GiB", format_bytes(302000000000));
assert_eq!("302.99 GiB", format_bytes(302990000000));
// Weird aproximation cases:
assert_eq!("999.90 GiB", format_bytes(999900000000));
assert_eq!("1.00 TiB", format_bytes(999990000000));
} }
} }