Skip to content

Commit 190d56c

Browse files
committed
feat: display type
1 parent 4a10b72 commit 190d56c

File tree

4 files changed

+188
-104
lines changed

4 files changed

+188
-104
lines changed

examples/ls.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ fn main() -> io::Result<()> {
1515

1616
if md.is_file() {
1717
let file_size = md.len();
18-
let file_size = bytesize::ByteSize::b(file_size);
18+
let file_size = bytesize::ByteSize::b(file_size).display().short();
1919

2020
println!("{file_size}\t{file_name}");
2121
} else {

src/display.rs

Lines changed: 170 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,170 @@
1+
use core::{fmt, write};
2+
3+
use crate::ByteSize;
4+
5+
#[derive(Debug, Clone)]
6+
pub(crate) enum Format {
7+
Iec,
8+
Si,
9+
Short,
10+
}
11+
12+
#[derive(Debug, Clone)]
13+
pub struct Display {
14+
pub(crate) byte_size: ByteSize,
15+
pub(crate) format: Format,
16+
}
17+
18+
impl Display {
19+
#[must_use]
20+
pub fn iec(mut self) -> Self {
21+
self.format = Format::Iec;
22+
self
23+
}
24+
25+
#[must_use]
26+
pub fn si(mut self) -> Self {
27+
self.format = Format::Si;
28+
self
29+
}
30+
31+
#[must_use]
32+
pub fn short(mut self) -> Self {
33+
self.format = Format::Short;
34+
self
35+
}
36+
}
37+
38+
impl fmt::Display for Display {
39+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
40+
let bytes = self.byte_size.as_u64();
41+
42+
let unit = match self.format {
43+
Format::Iec | Format::Short => crate::KIB,
44+
Format::Si => crate::KB,
45+
};
46+
let unit_base = match self.format {
47+
Format::Iec | Format::Short => crate::LN_KIB,
48+
Format::Si => crate::LN_KB,
49+
};
50+
51+
let unit_prefixes = match self.format {
52+
Format::Iec | Format::Short => crate::UNITS_IEC.as_bytes(),
53+
Format::Si => crate::UNITS_SI.as_bytes(),
54+
};
55+
let unit_separator = match self.format {
56+
Format::Iec | Format::Si => " ",
57+
Format::Short => "",
58+
};
59+
let unit_suffix = match self.format {
60+
Format::Iec => "iB",
61+
Format::Si => "B",
62+
Format::Short => "",
63+
};
64+
65+
if bytes < unit {
66+
write!(f, "{bytes}{unit_separator}B")?;
67+
} else {
68+
let size = bytes as f64;
69+
let exp = match (size.ln() / unit_base) as usize {
70+
0 => 1,
71+
e => e,
72+
};
73+
74+
let unit_prefix = unit_prefixes[exp - 1] as char;
75+
76+
write!(
77+
f,
78+
"{:.1}{unit_separator}{unit_prefix}{unit_suffix}",
79+
(size / unit.pow(exp as u32) as f64),
80+
)?;
81+
}
82+
83+
Ok(())
84+
}
85+
}
86+
87+
#[cfg(test)]
88+
mod tests {
89+
use super::*;
90+
91+
#[test]
92+
fn to_string_iec() {
93+
let display = Display {
94+
byte_size: ByteSize::gib(1),
95+
format: Format::Iec,
96+
};
97+
assert_eq!("1.0 GiB", display.to_string());
98+
99+
let display = Display {
100+
byte_size: ByteSize::gb(1),
101+
format: Format::Iec,
102+
};
103+
assert_eq!("953.7 MiB", display.to_string());
104+
}
105+
106+
#[test]
107+
fn to_string_si() {
108+
let display = Display {
109+
byte_size: ByteSize::gib(1),
110+
format: Format::Si,
111+
};
112+
assert_eq!("1.1 GB", display.to_string());
113+
114+
let display = Display {
115+
byte_size: ByteSize::gb(1),
116+
format: Format::Si,
117+
};
118+
assert_eq!("1.0 GB", display.to_string());
119+
}
120+
121+
#[test]
122+
fn to_string_short() {
123+
let display = Display {
124+
byte_size: ByteSize::gib(1),
125+
format: Format::Short,
126+
};
127+
assert_eq!("1.0G", display.to_string());
128+
129+
let display = Display {
130+
byte_size: ByteSize::gb(1),
131+
format: Format::Short,
132+
};
133+
assert_eq!("953.7M", display.to_string());
134+
}
135+
136+
#[track_caller]
137+
fn assert_to_string(expected: &str, byte_size: ByteSize, format: Format) {
138+
assert_eq!(expected, Display { byte_size, format }.to_string());
139+
}
140+
141+
#[test]
142+
fn test_to_string_as() {
143+
assert_to_string("215 B", ByteSize::b(215), Format::Iec);
144+
assert_to_string("215 B", ByteSize::b(215), Format::Si);
145+
146+
assert_to_string("1.0 KiB", ByteSize::kib(1), Format::Iec);
147+
assert_to_string("1.0 kB", ByteSize::kib(1), Format::Si);
148+
149+
assert_to_string("293.9 KiB", ByteSize::kb(301), Format::Iec);
150+
assert_to_string("301.0 kB", ByteSize::kb(301), Format::Si);
151+
152+
assert_to_string("1.0 MiB", ByteSize::mib(1), Format::Iec);
153+
assert_to_string("1.0 MB", ByteSize::mib(1), Format::Si);
154+
155+
assert_to_string("1.9 GiB", ByteSize::mib(1907), Format::Iec);
156+
assert_to_string("2.0 GB", ByteSize::mib(1908), Format::Si);
157+
158+
assert_to_string("399.6 MiB", ByteSize::mb(419), Format::Iec);
159+
assert_to_string("419.0 MB", ByteSize::mb(419), Format::Si);
160+
161+
assert_to_string("482.4 GiB", ByteSize::gb(518), Format::Iec);
162+
assert_to_string("518.0 GB", ByteSize::gb(518), Format::Si);
163+
164+
assert_to_string("741.2 TiB", ByteSize::tb(815), Format::Iec);
165+
assert_to_string("815.0 TB", ByteSize::tb(815), Format::Si);
166+
167+
assert_to_string("540.9 PiB", ByteSize::pb(609), Format::Iec);
168+
assert_to_string("609.0 PB", ByteSize::pb(609), Format::Si);
169+
}
170+
}

src/lib.rs

Lines changed: 15 additions & 99 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,9 @@
2424
//! ```
2525
//! use bytesize::ByteSize;
2626
//!
27-
//! assert_eq!("482.4 GiB", ByteSize::gb(518).to_string_as(false));
28-
//! assert_eq!("518.0 GB", ByteSize::gb(518).to_string_as(true));
27+
//! assert_eq!("518.0 GiB", ByteSize::gib(518).display().iec().to_string());
28+
//! assert_eq!("556.2 GB", ByteSize::gib(518).display().si().to_string());
29+
//! assert_eq!("518.0G", ByteSize::gib(518).display().short().to_string());
2930
//! ```
3031
//!
3132
//! Arithmetic operations are supported.
@@ -40,15 +41,16 @@
4041
//! assert_eq!(ByteSize::gb(996), minus);
4142
//! ```
4243
44+
use std::fmt::{self, Debug, Display, Formatter};
45+
use std::ops::{Add, AddAssign, Mul, MulAssign, Sub, SubAssign};
46+
4347
#[cfg(feature = "arbitrary")]
4448
mod arbitrary;
49+
mod display;
4550
mod parse;
4651
#[cfg(feature = "serde")]
4752
mod serde;
4853

49-
use std::fmt::{self, Debug, Display, Formatter};
50-
use std::ops::{Add, AddAssign, Mul, MulAssign, Sub, SubAssign};
51-
5254
/// byte size for 1 byte
5355
pub const B: u64 = 1;
5456
/// bytes size for 1 kilobyte
@@ -89,13 +91,6 @@ const LN_KIB: f64 = 6.931_471_805_599_453;
8991
/// `ln(1000) ~= 6.908`
9092
const LN_KB: f64 = 6.907_755_278_982_137;
9193

92-
#[derive(Debug, Clone, Default)]
93-
pub enum Format {
94-
#[default]
95-
IEC,
96-
SI,
97-
}
98-
9994
pub fn kb<V: Into<u64>>(size: V) -> u64 {
10095
size.into() * KB
10196
}
@@ -136,8 +131,8 @@ pub fn pib<V: Into<u64>>(size: V) -> u64 {
136131
size.into() * PIB
137132
}
138133

139-
/// Byte size representation
140-
#[derive(Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash, Default)]
134+
/// Byte size representation.
135+
#[derive(Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
141136
pub struct ByteSize(pub u64);
142137

143138
impl ByteSize {
@@ -201,56 +196,17 @@ impl ByteSize {
201196
self.0
202197
}
203198

204-
#[inline(always)]
205-
pub fn to_string_as(&self, si_unit: bool) -> String {
206-
to_string(self.0, si_unit)
207-
}
208-
}
209-
210-
pub fn to_string(bytes: u64, si_unit: bool) -> String {
211-
to_string_format(bytes, if si_unit { Format::SI } else { Format::IEC })
212-
}
213-
214-
pub fn to_string_format(bytes: u64, format: Format) -> String {
215-
let unit = match format {
216-
Format::IEC => KIB,
217-
Format::SI => KB,
218-
};
219-
let unit_base = match format {
220-
Format::IEC => LN_KIB,
221-
Format::SI => LN_KB,
222-
};
223-
224-
let unit_prefix = match format {
225-
Format::IEC => UNITS_IEC.as_bytes(),
226-
Format::SI => UNITS_SI.as_bytes(),
227-
};
228-
let unit_suffix = match format {
229-
Format::IEC => "iB",
230-
Format::SI => "B",
231-
};
232-
233-
if bytes < unit {
234-
format!("{} B", bytes)
235-
} else {
236-
let size = bytes as f64;
237-
let exp = match (size.ln() / unit_base) as usize {
238-
0 => 1,
239-
e => e,
240-
};
241-
242-
format!(
243-
"{:.1} {}{}",
244-
(size / unit.pow(exp as u32) as f64),
245-
unit_prefix[exp - 1] as char,
246-
unit_suffix
247-
)
199+
pub fn display(&self) -> crate::display::Display {
200+
crate::display::Display {
201+
byte_size: *self,
202+
format: crate::display::Format::Iec,
203+
}
248204
}
249205
}
250206

251207
impl Display for ByteSize {
252208
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
253-
f.pad(&to_string_format(self.0, Format::IEC))
209+
f.pad(&self.display().to_string())
254210
}
255211
}
256212

@@ -499,48 +455,8 @@ mod tests {
499455
assert_eq!("|--357 B---|", format!("|{:-^10}|", ByteSize(357)));
500456
}
501457

502-
#[track_caller]
503-
fn assert_to_string(expected: &str, b: ByteSize, format: Format) {
504-
assert_eq!(expected.to_string(), to_string_format(b.0, format));
505-
}
506-
507-
#[test]
508-
fn test_to_string_as() {
509-
assert_to_string("215 B", ByteSize::b(215), Format::IEC);
510-
assert_to_string("215 B", ByteSize::b(215), Format::SI);
511-
512-
assert_to_string("1.0 KiB", ByteSize::kib(1), Format::IEC);
513-
assert_to_string("1.0 kB", ByteSize::kib(1), Format::SI);
514-
515-
assert_to_string("293.9 KiB", ByteSize::kb(301), Format::IEC);
516-
assert_to_string("301.0 kB", ByteSize::kb(301), Format::SI);
517-
518-
assert_to_string("1.0 MiB", ByteSize::mib(1), Format::IEC);
519-
assert_to_string("1.0 MB", ByteSize::mib(1), Format::SI);
520-
521-
assert_to_string("1.9 GiB", ByteSize::mib(1907), Format::IEC);
522-
assert_to_string("2.0 GB", ByteSize::mib(1908), Format::SI);
523-
524-
assert_to_string("399.6 MiB", ByteSize::mb(419), Format::IEC);
525-
assert_to_string("419.0 MB", ByteSize::mb(419), Format::SI);
526-
527-
assert_to_string("482.4 GiB", ByteSize::gb(518), Format::IEC);
528-
assert_to_string("518.0 GB", ByteSize::gb(518), Format::SI);
529-
530-
assert_to_string("741.2 TiB", ByteSize::tb(815), Format::IEC);
531-
assert_to_string("815.0 TB", ByteSize::tb(815), Format::SI);
532-
533-
assert_to_string("540.9 PiB", ByteSize::pb(609), Format::IEC);
534-
assert_to_string("609.0 PB", ByteSize::pb(609), Format::SI);
535-
}
536-
537458
#[test]
538459
fn test_default() {
539460
assert_eq!(ByteSize::b(0), ByteSize::default());
540461
}
541-
542-
#[test]
543-
fn test_to_string() {
544-
assert_to_string("609.0 PB", ByteSize::pb(609), Format::SI);
545-
}
546462
}

src/parse.rs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -181,8 +181,6 @@ impl std::str::FromStr for Unit {
181181

182182
#[cfg(test)]
183183
mod tests {
184-
use crate::to_string_format;
185-
186184
use super::*;
187185

188186
#[test]
@@ -234,9 +232,9 @@ mod tests {
234232
s.parse::<ByteSize>().unwrap().0
235233
}
236234

237-
assert_eq!(parse(&format!("{}", parse("128GB"))), 128 * Unit::GigaByte);
235+
assert_eq!(parse(&parse("128GB").to_string()), 128 * Unit::GigaByte);
238236
assert_eq!(
239-
parse(&to_string_format(parse("128.000 GiB"), crate::Format::IEC)),
237+
parse(&ByteSize(parse("128.000 GiB")).to_string()),
240238
128 * Unit::GibiByte,
241239
);
242240
}

0 commit comments

Comments
 (0)