From 05bcfc48783d933cdbfdea6176f5be21ca3b603c Mon Sep 17 00:00:00 2001 From: Andrew Voynov Date: Fri, 6 Oct 2023 19:44:55 +0300 Subject: [PATCH 1/9] fix: swap values of `LN_KIB` & `LN_KB` --- src/lib.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 4395007..5b6f7fd 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -59,9 +59,10 @@ pub const TIB: u64 = 1_099_511_627_776; pub const PIB: u64 = 1_125_899_906_842_624; static UNITS: &str = "KMGTPE"; -static UNITS_SI: &str = "KMGTPE"; -static LN_KB: f64 = 6.931471806; // ln 1024 -static LN_KIB: f64 = 6.907755279; // ln 1000 +static UNITS_SI: &str = "kMGTPE"; + +static LN_KIB: f64 = 6.931471806; // ln 1024 +static LN_KB: f64 = 6.907755279; // ln 1000 pub fn kb>(size: V) -> u64 { size.into() * KB From 8e7c57dfcac09e0e903fca6a1a29bc8b89192cc0 Mon Sep 17 00:00:00 2001 From: Andrew Voynov Date: Fri, 6 Oct 2023 19:21:41 +0300 Subject: [PATCH 2/9] fix: invert SI/IEC conditions - Conditions that check whether the SI or IEC units must be used were inverted, i.e., when `si_prefix == true` it would use `"iB"` instead of `"B"`. - KB & kiB were used instead of kB & KiB. - Switches (true/false) in tests are also fixed. --- src/lib.rs | 48 +++++++++++++++++++++++++----------------------- src/parse.rs | 2 +- 2 files changed, 26 insertions(+), 24 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 5b6f7fd..c59a664 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -23,8 +23,8 @@ //! ``` //! use bytesize::ByteSize; //! -//! assert_eq!("482.4 GiB", ByteSize::gb(518).to_string_as(true)); -//! assert_eq!("518.0 GB", ByteSize::gb(518).to_string_as(false)); +//! assert_eq!("482.4 GiB", ByteSize::gb(518).to_string_as(false)); +//! assert_eq!("518.0 GB", ByteSize::gb(518).to_string_as(true)); //! ``` mod parse; @@ -177,14 +177,14 @@ impl ByteSize { } pub fn to_string(bytes: u64, si_prefix: bool) -> String { - let unit = if si_prefix { KIB } else { KB }; - let unit_base = if si_prefix { LN_KIB } else { LN_KB }; + let unit = if si_prefix { KB } else { KIB }; + let unit_base = if si_prefix { LN_KB } else { LN_KIB }; let unit_prefix = if si_prefix { UNITS_SI.as_bytes() } else { UNITS.as_bytes() }; - let unit_suffix = if si_prefix { "iB" } else { "B" }; + let unit_suffix = if si_prefix { "B" } else { "iB" }; if bytes < unit { format!("{} B", bytes) @@ -396,6 +396,7 @@ mod tests { assert!(ByteSize::b(0) < ByteSize::tib(1)); } + #[track_caller] fn assert_display(expected: &str, b: ByteSize) { assert_eq!(expected, format!("{}", b)); } @@ -423,39 +424,40 @@ mod tests { assert_eq!("|--357 B---|", format!("|{:-^10}|", ByteSize(357))); } + #[track_caller] fn assert_to_string(expected: &str, b: ByteSize, si: bool) { assert_eq!(expected.to_string(), b.to_string_as(si)); } #[test] fn test_to_string_as() { - assert_to_string("215 B", ByteSize::b(215), true); assert_to_string("215 B", ByteSize::b(215), false); + assert_to_string("215 B", ByteSize::b(215), true); - assert_to_string("1.0 KiB", ByteSize::kib(1), true); - assert_to_string("1.0 KB", ByteSize::kib(1), false); + assert_to_string("1.0 KiB", ByteSize::kib(1), false); + assert_to_string("1.0 kB", ByteSize::kib(1), true); - assert_to_string("293.9 KiB", ByteSize::kb(301), true); - assert_to_string("301.0 KB", ByteSize::kb(301), false); + assert_to_string("293.9 KiB", ByteSize::kb(301), false); + assert_to_string("301.0 kB", ByteSize::kb(301), true); - assert_to_string("1.0 MiB", ByteSize::mib(1), true); - assert_to_string("1048.6 KB", ByteSize::mib(1), false); + assert_to_string("1.0 MiB", ByteSize::mib(1), false); + assert_to_string("1048.6 kB", ByteSize::mib(1), true); // a bug case: https://github.com/flang-project/bytesize/issues/8 - assert_to_string("1.9 GiB", ByteSize::mib(1907), true); - assert_to_string("2.0 GB", ByteSize::mib(1908), false); + assert_to_string("1.9 GiB", ByteSize::mib(1907), false); + assert_to_string("2.0 GB", ByteSize::mib(1908), true); - assert_to_string("399.6 MiB", ByteSize::mb(419), true); - assert_to_string("419.0 MB", ByteSize::mb(419), false); + assert_to_string("399.6 MiB", ByteSize::mb(419), false); + assert_to_string("419.0 MB", ByteSize::mb(419), true); - assert_to_string("482.4 GiB", ByteSize::gb(518), true); - assert_to_string("518.0 GB", ByteSize::gb(518), false); + assert_to_string("482.4 GiB", ByteSize::gb(518), false); + assert_to_string("518.0 GB", ByteSize::gb(518), true); - assert_to_string("741.2 TiB", ByteSize::tb(815), true); - assert_to_string("815.0 TB", ByteSize::tb(815), false); + assert_to_string("741.2 TiB", ByteSize::tb(815), false); + assert_to_string("815.0 TB", ByteSize::tb(815), true); - assert_to_string("540.9 PiB", ByteSize::pb(609), true); - assert_to_string("609.0 PB", ByteSize::pb(609), false); + assert_to_string("540.9 PiB", ByteSize::pb(609), false); + assert_to_string("609.0 PB", ByteSize::pb(609), true); } #[test] @@ -465,6 +467,6 @@ mod tests { #[test] fn test_to_string() { - assert_to_string("609.0 PB", ByteSize::pb(609), false); + assert_to_string("609.0 PB", ByteSize::pb(609), true); } } diff --git a/src/parse.rs b/src/parse.rs index 218fe8b..8d2ca85 100644 --- a/src/parse.rs +++ b/src/parse.rs @@ -234,7 +234,7 @@ mod tests { assert_eq!(parse(&format!("{}", parse("128GB"))), 128 * Unit::GigaByte); assert_eq!( - parse(&crate::to_string(parse("128.000 GiB"), true)), + parse(&crate::to_string(parse("128.000 GiB"), false)), 128 * Unit::GibiByte ); } From d9eef5131d927c0d751ca64354ab912f61a4f53f Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Mon, 10 Feb 2025 00:32:13 +0000 Subject: [PATCH 3/9] fix: format with IEC (binary) by default --- CHANGELOG.md | 4 ++-- src/lib.rs | 20 +++++++++++--------- src/serde.rs | 3 +-- 3 files changed, 14 insertions(+), 13 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b1378a3..ccb8e3b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,8 +2,8 @@ ## Unreleased -- Use SI format by default with `Display`. -- Use "KiB" for SI unit. +- Use IEC (binary) format by default with `Display`. +- Use "kB" for SI unit. - Implement `Sub` for `ByteSize`. - Implement `Sub>` for `ByteSize`. - Implement `SubAssign` for `ByteSize`. diff --git a/src/lib.rs b/src/lib.rs index c59a664..9747d27 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -179,12 +179,15 @@ impl ByteSize { pub fn to_string(bytes: u64, si_prefix: bool) -> String { let unit = if si_prefix { KB } else { KIB }; let unit_base = if si_prefix { LN_KB } else { LN_KIB }; - let unit_prefix = if si_prefix { - UNITS_SI.as_bytes() - } else { - UNITS.as_bytes() + + let unit_prefix = match si_prefix { + true => UNITS_SI.as_bytes(), + false => UNITS.as_bytes(), + }; + let unit_suffix = match si_prefix { + true => "B", + false => "iB", }; - let unit_suffix = if si_prefix { "B" } else { "iB" }; if bytes < unit { format!("{} B", bytes) @@ -206,7 +209,7 @@ pub fn to_string(bytes: u64, si_prefix: bool) -> String { impl Display for ByteSize { fn fmt(&self, f: &mut Formatter) -> fmt::Result { - f.pad(&to_string(self.0, true)) + f.pad(&to_string(self.0, false)) } } @@ -440,10 +443,9 @@ mod tests { assert_to_string("293.9 KiB", ByteSize::kb(301), false); assert_to_string("301.0 kB", ByteSize::kb(301), true); - assert_to_string("1.0 MiB", ByteSize::mib(1), false); - assert_to_string("1048.6 kB", ByteSize::mib(1), true); + assert_to_string("1024.0 KiB", ByteSize::mib(1), false); + assert_to_string("1.0 MB", ByteSize::mib(1), true); - // a bug case: https://github.com/flang-project/bytesize/issues/8 assert_to_string("1.9 GiB", ByteSize::mib(1907), false); assert_to_string("2.0 GB", ByteSize::mib(1908), true); diff --git a/src/serde.rs b/src/serde.rs index 5cda0d3..5121953 100644 --- a/src/serde.rs +++ b/src/serde.rs @@ -92,10 +92,9 @@ mod tests { } #[test] - fn test_serde_json() { let json = serde_json::to_string(&ByteSize::mib(1)).unwrap(); - assert_eq!(json, "\"1.0 MiB\""); + assert_eq!(json, "\"1024.0 KiB\""); let deserialized = serde_json::from_str::(&json).unwrap(); assert_eq!(deserialized.0, 1048576); From 3ecd475f846b5b7962873ee3acdb8b55ac904ab7 Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Mon, 10 Feb 2025 00:33:38 +0000 Subject: [PATCH 4/9] docs: doc units_* statics --- src/lib.rs | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 9747d27..74160a6 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -58,7 +58,15 @@ pub const TIB: u64 = 1_099_511_627_776; /// bytes size for 1 pebibyte pub const PIB: u64 = 1_125_899_906_842_624; -static UNITS: &str = "KMGTPE"; +/// IEC (binary) units. +/// +/// See . +static UNITS_IEC: &str = "KMGTPE"; + +/// SI (decimal) units. +/// +/// +/// See . static UNITS_SI: &str = "kMGTPE"; static LN_KIB: f64 = 6.931471806; // ln 1024 @@ -182,7 +190,7 @@ pub fn to_string(bytes: u64, si_prefix: bool) -> String { let unit_prefix = match si_prefix { true => UNITS_SI.as_bytes(), - false => UNITS.as_bytes(), + false => UNITS_IEC.as_bytes(), }; let unit_suffix = match si_prefix { true => "B", From c72ffa92a7ad4757cc74c6dfac30ecc4a541c922 Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Mon, 10 Feb 2025 00:35:06 +0000 Subject: [PATCH 5/9] refactor: move statics to consts --- src/lib.rs | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 74160a6..eeb65a8 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -61,16 +61,19 @@ pub const PIB: u64 = 1_125_899_906_842_624; /// IEC (binary) units. /// /// See . -static UNITS_IEC: &str = "KMGTPE"; +const UNITS_IEC: &str = "KMGTPE"; /// SI (decimal) units. /// /// /// See . -static UNITS_SI: &str = "kMGTPE"; +const UNITS_SI: &str = "kMGTPE"; -static LN_KIB: f64 = 6.931471806; // ln 1024 -static LN_KB: f64 = 6.907755279; // ln 1000 +/// `ln(1024) ~= 6.931` +const LN_KIB: f64 = 6.931471806; + +/// `ln(1000) ~= 6.908` +const LN_KB: f64 = 6.907755279; pub fn kb>(size: V) -> u64 { size.into() * KB From 9fae90c33874bea2851a57bd9493c0d685a4e42e Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Mon, 10 Feb 2025 00:39:45 +0000 Subject: [PATCH 6/9] refactor: introduce format enum --- src/lib.rs | 37 +++++++++++++++++++++++++++---------- 1 file changed, 27 insertions(+), 10 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index eeb65a8..914105f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -75,6 +75,13 @@ const LN_KIB: f64 = 6.931471806; /// `ln(1000) ~= 6.908` const LN_KB: f64 = 6.907755279; +#[derive(Debug, Clone, Default)] +pub enum Format { + #[default] + IEC, + SI, +} + pub fn kb>(size: V) -> u64 { size.into() * KB } @@ -187,17 +194,27 @@ impl ByteSize { } } -pub fn to_string(bytes: u64, si_prefix: bool) -> String { - let unit = if si_prefix { KB } else { KIB }; - let unit_base = if si_prefix { LN_KB } else { LN_KIB }; +pub fn to_string(bytes: u64, si_unit: bool) -> String { + to_string_format(bytes, if si_unit { Format::SI } else { Format::IEC }) +} + +pub fn to_string_format(bytes: u64, format: Format) -> String { + let unit = match format { + Format::IEC => KIB, + Format::SI => KB, + }; + let unit_base = match format { + Format::IEC => LN_KIB, + Format::SI => LN_KB, + }; - let unit_prefix = match si_prefix { - true => UNITS_SI.as_bytes(), - false => UNITS_IEC.as_bytes(), + let unit_prefix = match format { + Format::IEC => UNITS_IEC.as_bytes(), + Format::SI => UNITS_SI.as_bytes(), }; - let unit_suffix = match si_prefix { - true => "B", - false => "iB", + let unit_suffix = match format { + Format::IEC => "iB", + Format::SI => "B", }; if bytes < unit { @@ -220,7 +237,7 @@ pub fn to_string(bytes: u64, si_prefix: bool) -> String { impl Display for ByteSize { fn fmt(&self, f: &mut Formatter) -> fmt::Result { - f.pad(&to_string(self.0, false)) + f.pad(&to_string_format(self.0, Format::IEC)) } } From ee144fa4e70ea8fd0b59a361b1593d63384e9c24 Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Mon, 10 Feb 2025 00:42:18 +0000 Subject: [PATCH 7/9] test: use to_string_format in tests --- src/lib.rs | 42 +++++++++++++++++++++--------------------- src/parse.rs | 4 +++- 2 files changed, 24 insertions(+), 22 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 914105f..f8de516 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -456,38 +456,38 @@ mod tests { } #[track_caller] - fn assert_to_string(expected: &str, b: ByteSize, si: bool) { - assert_eq!(expected.to_string(), b.to_string_as(si)); + fn assert_to_string(expected: &str, b: ByteSize, format: Format) { + assert_eq!(expected.to_string(), to_string_format(b.0, format)); } #[test] fn test_to_string_as() { - assert_to_string("215 B", ByteSize::b(215), false); - assert_to_string("215 B", ByteSize::b(215), true); + assert_to_string("215 B", ByteSize::b(215), Format::IEC); + assert_to_string("215 B", ByteSize::b(215), Format::SI); - assert_to_string("1.0 KiB", ByteSize::kib(1), false); - assert_to_string("1.0 kB", ByteSize::kib(1), true); + assert_to_string("1.0 KiB", ByteSize::kib(1), Format::IEC); + assert_to_string("1.0 kB", ByteSize::kib(1), Format::SI); - assert_to_string("293.9 KiB", ByteSize::kb(301), false); - assert_to_string("301.0 kB", ByteSize::kb(301), true); + assert_to_string("293.9 KiB", ByteSize::kb(301), Format::IEC); + assert_to_string("301.0 kB", ByteSize::kb(301), Format::SI); - assert_to_string("1024.0 KiB", ByteSize::mib(1), false); - assert_to_string("1.0 MB", ByteSize::mib(1), true); + assert_to_string("1024.0 KiB", ByteSize::mib(1), Format::IEC); + assert_to_string("1.0 MB", ByteSize::mib(1), Format::SI); - assert_to_string("1.9 GiB", ByteSize::mib(1907), false); - assert_to_string("2.0 GB", ByteSize::mib(1908), true); + assert_to_string("1.9 GiB", ByteSize::mib(1907), Format::IEC); + assert_to_string("2.0 GB", ByteSize::mib(1908), Format::SI); - assert_to_string("399.6 MiB", ByteSize::mb(419), false); - assert_to_string("419.0 MB", ByteSize::mb(419), true); + assert_to_string("399.6 MiB", ByteSize::mb(419), Format::IEC); + assert_to_string("419.0 MB", ByteSize::mb(419), Format::SI); - assert_to_string("482.4 GiB", ByteSize::gb(518), false); - assert_to_string("518.0 GB", ByteSize::gb(518), true); + assert_to_string("482.4 GiB", ByteSize::gb(518), Format::IEC); + assert_to_string("518.0 GB", ByteSize::gb(518), Format::SI); - assert_to_string("741.2 TiB", ByteSize::tb(815), false); - assert_to_string("815.0 TB", ByteSize::tb(815), true); + assert_to_string("741.2 TiB", ByteSize::tb(815), Format::IEC); + assert_to_string("815.0 TB", ByteSize::tb(815), Format::SI); - assert_to_string("540.9 PiB", ByteSize::pb(609), false); - assert_to_string("609.0 PB", ByteSize::pb(609), true); + assert_to_string("540.9 PiB", ByteSize::pb(609), Format::IEC); + assert_to_string("609.0 PB", ByteSize::pb(609), Format::SI); } #[test] @@ -497,6 +497,6 @@ mod tests { #[test] fn test_to_string() { - assert_to_string("609.0 PB", ByteSize::pb(609), true); + assert_to_string("609.0 PB", ByteSize::pb(609), Format::SI); } } diff --git a/src/parse.rs b/src/parse.rs index 8d2ca85..ea71ee7 100644 --- a/src/parse.rs +++ b/src/parse.rs @@ -181,6 +181,8 @@ impl std::str::FromStr for Unit { #[cfg(test)] mod tests { + use crate::to_string_format; + use super::*; #[test] @@ -234,7 +236,7 @@ mod tests { assert_eq!(parse(&format!("{}", parse("128GB"))), 128 * Unit::GigaByte); assert_eq!( - parse(&crate::to_string(parse("128.000 GiB"), false)), + parse(&to_string_format(parse("128.000 GiB"), crate::Format::IEC,)), 128 * Unit::GibiByte ); } From 80881ac7fb566fb93a09f41c29beacf60884bed1 Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Mon, 10 Feb 2025 01:17:01 +0000 Subject: [PATCH 8/9] chore: expand debug impl --- src/lib.rs | 2 +- src/parse.rs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index f8de516..c14e4a9 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -243,7 +243,7 @@ impl Display for ByteSize { impl Debug for ByteSize { fn fmt(&self, f: &mut Formatter) -> fmt::Result { - write!(f, "{}", self) + ::fmt(self, f) } } diff --git a/src/parse.rs b/src/parse.rs index ea71ee7..3912eb5 100644 --- a/src/parse.rs +++ b/src/parse.rs @@ -236,8 +236,8 @@ mod tests { assert_eq!(parse(&format!("{}", parse("128GB"))), 128 * Unit::GigaByte); assert_eq!( - parse(&to_string_format(parse("128.000 GiB"), crate::Format::IEC,)), - 128 * Unit::GibiByte + parse(&to_string_format(parse("128.000 GiB"), crate::Format::IEC)), + 128 * Unit::GibiByte, ); } } From 81d885fcea548b85ee58daeb723f5fe37f7369f5 Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Tue, 11 Feb 2025 23:06:36 +0000 Subject: [PATCH 9/9] fix: increase precision of LN_ constants --- Cargo.toml | 6 +++++- src/lib.rs | 7 +++---- src/serde.rs | 2 +- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index fc54e5e..92ea6ad 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,7 +2,11 @@ name = "bytesize" description = "A utility for human-readable byte count representations" version = "1.3.0" -authors = ["Hyunsik Choi ", "MrCroxx "] +authors = [ + "Hyunsik Choi ", + "MrCroxx ", + "Rob Ede ", +] keywords = ["byte", "byte-size", "utility", "human-readable", "format"] categories = ["development-tools", "filesystem"] repository = "https://github.com/bytesize-rs/bytesize" diff --git a/src/lib.rs b/src/lib.rs index c14e4a9..2b37cd1 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -65,15 +65,14 @@ const UNITS_IEC: &str = "KMGTPE"; /// SI (decimal) units. /// -/// /// See . const UNITS_SI: &str = "kMGTPE"; /// `ln(1024) ~= 6.931` -const LN_KIB: f64 = 6.931471806; +const LN_KIB: f64 = 6.931_471_805_599_453; /// `ln(1000) ~= 6.908` -const LN_KB: f64 = 6.907755279; +const LN_KB: f64 = 6.907_755_278_982_137; #[derive(Debug, Clone, Default)] pub enum Format { @@ -471,7 +470,7 @@ mod tests { assert_to_string("293.9 KiB", ByteSize::kb(301), Format::IEC); assert_to_string("301.0 kB", ByteSize::kb(301), Format::SI); - assert_to_string("1024.0 KiB", ByteSize::mib(1), Format::IEC); + assert_to_string("1.0 MiB", ByteSize::mib(1), Format::IEC); assert_to_string("1.0 MB", ByteSize::mib(1), Format::SI); assert_to_string("1.9 GiB", ByteSize::mib(1907), Format::IEC); diff --git a/src/serde.rs b/src/serde.rs index 5121953..3cd3a41 100644 --- a/src/serde.rs +++ b/src/serde.rs @@ -94,7 +94,7 @@ mod tests { #[test] fn test_serde_json() { let json = serde_json::to_string(&ByteSize::mib(1)).unwrap(); - assert_eq!(json, "\"1024.0 KiB\""); + assert_eq!(json, "\"1.0 MiB\""); let deserialized = serde_json::from_str::(&json).unwrap(); assert_eq!(deserialized.0, 1048576);