Skip to content

Commit 352d7bb

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 352d7bb

File tree

2 files changed

+122
-50
lines changed

2 files changed

+122
-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: 121 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,46 @@ 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 F: ByteFormatter
254+
{
255+
fmt.humanize(self.0)
175256
}
176257
}
177258

259+
#[deprecated(since="1.1.0", note="use `ByteSize::b(bytes).humanize(SI|IEC)`")]
178260
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()
261+
if si_prefix {
262+
humanize(bytes, si_prefix, " ", "B")
183263
} 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-
)
264+
humanize(bytes, si_prefix, " ", "iB")
203265
}
204266
}
205267

206268
impl Display for ByteSize {
207269
fn fmt(&self, f: &mut Formatter) -> Result {
208-
write!(f, "{}", to_string(self.0, false))
270+
write!(f, "{}", self.humanize(SI))
209271
}
210272
}
211273

@@ -310,47 +372,57 @@ mod tests {
310372
#[test]
311373
fn test_display() {
312374
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));
375+
assert_display("1.0 kB", ByteSize::kb(1));
376+
assert_display("301.0 kB", ByteSize::kb(301));
315377
assert_display("419.0 MB", ByteSize::mb(419));
316378
assert_display("518.0 GB", ByteSize::gb(518));
317379
assert_display("815.0 TB", ByteSize::tb(815));
318380
assert_display("609.0 PB", ByteSize::pb(609));
319381
}
320382

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

325389
#[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);
390+
fn test_humanize() {
391+
assert_humanize("215 B", ByteSize::b(215), IEC);
392+
assert_humanize("215 B", ByteSize::b(215), SI);
329393

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

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

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

339406
// 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);
407+
assert_humanize("1.9 GiB", ByteSize::mib(1907), IEC);
408+
assert_humanize("2.0 GB", ByteSize::mib(1908), SI);
409+
assert_humanize("1.9G", ByteSize::mib(1907), Sort);
342410

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

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

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

352-
assert_to_string("540.9 PiB", ByteSize::pb(609), true);
353-
assert_to_string("609.0 PB", ByteSize::pb(609), false);
423+
assert_humanize("540.9 PiB", ByteSize::pb(609), IEC);
424+
assert_humanize("609.0 PB", ByteSize::pb(609), SI);
425+
assert_humanize("540.9P", ByteSize::pb(609), Sort);
354426
}
355427

356428
#[test]
@@ -360,6 +432,6 @@ mod tests {
360432

361433
#[test]
362434
fn test_to_string() {
363-
assert_to_string("609.0 PB", ByteSize::pb(609), false);
435+
assert_humanize("609.0 PB", ByteSize::pb(609), SI);
364436
}
365437
}

0 commit comments

Comments
 (0)