From 5f599dce8dd0939855569aa36cbe15a8bbaa9594 Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Wed, 12 Feb 2025 02:42:08 +0000 Subject: [PATCH 1/3] feat: display type --- examples/ls.rs | 2 +- src/display.rs | 236 +++++++++++++++++++++++++++++++++++++++++++++++++ src/lib.rs | 132 +++++++-------------------- src/parse.rs | 6 +- 4 files changed, 270 insertions(+), 106 deletions(-) create mode 100644 src/display.rs diff --git a/examples/ls.rs b/examples/ls.rs index 7b380b3a..72383f23 100644 --- a/examples/ls.rs +++ b/examples/ls.rs @@ -15,7 +15,7 @@ fn main() -> io::Result<()> { if md.is_file() { let file_size = md.len(); - let file_size = bytesize::ByteSize::b(file_size); + let file_size = bytesize::ByteSize::b(file_size).display().iec_short(); println!("{file_size}\t{file_name}"); } else { diff --git a/src/display.rs b/src/display.rs new file mode 100644 index 00000000..53c8726c --- /dev/null +++ b/src/display.rs @@ -0,0 +1,236 @@ +use core::{fmt, write}; + +use crate::ByteSize; + +/// Format / style to use when displaying a [`ByteSize`]. +#[derive(Debug, Clone, Copy)] +pub(crate) enum Format { + Iec, + IecShort, + Si, + SiShort, +} + +impl Format { + fn unit(self) -> u64 { + match self { + Format::Iec | Format::IecShort => crate::KIB, + Format::Si | Format::SiShort => crate::KB, + } + } + + fn unit_base(self) -> f64 { + match self { + Format::Iec | Format::IecShort => crate::LN_KIB, + Format::Si | Format::SiShort => crate::LN_KB, + } + } + + fn unit_prefixes(self) -> &'static [u8] { + match self { + Format::Iec | Format::IecShort => crate::UNITS_IEC.as_bytes(), + Format::Si | Format::SiShort => crate::UNITS_SI.as_bytes(), + } + } + + fn unit_separator(self) -> &'static str { + match self { + Format::Iec | Format::Si => " ", + Format::IecShort | Format::SiShort => "", + } + } + + fn unit_suffix(self) -> &'static str { + match self { + Format::Iec => "iB", + Format::Si => "B", + Format::IecShort | Format::SiShort => "", + } + } +} + +/// Formatting display wrapper for [`ByteSize`]. +/// +/// Supports various styles, see methods. By default, the [`iec()`](Self::iec()) style is used. +/// +/// # Examples +/// +/// ``` +/// # use bytesize::ByteSize; +/// assert_eq!( +/// "1.0 MiB", +/// ByteSize::mib(1).display().iec().to_string(), +/// ); +/// +/// assert_eq!( +/// "42.0k", +/// ByteSize::kb(42).display().si_short().to_string(), +/// ); +/// ``` +#[derive(Debug, Clone)] +pub struct Display { + pub(crate) byte_size: ByteSize, + pub(crate) format: Format, +} + +impl Display { + /// Format using IEC (binary) units. + /// + /// E.g., `4.2 MiB`. + #[must_use] + #[doc(alias = "binary")] + pub fn iec(mut self) -> Self { + self.format = Format::Iec; + self + } + + /// Format using SI (decimal) units. + /// + /// E.g., `4.2 MB`. + /// + /// Designed to produce output compatible with `sort -h`. + #[must_use] + #[doc(alias = "binary")] + pub fn iec_short(mut self) -> Self { + self.format = Format::IecShort; + self + } + + /// Format using a short style and IEC (binary) units. + /// + /// E.g., `4.2M`. + #[must_use] + #[doc(alias = "decimal")] + pub fn si(mut self) -> Self { + self.format = Format::Si; + self + } + + /// Format using a short style and SI (decimal) units. + /// + /// E.g., `4.2M`. + #[must_use] + #[doc(alias = "decimal")] + pub fn si_short(mut self) -> Self { + self.format = Format::SiShort; + self + } +} + +impl fmt::Display for Display { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let bytes = self.byte_size.as_u64(); + + let unit = self.format.unit(); + let unit_base = self.format.unit_base(); + + let unit_prefixes = self.format.unit_prefixes(); + let unit_separator = self.format.unit_separator(); + let unit_suffix = self.format.unit_suffix(); + + if bytes < unit { + write!(f, "{bytes}{unit_separator}B")?; + } else { + let size = bytes as f64; + let exp = match (size.ln() / unit_base) as usize { + 0 => 1, + e => e, + }; + + let unit_prefix = unit_prefixes[exp - 1] as char; + + write!( + f, + "{:.1}{unit_separator}{unit_prefix}{unit_suffix}", + (size / unit.pow(exp as u32) as f64), + )?; + } + + Ok(()) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn to_string_iec() { + let display = Display { + byte_size: ByteSize::gib(1), + format: Format::Iec, + }; + assert_eq!("1.0 GiB", display.to_string()); + + let display = Display { + byte_size: ByteSize::gb(1), + format: Format::Iec, + }; + assert_eq!("953.7 MiB", display.to_string()); + } + + #[test] + fn to_string_si() { + let display = Display { + byte_size: ByteSize::gib(1), + format: Format::Si, + }; + assert_eq!("1.1 GB", display.to_string()); + + let display = Display { + byte_size: ByteSize::gb(1), + format: Format::Si, + }; + assert_eq!("1.0 GB", display.to_string()); + } + + #[test] + fn to_string_short() { + let display = Display { + byte_size: ByteSize::gib(1), + format: Format::IecShort, + }; + assert_eq!("1.0G", display.to_string()); + + let display = Display { + byte_size: ByteSize::gb(1), + format: Format::IecShort, + }; + assert_eq!("953.7M", display.to_string()); + } + + #[track_caller] + fn assert_to_string(expected: &str, byte_size: ByteSize, format: Format) { + assert_eq!(expected, Display { byte_size, format }.to_string()); + } + + #[test] + fn test_to_string_as() { + 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), Format::Iec); + assert_to_string("1.0 kB", ByteSize::kib(1), Format::Si); + + 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("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); + assert_to_string("2.0 GB", ByteSize::mib(1908), Format::Si); + + 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), Format::Iec); + assert_to_string("518.0 GB", ByteSize::gb(518), Format::Si); + + 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), Format::Iec); + assert_to_string("609.0 PB", ByteSize::pb(609), Format::Si); + } +} diff --git a/src/lib.rs b/src/lib.rs index 4e0e0c1e..b6fbeca7 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -24,7 +24,9 @@ //! ``` //! use bytesize::ByteSize; //! -//! assert_eq!("482.4 GiB", ByteSize::gb(518).to_string()); +//! assert_eq!("518.0 GiB", ByteSize::gib(518).display().iec().to_string()); +//! assert_eq!("556.2 GB", ByteSize::gib(518).display().si().to_string()); +//! assert_eq!("518.0G", ByteSize::gib(518).display().iec_short().to_string()); //! ``` //! //! Arithmetic operations are supported. @@ -39,16 +41,22 @@ //! assert_eq!(ByteSize::gb(996), minus); //! ``` +use std::{ + fmt, + ops::{Add, AddAssign, Mul, MulAssign, Sub, SubAssign}, +}; + #[cfg(feature = "arbitrary")] mod arbitrary; +mod display; mod parse; #[cfg(feature = "serde")] mod serde; -use std::fmt::{self, Debug, Display, Formatter}; -use std::ops::{Add, AddAssign, Mul, MulAssign, Sub, SubAssign}; +pub use crate::display::Display; +use crate::display::Format; -/// Number of bytes in 1 kilobyte. +/// Number of bytes in 1 kilobyte pub const KB: u64 = 1_000; /// Number of bytes in 1 megabyte. pub const MB: u64 = 1_000_000; @@ -86,21 +94,6 @@ const LN_KIB: f64 = 6.931_471_805_599_453; /// `ln(1000) ~= 6.908` const LN_KB: f64 = 6.907_755_278_982_137; -/// Formatting style. -#[derive(Debug, Clone, Default)] -pub enum Format { - /// IEC (binary) representation. - /// - /// E.g., "1.0 MiB" - #[default] - IEC, - - /// SI (decimal) representation. - /// - /// E.g., "1.02 MB" - SI, -} - /// Converts a quantity of kilobytes to bytes. pub fn kb(size: impl Into) -> u64 { size.into() * KB @@ -227,55 +220,32 @@ impl ByteSize { pub const fn as_u64(&self) -> u64 { self.0 } -} -/// Constructs human-readable string representation of `bytes` with given `format` style. -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 format { - Format::IEC => UNITS_IEC.as_bytes(), - Format::SI => UNITS_SI.as_bytes(), - }; - let unit_suffix = match format { - Format::IEC => "iB", - Format::SI => "B", - }; - - if bytes < unit { - format!("{} B", bytes) - } else { - let size = bytes as f64; - let exp = match (size.ln() / unit_base) as usize { - 0 => 1, - e => e, - }; - - format!( - "{:.1} {}{}", - (size / unit.pow(exp as u32) as f64), - unit_prefix[exp - 1] as char, - unit_suffix - ) + /// Returns a formatting display wrapper. + pub fn display(&self) -> Display { + Display { + byte_size: *self, + format: Format::Iec, + } } } -impl Display for ByteSize { - fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { - f.pad(&to_string_format(self.0, Format::IEC)) +impl fmt::Display for ByteSize { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let display = self.display(); + + if f.width().is_none() && f.precision().is_none() { + // allocation-free fast path for when no formatting options are specified + write!(f, "{display}") + } else { + f.pad(&display.to_string()) + } } } -impl Debug for ByteSize { - fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { - ::fmt(self, f) +impl fmt::Debug for ByteSize { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "{} ({} bytes)", self, self.0) } } @@ -509,48 +479,8 @@ mod tests { assert_eq!("|--357 B---|", format!("|{:-^10}|", ByteSize(357))); } - #[track_caller] - 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), Format::IEC); - assert_to_string("215 B", ByteSize::b(215), Format::SI); - - 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), Format::IEC); - assert_to_string("301.0 kB", ByteSize::kb(301), Format::SI); - - 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); - assert_to_string("2.0 GB", ByteSize::mib(1908), Format::SI); - - 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), Format::IEC); - assert_to_string("518.0 GB", ByteSize::gb(518), Format::SI); - - 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), Format::IEC); - assert_to_string("609.0 PB", ByteSize::pb(609), Format::SI); - } - #[test] fn test_default() { assert_eq!(ByteSize::b(0), ByteSize::default()); } - - #[test] - fn test_to_string() { - assert_to_string("609.0 PB", ByteSize::pb(609), Format::SI); - } } diff --git a/src/parse.rs b/src/parse.rs index 83c5c5da..dc38e65b 100644 --- a/src/parse.rs +++ b/src/parse.rs @@ -181,8 +181,6 @@ impl std::str::FromStr for Unit { #[cfg(test)] mod tests { - use crate::to_string_format; - use super::*; #[test] @@ -234,9 +232,9 @@ mod tests { s.parse::().unwrap().0 } - assert_eq!(parse(&format!("{}", parse("128GB"))), 128 * Unit::GigaByte); + assert_eq!(parse(&parse("128GB").to_string()), 128 * Unit::GigaByte); assert_eq!( - parse(&to_string_format(parse("128.000 GiB"), crate::Format::IEC)), + parse(&ByteSize(parse("128.000 GiB")).to_string()), 128 * Unit::GibiByte, ); } From 4725e58a56b0a61846f0751a3c706ee9a3615946 Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Thu, 13 Feb 2025 21:21:18 +0000 Subject: [PATCH 2/3] test: add display bench --- Cargo.lock | 280 ++++++++++++++++++++++++++++++++++++++++++++- Cargo.toml | 7 +- benches/display.rs | 47 ++++++++ justfile | 4 +- 4 files changed, 332 insertions(+), 6 deletions(-) create mode 100644 benches/display.rs diff --git a/Cargo.lock b/Cargo.lock index f29b3d09..7df3cd41 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -11,17 +11,30 @@ dependencies = [ "memchr", ] +[[package]] +name = "anstyle" +version = "1.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9" + [[package]] name = "arbitrary" version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dde20b3d026af13f561bdd0f15edf01fc734f0dafcedbaf42bba506a9517f223" +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + [[package]] name = "bytesize" version = "1.3.0" dependencies = [ "arbitrary", + "divan", "quickcheck", "serde", "serde_json", @@ -34,6 +47,63 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "clap" +version = "4.3.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb690e81c7840c0d7aade59f242ea3b41b9bc27bcd5997890e7702ae4b32e487" +dependencies = [ + "clap_builder", +] + +[[package]] +name = "clap_builder" +version = "4.3.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ed2e96bc16d8d740f6f48d663eddf4b8a0983e79210fd55479b7bcd0a69860e" +dependencies = [ + "anstyle", + "clap_lex", + "terminal_size", +] + +[[package]] +name = "clap_lex" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2da6da31387c7e4ef160ffab6d5e7f00c42626fe39aea70a7b0f1773f7dd6c1b" + +[[package]] +name = "condtype" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf0a07a401f374238ab8e2f11a104d2851bf9ce711ec69804834de8af45c7af" + +[[package]] +name = "divan" +version = "0.1.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e05d17bd4ff1c1e7998ed4623d2efd91f72f1e24141ac33aac9377974270e1f" +dependencies = [ + "cfg-if", + "clap", + "condtype", + "divan-macros", + "libc", + "regex-lite", +] + +[[package]] +name = "divan-macros" +version = "0.1.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b4464d46ce68bfc7cb76389248c7c254def7baca8bece0693b02b83842c4c88" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "env_logger" version = "0.8.4" @@ -50,6 +120,16 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" +[[package]] +name = "errno" +version = "0.3.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33d852cb9b869c2a9b3df2f71a3074817f01e1844f839a144f5fcef059a4eb5d" +dependencies = [ + "libc", + "windows-sys 0.59.0", +] + [[package]] name = "getrandom" version = "0.2.15" @@ -67,6 +147,12 @@ version = "0.15.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" +[[package]] +name = "hermit-abi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" + [[package]] name = "indexmap" version = "2.7.1" @@ -77,6 +163,17 @@ dependencies = [ "hashbrown", ] +[[package]] +name = "io-lifetimes" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eae7b9aee968036d54dce06cebaefd919e4472e753296daccd6d344e3e2df0c2" +dependencies = [ + "hermit-abi", + "libc", + "windows-sys 0.48.0", +] + [[package]] name = "itoa" version = "1.0.14" @@ -89,6 +186,12 @@ version = "0.2.169" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a" +[[package]] +name = "linux-raw-sys" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519" + [[package]] name = "log" version = "0.4.25" @@ -171,12 +274,32 @@ dependencies = [ "regex-syntax", ] +[[package]] +name = "regex-lite" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53a49587ad06b26609c52e423de037e7f57f20d53535d66e08c695f347df952a" + [[package]] name = "regex-syntax" version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" +[[package]] +name = "rustix" +version = "0.37.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "519165d378b97752ca44bbe15047d5d3409e875f39327546b42ac81d7e18c1b6" +dependencies = [ + "bitflags", + "errno", + "io-lifetimes", + "libc", + "linux-raw-sys", + "windows-sys 0.48.0", +] + [[package]] name = "ryu" version = "1.0.19" @@ -235,6 +358,16 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "terminal_size" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e6bf6f19e9f8ed8d4048dc22981458ebcf406d67e94cd422e5ecd73d63b3237" +dependencies = [ + "rustix", + "windows-sys 0.48.0", +] + [[package]] name = "toml" version = "0.8.20" @@ -258,9 +391,9 @@ dependencies = [ [[package]] name = "toml_edit" -version = "0.22.23" +version = "0.22.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02a8b472d1a3d7c18e2d61a489aee3453fd9031c33e4f55bd533f4a7adca1bee" +checksum = "17b4795ff5edd201c7cd6dca065ae59972ce77d1b80fa0a84d94950ece7d1474" dependencies = [ "indexmap", "serde", @@ -281,11 +414,150 @@ version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" +[[package]] +name = "windows-sys" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +dependencies = [ + "windows-targets 0.48.5", +] + +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-targets" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" +dependencies = [ + "windows_aarch64_gnullvm 0.48.5", + "windows_aarch64_msvc 0.48.5", + "windows_i686_gnu 0.48.5", + "windows_i686_msvc 0.48.5", + "windows_x86_64_gnu 0.48.5", + "windows_x86_64_gnullvm 0.48.5", + "windows_x86_64_msvc 0.48.5", +] + +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm 0.52.6", + "windows_aarch64_msvc 0.52.6", + "windows_i686_gnu 0.52.6", + "windows_i686_gnullvm", + "windows_i686_msvc 0.52.6", + "windows_x86_64_gnu 0.52.6", + "windows_x86_64_gnullvm 0.52.6", + "windows_x86_64_msvc 0.52.6", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_i686_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + [[package]] name = "winnow" -version = "0.7.1" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86e376c75f4f43f44db463cf729e0d3acbf954d13e22c51e26e4c264b4ab545f" +checksum = "59690dea168f2198d1a3b0cac23b8063efcd11012f10ae4698f284808c8ef603" dependencies = [ "memchr", ] diff --git a/Cargo.toml b/Cargo.toml index 00a2e8e3..9159040f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,7 +12,7 @@ categories = ["development-tools", "filesystem"] repository = "https://github.com/bytesize-rs/bytesize" license = "Apache-2.0" edition = "2021" -rust-version = "1.65" +rust-version = "1.70" [features] default = [] @@ -24,11 +24,16 @@ arbitrary = { version = "1", optional = true } serde = { version = "1", optional = true } [dev-dependencies] +divan = "0.1" quickcheck = "1" serde = { version = "1", features = ["derive"] } serde_json = "1" toml = "0.8" +[[bench]] +name = "display" +harness = false + [lints.rust] rust-2018-idioms = { level = "deny" } future-incompatible = { level = "deny" } diff --git a/benches/display.rs b/benches/display.rs new file mode 100644 index 00000000..fe88a9ac --- /dev/null +++ b/benches/display.rs @@ -0,0 +1,47 @@ +#![allow(missing_docs)] + +use std::{env, fmt, hint::black_box}; + +struct ByteSizeAlwaysPad(bytesize::ByteSize); + +impl fmt::Display for ByteSizeAlwaysPad { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.pad(&self.0.display().to_string()) + } +} + +#[divan::bench] +fn display_inner_display() { + black_box(format!("{}", bytesize::ByteSize::kib(42).display())); +} + +#[divan::bench] +fn display_bytesize_standard() { + black_box(format!("{}", bytesize::ByteSize::kib(42).display())); +} + +#[divan::bench] +fn display_bytesize_custom() { + black_box(format!("|{:-^10}|", bytesize::ByteSize::kib(42))); +} + +#[divan::bench] +fn display_always_pad_standard() { + black_box(format!( + "{}", + ByteSizeAlwaysPad(bytesize::ByteSize::kib(42)) + )); +} + +#[divan::bench] +fn display_always_pad_custom() { + black_box(format!( + "|{:-^10}|", + ByteSizeAlwaysPad(bytesize::ByteSize::kib(42)) + )); +} + +fn main() { + env::set_var("DIVAN_SAMPLE_COUNT", "1000"); + divan::main(); +} diff --git a/justfile b/justfile index 709d3e24..9f8cc674 100644 --- a/justfile +++ b/justfile @@ -48,7 +48,9 @@ test toolchain="": # Downgrade dev-dependencies necessary to run MSRV checks/tests. [private] downgrade-msrv: - # "No MSRV downgrades currently necessary" + cargo update -p=divan --precise=0.1.15 + cargo update -p=clap --precise=4.3.24 + cargo update -p=clap_lex --precise=0.5.0 # Test workspace using MSRV. [group("test")] From 65102408d59266402612022a741018764ba520bf Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Tue, 18 Feb 2025 11:34:12 +0000 Subject: [PATCH 3/3] chore: restore dot --- src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib.rs b/src/lib.rs index b6fbeca7..fa4c53cf 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -56,7 +56,7 @@ mod serde; pub use crate::display::Display; use crate::display::Format; -/// Number of bytes in 1 kilobyte +/// Number of bytes in 1 kilobyte. pub const KB: u64 = 1_000; /// Number of bytes in 1 megabyte. pub const MB: u64 = 1_000_000;