Skip to content

Commit d3be6c8

Browse files
committed
adds costomizable byte formatters
- this clarifies the intend beyond of what the previously used si boolean can - users may specify their own formatters - adds a byte formatter that is compatible with `sort -h` fixes #14
1 parent f934fa8 commit d3be6c8

File tree

2 files changed

+124
-50
lines changed

2 files changed

+124
-50
lines changed

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
[package]
22
name = "bytesize"
33
description = "a utility for human-readable bytes representations"
4-
version = "1.0.0"
4+
version = "1.1.0"
55
authors = ["Hyunsik Choi <[email protected]>"]
66

77
homepage = "https://github.com/hyunsik/bytesize/"

src/lib.rs

Lines changed: 123 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,65 @@ pub fn pib<V: Into<u64>>(size: V) -> u64 {
103103
size.into() * PIB
104104
}
105105

106+
/// 32 * 1024 Byte = 32 KiB
107+
pub struct IEC;
108+
109+
/// 32 * 1000 Byte = 32 KB
110+
pub struct SI;
111+
112+
/// 32 * 1024 Byte = 32K
113+
pub struct Sort;
114+
115+
fn humanize(bytes: u64, si: bool, prefix: &str, suffix: &str) -> String {
116+
let unit = if si { KB } else { KIB };
117+
let unit_base = if si { LN_KB } else { LN_KIB };
118+
let unit_prefix = if si {
119+
UNITS_SI.as_bytes()
120+
} else {
121+
UNITS.as_bytes()
122+
};
123+
124+
if bytes < unit {
125+
format!("{}{}B", bytes, prefix)
126+
} else {
127+
let size = bytes as f64;
128+
let exp = match (size.ln() / unit_base) as usize {
129+
e if e == 0 => 1,
130+
e => e,
131+
};
132+
133+
format!(
134+
"{:.1}{}{}{}",
135+
(size / unit.pow(exp as u32) as f64),
136+
prefix,
137+
unit_prefix[exp - 1] as char,
138+
suffix
139+
)
140+
}
141+
}
142+
143+
pub trait ByteFormatter {
144+
fn humanize(&self, bytes: u64) -> String;
145+
}
146+
147+
impl ByteFormatter for IEC {
148+
fn humanize(&self, bytes: u64) -> String {
149+
humanize(bytes, false, " ", "iB")
150+
}
151+
}
152+
153+
impl ByteFormatter for SI {
154+
fn humanize(&self, bytes: u64) -> String {
155+
humanize(bytes, true, " ", "B")
156+
}
157+
}
158+
159+
impl ByteFormatter for Sort {
160+
fn humanize(&self, bytes: u64) -> String {
161+
humanize(bytes, false, "", "")
162+
}
163+
}
164+
106165
/// Byte size representation
107166
#[derive(Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Default)]
108167
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
@@ -169,43 +228,47 @@ impl ByteSize {
169228
self.0
170229
}
171230

231+
#[deprecated(since = "1.1.0", note = "use `bs.humanize(SI|IEC)`")]
172232
#[inline(always)]
173233
pub fn to_string_as(&self, si_unit: bool) -> String {
174-
to_string(self.0, si_unit)
234+
if si_unit {
235+
self.humanize(SI)
236+
} else {
237+
self.humanize(IEC)
238+
}
239+
}
240+
241+
/// Returns humanized String representation.
242+
///
243+
/// ## Examples
244+
///
245+
/// ```
246+
/// # extern crate bytesize;
247+
/// # use bytesize::*;
248+
/// assert_eq!("1.0 KiB", ByteSize::b(1024).humanize(IEC));
249+
/// assert_eq!("1.0 kB", ByteSize::b(1000).humanize(SI));
250+
/// ```
251+
#[inline(always)]
252+
pub fn humanize<F>(&self, fmt: F) -> String
253+
where
254+
F: ByteFormatter,
255+
{
256+
fmt.humanize(self.0)
175257
}
176258
}
177259

