pretty_bytes_typed/
binary.rs1#![allow(clippy::module_name_repetitions)]
2
3use crate::util::round_float;
4
5#[derive(Debug, PartialEq, Clone)]
7#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
8#[must_use]
9pub struct PrettyBytesBinary {
10 num: f64,
11 suffix: ByteValuesBinary,
12}
13
14impl std::fmt::Display for PrettyBytesBinary {
15 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
16 write!(f, "{} {:?}", self.num, self.suffix)
17 }
18}
19
20#[derive(Clone, Copy, Debug, PartialEq)]
21#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
22enum ByteValuesBinary {
23 B,
24 KiB,
25 MiB,
26 GiB,
27 TiB,
28 PiB,
29 EiB,
30}
31
32impl ByteValuesBinary {
33 const UNITS: [Self; 7] = [
35 Self::B,
36 Self::KiB,
37 Self::MiB,
38 Self::GiB,
39 Self::TiB,
40 Self::PiB,
41 Self::EiB,
42 ];
43}
44
45#[allow(clippy::cast_precision_loss)]
62pub fn pretty_bytes_binary(num: u64, round_places: Option<u8>) -> PrettyBytesBinary {
63 if num == 0 {
65 return PrettyBytesBinary {
66 num: 0.,
67 suffix: ByteValuesBinary::B,
68 };
69 }
70
71 let exponent = std::cmp::min(num.ilog(1024) as usize, ByteValuesBinary::UNITS.len() - 1);
72
73 let mut num = num as f64 / 1024_f64.powi(exponent as i32);
74
75 if let Some(round_places) = round_places {
76 num = round_float(num, round_places);
77 }
78
79 let unit = ByteValuesBinary::UNITS[exponent];
80
81 PrettyBytesBinary { num, suffix: unit }
82}
83
84pub fn pretty_bytes_signed_binary(num: i64, round_places: Option<u8>) -> PrettyBytesBinary {
95 let is_negative = num.is_negative();
96 let num = num.unsigned_abs();
97
98 let mut pretty_bytes = pretty_bytes_binary(num, round_places);
99
100 if is_negative {
101 pretty_bytes.num = -pretty_bytes.num;
102 }
103
104 pretty_bytes
105}
106
107#[cfg(test)]
108mod tests {
109 use super::*;
110
111 #[test]
112 #[allow(clippy::too_many_lines)]
113 fn test_pretty_bytes_binary() {
114 assert_eq!(
116 pretty_bytes_binary(0, None),
117 PrettyBytesBinary {
118 num: 0.,
119 suffix: ByteValuesBinary::B,
120 }
121 );
122
123 assert_eq!(
125 pretty_bytes_binary(1024_u64.pow(0), None),
126 PrettyBytesBinary {
127 num: 1.,
128 suffix: ByteValuesBinary::B,
129 }
130 );
131
132 assert_eq!(
133 pretty_bytes_binary(1024_u64.pow(1), None),
134 PrettyBytesBinary {
135 num: 1.,
136 suffix: ByteValuesBinary::KiB,
137 }
138 );
139
140 assert_eq!(
141 pretty_bytes_binary(1024_u64.pow(2), None),
142 PrettyBytesBinary {
143 num: 1.,
144 suffix: ByteValuesBinary::MiB,
145 }
146 );
147
148 assert_eq!(
149 pretty_bytes_binary(1024_u64.pow(3), None),
150 PrettyBytesBinary {
151 num: 1.,
152 suffix: ByteValuesBinary::GiB,
153 }
154 );
155
156 assert_eq!(
157 pretty_bytes_binary(1024_u64.pow(4), None),
158 PrettyBytesBinary {
159 num: 1.,
160 suffix: ByteValuesBinary::TiB,
161 }
162 );
163
164 assert_eq!(
165 pretty_bytes_binary(1024_u64.pow(5), None),
166 PrettyBytesBinary {
167 num: 1.,
168 suffix: ByteValuesBinary::PiB,
169 }
170 );
171
172 assert_eq!(
173 pretty_bytes_binary(1024_u64.pow(6), None),
174 PrettyBytesBinary {
175 num: 1.,
176 suffix: ByteValuesBinary::EiB,
177 }
178 );
179
180 assert_eq!(
182 pretty_bytes_binary(5014, Some(2)),
183 PrettyBytesBinary {
184 num: 4.9,
185 suffix: ByteValuesBinary::KiB,
186 }
187 );
188 }
189}