Skip to content

Commit b21a0f7

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

File tree

3 files changed

+147
-6
lines changed

3 files changed

+147
-6
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: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
use core::{fmt, write};
2+
3+
use crate::ByteSize;
4+
5+
#[derive(Debug, Clone)]
6+
pub(crate) enum Style {
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) style: Style,
16+
}
17+
18+
impl Display {
19+
pub fn iec(mut self) -> Self {
20+
self.style = Style::IEC;
21+
self
22+
}
23+
24+
pub fn si(mut self) -> Self {
25+
self.style = Style::SI;
26+
self
27+
}
28+
29+
pub fn short(mut self) -> Self {
30+
self.style = Style::Short;
31+
self
32+
}
33+
}
34+
35+
impl fmt::Display for Display {
36+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
37+
let bytes = self.byte_size.as_u64();
38+
39+
let unit = match self.style {
40+
Style::IEC | Style::Short => crate::KIB,
41+
Style::SI => crate::KB,
42+
};
43+
let unit_base = match self.style {
44+
Style::IEC | Style::Short => crate::LN_KIB,
45+
Style::SI => crate::LN_KB,
46+
};
47+
48+
let unit_prefixes = match self.style {
49+
Style::IEC | Style::Short => crate::UNITS_IEC.as_bytes(),
50+
Style::SI => crate::UNITS_SI.as_bytes(),
51+
};
52+
let unit_separator = match self.style {
53+
Style::IEC | Style::SI => " ",
54+
Style::Short => "",
55+
};
56+
let unit_suffix = match self.style {
57+
Style::IEC => "iB",
58+
Style::SI => "B",
59+
Style::Short => "",
60+
};
61+
62+
if bytes < unit {
63+
write!(f, "{bytes}{unit_separator}B")?;
64+
} else {
65+
let size = bytes as f64;
66+
let exp = match (size.ln() / unit_base) as usize {
67+
0 => 1,
68+
e => e,
69+
};
70+
71+
let unit_prefix = unit_prefixes[exp - 1] as char;
72+
73+
write!(
74+
f,
75+
"{:.1}{unit_separator}{unit_prefix}{unit_suffix}",
76+
(size / unit.pow(exp as u32) as f64),
77+
)?;
78+
}
79+
80+
Ok(())
81+
}
82+
}
83+
84+
#[cfg(test)]
85+
mod tests {
86+
use super::*;
87+
88+
#[test]
89+
fn to_string_iec() {
90+
let display = Display {
91+
byte_size: ByteSize::gib(1),
92+
style: Style::IEC,
93+
};
94+
assert_eq!("1.0 GiB", display.to_string());
95+
96+
let display = Display {
97+
byte_size: ByteSize::gb(1),
98+
style: Style::IEC,
99+
};
100+
assert_eq!("953.7 MiB", display.to_string());
101+
}
102+
103+
#[test]
104+
fn to_string_si() {
105+
let display = Display {
106+
byte_size: ByteSize::gib(1),
107+
style: Style::SI,
108+
};
109+
assert_eq!("1.1 GB", display.to_string());
110+
111+
let display = Display {
112+
byte_size: ByteSize::gb(1),
113+
style: Style::SI,
114+
};
115+
assert_eq!("1.0 GB", display.to_string());
116+
}
117+
118+
#[test]
119+
fn to_string_short() {
120+
let display = Display {
121+
byte_size: ByteSize::gib(1),
122+
style: Style::Short,
123+
};
124+
assert_eq!("1.0G", display.to_string());
125+
126+
let display = Display {
127+
byte_size: ByteSize::gb(1),
128+
style: Style::Short,
129+
};
130+
assert_eq!("953.7M", display.to_string());
131+
}
132+
}

src/lib.rs

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -40,18 +40,20 @@
4040
//! assert_eq!(ByteSize::gb(996), minus);
4141
//! ```
4242
43+
use std::fmt::{self, Debug, Display, Formatter};
44+
use std::ops::{Add, AddAssign, Mul, MulAssign, Sub, SubAssign};
45+
4346
#[cfg(feature = "arbitrary")]
4447
mod arbitrary;
48+
mod display;
4549
mod parse;
4650
#[cfg(feature = "serde")]
4751
mod serde;
4852

49-
use std::fmt::{self, Debug, Display, Formatter};
50-
use std::ops::{Add, AddAssign, Mul, MulAssign, Sub, SubAssign};
51-
5253
/// byte size for 1 byte
5354
pub const B: u64 = 1;
5455
/// bytes size for 1 kilobyte
56+
/// Number of bytes in 1 kilobyte.
5557
pub const KB: u64 = 1_000;
5658
/// bytes size for 1 megabyte
5759
pub const MB: u64 = 1_000_000;
@@ -136,8 +138,8 @@ pub fn pib<V: Into<u64>>(size: V) -> u64 {
136138
size.into() * PIB
137139
}
138140

139-
/// Byte size representation
140-
#[derive(Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash, Default)]
141+
/// Byte size representation.
142+
#[derive(Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
141143
pub struct ByteSize(pub u64);
142144

143145
impl ByteSize {
@@ -201,6 +203,13 @@ impl ByteSize {
201203
self.0
202204
}
203205

206+
pub fn display(&self) -> crate::display::Display {
207+
crate::display::Display {
208+
byte_size: *self,
209+
style: crate::display::Style::IEC,
210+
}
211+
}
212+
204213
#[inline(always)]
205214
pub fn to_string_as(&self, si_unit: bool) -> String {
206215
to_string(self.0, si_unit)

0 commit comments

Comments
 (0)