260+
#[deprecated(since = "1.1.0", note = "use `ByteSize::b(bytes).humanize(SI|IEC)`")]
178261
pub fn to_string(bytes: u64, si_prefix: bool) -> String {
179-
let unit = if si_prefix { KIB } else { KB };
180-
let unit_base = if si_prefix { LN_KIB } else { LN_KB };
181-
let unit_prefix = if si_prefix {
182-
UNITS_SI.as_bytes()
262+
if si_prefix {
263+
humanize(bytes, si_prefix, " ", "B")
183264
} else {
184-
UNITS.as_bytes()
185-
};
186-
let unit_suffix = if si_prefix { "iB" } else { "B" };
187-
188-
if bytes < unit {
189-
format!("{} B", bytes)
190-
} else {
191-
let size = bytes as f64;
192-
let exp = match (size.ln() / unit_base) as usize {
193-
e if e == 0 => 1,
194-
e => e,
195-
};
196-
197-
format!(
198-
"{:.1} {}{}",
199-
(size / unit.pow(exp as u32) as f64),
200-
unit_prefix[exp - 1] as char,
201-
unit_suffix
202-
)
265+
humanize(bytes, si_prefix, " ", "iB")
203266
}
204267
}
205268

206269
impl Display for ByteSize {
207270
fn fmt(&self, f: &mut Formatter) -> Result {
208-
write!(f, "{}", to_string(self.0, false))
271+
write!(f, "{}", self.humanize(SI))
209272
}
210273
}
211274

@@ -310,47 +373,58 @@ mod tests {
310373
#[test]
311374
fn test_display() {
312375
assert_display("215 B", ByteSize::b(215));
313-
assert_display("1.0 KB", ByteSize::kb(1));
314-
assert_display("301.0 KB", ByteSize::kb(301));
376+
assert_display("1.0 kB", ByteSize::kb(1));
377+
assert_display("301.0 kB", ByteSize::kb(301));
315378
assert_display("419.0 MB", ByteSize::mb(419));
316379
assert_display("518.0 GB", ByteSize::gb(518));
317380
assert_display("815.0 TB", ByteSize::tb(815));
318381
assert_display("609.0 PB", ByteSize::pb(609));
319382
}
320383

321-
fn assert_to_string(expected: &str, b: ByteSize, si: bool) {
322-
assert_eq!(expected.to_string(), b.to_string_as(si));
384+
fn assert_humanize<F>(expected: &str, b: ByteSize, fmt: F)
385+
where
386+
F: ByteFormatter,
387+
{
388+
assert_eq!(expected.to_string(), b.humanize(fmt));
323389
}
324390

325391
#[test]
326-
fn test_to_string_as() {
327-
assert_to_string("215 B", ByteSize::b(215), true);
328-
assert_to_string("215 B", ByteSize::b(215), false);
392+
fn test_humanize() {
393+
assert_humanize("215 B", ByteSize::b(215), IEC);
394+
assert_humanize("215 B", ByteSize::b(215), SI);
329395

330-
assert_to_string("1.0 kiB", ByteSize::kib(1), true);
331-
assert_to_string("1.0 KB", ByteSize::kib(1), false);
396+
assert_humanize("1.0 KiB", ByteSize::kib(1), IEC);
397+
assert_humanize("1.0 kB", ByteSize::kib(1), SI);
398+
assert_humanize("1.0K", ByteSize::kib(1), Sort);
332399

333-
assert_to_string("293.9 kiB", ByteSize::kb(301), true);
334-
assert_to_string("301.0 KB", ByteSize::kb(301), false);
400+
assert_humanize("293.9 KiB", ByteSize::kb(301), IEC);
401+
assert_humanize("301.0 kB", ByteSize::kb(301), SI);
402+
assert_humanize("293.9K", ByteSize::kb(301), Sort);
335403

336-
assert_to_string("1.0 MiB", ByteSize::mib(1), true);
337-
assert_to_string("1048.6 KB", ByteSize::mib(1), false);
404+
assert_humanize("1.0 MiB", ByteSize::mib(1), IEC);
405+
assert_humanize("1048.6 kB", ByteSize::mib(1), SI);
406+
assert_humanize("1.0M", ByteSize::mib(1), Sort);
338407

339408
// a bug case: https://github.com/flang-project/bytesize/issues/8
340-
assert_to_string("1.9 GiB", ByteSize::mib(1907), true);
341-
assert_to_string("2.0 GB", ByteSize::mib(1908), false);
409+
assert_humanize("1.9 GiB", ByteSize::mib(1907), IEC);
410+
assert_humanize("2.0 GB", ByteSize::mib(1908), SI);
411+
assert_humanize("1.9G", ByteSize::mib(1907), Sort);
342412

343-
assert_to_string("399.6 MiB", ByteSize::mb(419), true);
344-
assert_to_string("419.0 MB", ByteSize::mb(419), false);
413+
assert_humanize("399.6 MiB", ByteSize::mb(419), IEC);
414+
assert_humanize("419.0 MB", ByteSize::mb(419), SI);
415+
assert_humanize("399.6M", ByteSize::mb(419), Sort);
345416

346-
assert_to_string("482.4 GiB", ByteSize::gb(518), true);
347-
assert_to_string("518.0 GB", ByteSize::gb(518), false);
417+
assert_humanize("482.4 GiB", ByteSize::gb(518), IEC);
418+
assert_humanize("518.0 GB", ByteSize::gb(518), SI);
419+
assert_humanize("482.4G", ByteSize::gb(518), Sort);
348420

349-
assert_to_string("741.2 TiB", ByteSize::tb(815), true);
350-
assert_to_string("815.0 TB", ByteSize::tb(815), false);
421+
assert_humanize("741.2 TiB", ByteSize::tb(815), IEC);
422+
assert_humanize("815.0 TB", ByteSize::tb(815), SI);
423+
assert_humanize("741.2T", ByteSize::tb(815), Sort);
351424

352-
assert_to_string("540.9 PiB", ByteSize::pb(609), true);
353-
assert_to_string("609.0 PB", ByteSize::pb(609), false);
425+
assert_humanize("540.9 PiB", ByteSize::pb(609), IEC);
426+
assert_humanize("609.0 PB", ByteSize::pb(609), SI);
427+
assert_humanize("540.9P", ByteSize::pb(609), Sort);
354428
}
355429

356430
#[test]
@@ -360,6 +434,6 @@ mod tests {
360434

361435
#[test]
362436
fn test_to_string() {
363-
assert_to_string("609.0 PB", ByteSize::pb(609), false);
437+
assert_humanize("609.0 PB", ByteSize::pb(609), SI);
364438
}
365439
}

0 commit comments

Comments
 (0)