1pub const AVAILABLE_UNIT_SIZES: [Option<char>;9] = [
17 None,
18 Some('K'),
19 Some('M'),
20 Some('G'),
21 Some('T'),
22 Some('P'),
23 Some('E'),
24 Some('Z'),
25 Some('Y'),
26];
27
28pub trait BigByte {
30 fn big_byte(&self, precision: usize) -> String;
32}
33
34impl BigByte for f32 {
35 fn big_byte(&self, precision: usize) -> String {
36 let mut value: f32 = *self;
37 let mut counter: usize = 0;
38 let (counter, value): (usize, f32) = loop {
39 if counter >= AVAILABLE_UNIT_SIZES.len() {
40 break (counter, value);
41 }
42 if value < 1024.0 {
43 break (counter, value);
44 }
45 value /= 1024.0;
46 counter += 1;
47 };
48
49 match AVAILABLE_UNIT_SIZES.get(counter) {
50 Some(None) => format!("{:.*} B", precision, value),
51 Some(Some(c)) => format!("{:.*} {}iB", precision, value, c),
52 None => format!("{:.*} {}iB", precision, value, AVAILABLE_UNIT_SIZES.last().unwrap().unwrap()),
53 }
54 }
55}
56impl BigByte for f64 {
57 fn big_byte(&self, precision: usize) -> String {
58 let mut value: f64 = *self;
59 let mut counter: usize = 0;
60 let (counter, value): (usize, f64) = loop {
61 if counter + 1 >= AVAILABLE_UNIT_SIZES.len() {
62 break (counter, value);
63 }
64 if value < 1024.0 {
65 break (counter, value);
66 }
67 value /= 1024.0;
68 counter += 1;
69 };
70
71 match AVAILABLE_UNIT_SIZES.get(counter) {
72 Some(None) => format!("{:.*} B", precision, value),
73 Some(Some(c)) => format!("{:.*} {}iB", precision, value, c),
74 None => format!("{:.*} {}iB", precision, value, AVAILABLE_UNIT_SIZES.last().unwrap().unwrap()),
75 }
76 }
77}
78
79impl BigByte for u8 {
80 fn big_byte(&self, precision: usize) -> String {
81 (*self as f32).big_byte(precision)
82 }
83}
84
85impl BigByte for u16 {
86 fn big_byte(&self, precision: usize) -> String {
87 (*self as f32).big_byte(precision)
88 }
89}
90
91impl BigByte for u32 {
92 fn big_byte(&self, precision: usize) -> String {
93 (*self as f32).big_byte(precision)
94 }
95}
96
97impl BigByte for u64 {
98 fn big_byte(&self, precision: usize) -> String {
99 (*self as f32).big_byte(precision)
100 }
101}
102
103impl BigByte for u128 {
104 fn big_byte(&self, precision: usize) -> String {
105 (*self as f64).big_byte(precision)
106 }
107}
108
109impl BigByte for usize {
110 fn big_byte(&self, precision: usize) -> String {
111 (*self as f64).big_byte(precision)
112 }
113}
114
115#[cfg(test)]
116mod tests {
117 use super::*;
118
119 #[test]
120 fn byte_test() {
121 assert_eq!(2.001.big_byte(3), "2.001 B");
122 }
123
124 #[test]
125 #[allow(non_snake_case)]
126 fn u16_two_KiB_test() {
127 assert_eq!(2048_u16.big_byte(0), "2 KiB");
128 }
129
130 #[test]
131 fn gibibyte_test() {
132 assert_eq!(2_635_000_987.0.big_byte(1), "2.5 GiB");
133 }
134
135 #[test]
136 fn too_big_test() {
137 let bytes = 2_635.0 * 1024_f64.powi(8);
138 assert_eq!(bytes.big_byte(1), "2635.0 YiB");
139 }
140}