humanize_bytes/
lib.rs

1//! # Humanize Bytes
2//!
3//! Format a number of bytes as a human-readable string.
4//!
5//! See for more info: <https://en.wikipedia.org/wiki/Binary_prefix>
6//!
7//! 1 KB = 1000 B
8//!
9//! 1 KiB = 1024 B
10//!
11//! ```rust
12//! use humanize_bytes::{humanize_bytes_decimal, humanize_bytes_binary, humanize_quantity};
13//!
14//! assert_eq!(humanize_bytes_binary!(0), "0 B");
15//! assert_eq!(humanize_bytes_binary!(512), "512 B");
16//! assert_eq!(humanize_bytes_binary!(1023), "1023 B");
17//! assert_eq!(humanize_bytes_binary!(1024), "1 KiB");
18//! assert_eq!(humanize_bytes_binary!(1024 + 99), "1 KiB");
19//! assert_eq!(humanize_bytes_binary!(1024 + 103), "1.1 KiB");
20//! assert_eq!(humanize_bytes_binary!(1024 * 1024 - 1), "1023.9 KiB");
21//! assert_eq!(humanize_bytes_binary!(1024 * 1024), "1 MiB");
22//! assert_eq!(humanize_bytes_binary!(1024 * 1024 * 1024), "1 GiB");
23//!
24//! assert_eq!(humanize_bytes_decimal!(0), "0 B");
25//! assert_eq!(humanize_bytes_decimal!(512), "512 B");
26//! assert_eq!(humanize_bytes_decimal!(999), "999 B");
27//! assert_eq!(humanize_bytes_decimal!(1000), "1 kB");
28//! assert_eq!(humanize_bytes_decimal!(1000 + 99), "1 kB");
29//! assert_eq!(humanize_bytes_decimal!(1000 + 100), "1.1 kB");
30//! assert_eq!(humanize_bytes_decimal!(1000 * 1000 - 1), "999.9 kB");
31//! assert_eq!(humanize_bytes_decimal!(1000 * 1000), "1 MB");
32//! assert_eq!(humanize_bytes_decimal!(1000 * 1000 * 1000), "1 GB");
33//!
34//! assert_eq!(humanize_quantity!(0), "0");
35//! assert_eq!(humanize_quantity!(512), "512");
36//! assert_eq!(humanize_quantity!(999), "999");
37//! assert_eq!(humanize_quantity!(1000), "1 k");
38//! assert_eq!(humanize_quantity!(1000 + 99), "1 k");
39//! assert_eq!(humanize_quantity!(1000 + 100), "1.1 k");
40//! assert_eq!(humanize_quantity!(1000 * 1000 - 1), "999.9 k");
41//! assert_eq!(humanize_quantity!(1000 * 1000), "1 M");
42//! ```
43//!
44
45#![no_std]
46
47pub use smartstring;
48
49mod binary {
50
51    ///
52    /// Format a number of bytes as a human-readable string, using the IEC binary suffixes.
53    ///
54    /// 1024 (B, KiB, MiB, GiB, TiB, PiB, EiB, ZiB, YiB, RiB, QiB)
55    ///
56    #[macro_export]
57    macro_rules! humanize_bytes_binary {
58        ($value:expr) => {{
59            use ::core::fmt::Write;
60            use ::humanize_bytes::smartstring::{LazyCompact, SmartString};
61            let mut num_bytes = { $value } as f64;
62            let mut result = SmartString::<LazyCompact>::new();
63            if num_bytes < 0.0 {
64                write!(result, "-").unwrap();
65                num_bytes = -num_bytes;
66            }
67
68            if num_bytes < 1024.0 {
69                write!(result, "{} B", num_bytes as u16).unwrap();
70                result
71            } else {
72                const SUFFIX: [&str; 11] = [
73                    "B", "KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "ZiB", "YiB", "RiB", "QiB",
74                ];
75                const UNIT: f64 = 1024.0;
76                let base = num_bytes.log2() as usize / 10;
77                let curr_base = UNIT.powi(base as i32) as f64;
78                let units = num_bytes / curr_base;
79                let units = (units * 100.0).floor() / 100.0;
80                let mut once = true;
81                let mut extra = SmartString::<LazyCompact>::new();
82                write!(extra, "{:.2}", units).unwrap();
83                let trimmed = extra
84                    .trim_end_matches(|_| {
85                        if once {
86                            once = false;
87                            true
88                        } else {
89                            false
90                        }
91                    })
92                    .trim_end_matches("0")
93                    .trim_end_matches(".");
94                result.push_str(trimmed);
95                result.push_str(" ");
96                result.push_str(SUFFIX[base as usize]);
97                result
98            }
99        }};
100    }
101
102    pub use humanize_bytes_binary;
103}
104
105mod decimal {
106
107    ///
108    /// Format a number of bytes as a human-readable string, using the SI decimal suffixes.
109    ///
110    /// 1000 (B, kB, MB, GB, TB, PB, EB, ZB, YB)
111    #[macro_export]
112    macro_rules! humanize_bytes_decimal {
113        ($value:expr) => {{
114            use ::core::fmt::Write;
115            use ::humanize_bytes::smartstring::{LazyCompact, SmartString};
116            let mut num_bytes = { $value } as f64;
117            let mut result = SmartString::<LazyCompact>::new();
118            if num_bytes < 0.0 {
119                write!(result, "-").unwrap();
120                num_bytes = -num_bytes;
121            }
122            if num_bytes < 1000.0 {
123                write!(result, "{} B", num_bytes as u16).unwrap();
124                result
125            } else {
126                const SUFFIX: [&str; 11] = [
127                    "B", "kB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB", "RB", "QB",
128                ];
129                const UNIT: f64 = 1000.0;
130                let base = num_bytes.log10() as usize / 3;
131                let curr_base = UNIT.powi(base as i32) as f64;
132                let units = num_bytes / curr_base;
133                let units = (units * 100.0).floor() / 100.0;
134                let mut once = true;
135                let mut extra = SmartString::<LazyCompact>::new();
136                write!(extra, "{:.2}", units).unwrap();
137                let trimmed = extra
138                    .trim_end_matches(|_| {
139                        if once {
140                            once = false;
141                            true
142                        } else {
143                            false
144                        }
145                    })
146                    .trim_end_matches("0")
147                    .trim_end_matches(".");
148                result.push_str(trimmed);
149                result.push_str(" ");
150                result.push_str(SUFFIX[base as usize]);
151                result
152            }
153        }};
154    }
155
156    pub use humanize_bytes_decimal;
157
158    ///
159    /// Format a number of bytes as a human-readable string, using the SI decimal suffixes.
160    ///
161    /// Factors of 1000 (, k, M, G, T, P, E, Z, Y, R, Q)
162    /// kilo, mega, giga, tera, peta, exa, zetta, yotta, ronna, quetta
163    ///
164    #[macro_export]
165    macro_rules! humanize_quantity {
166        ($value:expr) => {{
167            use ::core::fmt::Write;
168            use ::humanize_bytes::smartstring::{LazyCompact, SmartString};
169            let mut num_bytes = { $value } as f64;
170            let mut result = SmartString::<LazyCompact>::new();
171            if num_bytes < 0.0 {
172                write!(result, "-").unwrap();
173                num_bytes = -num_bytes;
174            }
175            if num_bytes < 1000.0 {
176                write!(result, "{}", num_bytes as u16).unwrap();
177                result
178            } else {
179                const SUFFIX: [&str; 11] = ["", "k", "M", "G", "T", "P", "E", "Z", "Y", "R", "Q"];
180                const UNIT: f64 = 1000.0;
181                let base = num_bytes.log10() as usize / 3;
182                let curr_base = UNIT.powi(base as i32) as f64;
183                let units = num_bytes / curr_base;
184                let units = (units * 100.0).floor() / 100.0;
185                let mut once = true;
186                let mut extra = SmartString::<LazyCompact>::new();
187                write!(extra, "{:.2}", units).unwrap();
188                let trimmed = extra
189                    .trim_end_matches(|_| {
190                        if once {
191                            once = false;
192                            true
193                        } else {
194                            false
195                        }
196                    })
197                    .trim_end_matches("0")
198                    .trim_end_matches(".");
199                result.push_str(trimmed);
200                result.push_str(" ");
201                result.push_str(SUFFIX[base as usize]);
202                result
203            }
204        }};
205    }
206
207    pub use humanize_quantity;
208}