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}