1use std::{fmt, ops};
2
3use super::Factor;
4
5pub trait ByteUnits {
7 fn bytes(self) -> ByteLength;
11 fn kibibytes(self) -> ByteLength;
15 fn kilobytes(self) -> ByteLength;
19
20 fn mebibytes(self) -> ByteLength;
24 fn megabytes(self) -> ByteLength;
28
29 fn gibibytes(self) -> ByteLength;
33 fn gigabytes(self) -> ByteLength;
37
38 fn tebibytes(self) -> ByteLength;
42 fn terabytes(self) -> ByteLength;
46}
47impl ByteUnits for usize {
48 fn bytes(self) -> ByteLength {
49 ByteLength(self)
50 }
51
52 fn kibibytes(self) -> ByteLength {
53 ByteLength::from_kibi(self)
54 }
55
56 fn kilobytes(self) -> ByteLength {
57 ByteLength::from_kilo(self)
58 }
59
60 fn mebibytes(self) -> ByteLength {
61 ByteLength::from_mebi(self)
62 }
63
64 fn megabytes(self) -> ByteLength {
65 ByteLength::from_mega(self)
66 }
67
68 fn gibibytes(self) -> ByteLength {
69 ByteLength::from_gibi(self)
70 }
71
72 fn gigabytes(self) -> ByteLength {
73 ByteLength::from_giga(self)
74 }
75
76 fn tebibytes(self) -> ByteLength {
77 ByteLength::from_tebi(self)
78 }
79
80 fn terabytes(self) -> ByteLength {
81 ByteLength::from_tera(self)
82 }
83}
84
85#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default, serde::Serialize, serde::Deserialize)]
90#[serde(transparent)]
91pub struct ByteLength(pub usize);
92impl From<usize> for ByteLength {
93 fn from(value: usize) -> Self {
94 Self(value)
95 }
96}
97impl ops::Add for ByteLength {
98 type Output = Self;
99
100 fn add(self, rhs: Self) -> Self::Output {
101 Self(self.0 + rhs.0)
102 }
103}
104impl ops::AddAssign for ByteLength {
105 fn add_assign(&mut self, rhs: Self) {
106 self.0 += rhs.0;
107 }
108}
109impl ops::Sub for ByteLength {
110 type Output = Self;
111
112 fn sub(self, rhs: Self) -> Self::Output {
113 Self(self.0 - rhs.0)
114 }
115}
116impl ops::SubAssign for ByteLength {
117 fn sub_assign(&mut self, rhs: Self) {
118 self.0 -= rhs.0;
119 }
120}
121impl ByteLength {
122 pub fn bytes(&self) -> usize {
126 self.0
127 }
128
129 fn scaled(self, scale: f64) -> f64 {
130 self.0 as f64 / scale
131 }
132
133 pub fn kibis(self) -> f64 {
135 self.scaled(1024.0)
136 }
137
138 pub fn kilos(self) -> f64 {
140 self.scaled(1000.0)
141 }
142
143 pub fn mebis(self) -> f64 {
145 self.scaled(1024.0f64.powi(2))
146 }
147
148 pub fn megas(self) -> f64 {
150 self.scaled(1000.0f64.powi(2))
151 }
152
153 pub fn gibis(self) -> f64 {
155 self.scaled(1024.0f64.powi(3))
156 }
157
158 pub fn gigas(self) -> f64 {
160 self.scaled(1000.0f64.powi(3))
161 }
162
163 pub fn tebis(self) -> f64 {
165 self.scaled(1024.0f64.powi(4))
166 }
167
168 pub fn teras(self) -> f64 {
170 self.scaled(1000.0f64.powi(4))
171 }
172
173 pub const MAX: ByteLength = ByteLength(usize::MAX);
175
176 pub const fn saturating_add(self, rhs: ByteLength) -> ByteLength {
178 ByteLength(self.0.saturating_add(rhs.0))
179 }
180
181 pub const fn saturating_sub(self, rhs: ByteLength) -> ByteLength {
183 ByteLength(self.0.saturating_sub(rhs.0))
184 }
185
186 pub const fn saturating_mul(self, rhs: ByteLength) -> ByteLength {
188 ByteLength(self.0.saturating_mul(rhs.0))
189 }
190
191 pub const fn wrapping_add(self, rhs: ByteLength) -> ByteLength {
199 ByteLength(self.0.wrapping_add(rhs.0))
200 }
201
202 pub const fn wrapping_sub(self, rhs: ByteLength) -> ByteLength {
204 ByteLength(self.0.wrapping_sub(rhs.0))
205 }
206
207 pub const fn wrapping_mul(self, rhs: ByteLength) -> ByteLength {
209 ByteLength(self.0.wrapping_mul(rhs.0))
210 }
211
212 pub const fn wrapping_div(self, rhs: ByteLength) -> ByteLength {
214 ByteLength(self.0.wrapping_div(rhs.0))
215 }
216
217 pub fn checked_add(self, rhs: ByteLength) -> Option<ByteLength> {
219 self.0.checked_add(rhs.0).map(ByteLength)
220 }
221
222 pub fn checked_sub(self, rhs: ByteLength) -> Option<ByteLength> {
224 self.0.checked_sub(rhs.0).map(ByteLength)
225 }
226
227 pub fn checked_mul(self, rhs: ByteLength) -> Option<ByteLength> {
229 self.0.checked_mul(rhs.0).map(ByteLength)
230 }
231
232 pub fn checked_div(self, rhs: ByteLength) -> Option<ByteLength> {
234 self.0.checked_div(rhs.0).map(ByteLength)
235 }
236}
237
238impl ByteLength {
240 pub const fn from_byte(bytes: usize) -> Self {
244 ByteLength(bytes)
245 }
246
247 const fn new(value: usize, scale: usize) -> Self {
248 ByteLength(value.saturating_mul(scale))
249 }
250
251 pub const fn from_kibi(kibi_bytes: usize) -> Self {
255 Self::new(kibi_bytes, 1024)
256 }
257
258 pub const fn from_kilo(kibi_bytes: usize) -> Self {
262 Self::new(kibi_bytes, 1000)
263 }
264
265 pub const fn from_mebi(mebi_bytes: usize) -> Self {
269 Self::new(mebi_bytes, 1024usize.pow(2))
270 }
271
272 pub const fn from_mega(mebi_bytes: usize) -> Self {
276 Self::new(mebi_bytes, 1000usize.pow(2))
277 }
278
279 pub const fn from_gibi(gibi_bytes: usize) -> Self {
283 Self::new(gibi_bytes, 1024usize.pow(3))
284 }
285
286 pub const fn from_giga(giga_bytes: usize) -> Self {
290 Self::new(giga_bytes, 1000usize.pow(3))
291 }
292
293 pub const fn from_tebi(gibi_bytes: usize) -> Self {
297 Self::new(gibi_bytes, 1024usize.pow(4))
298 }
299
300 pub const fn from_tera(tera_bytes: usize) -> Self {
304 Self::new(tera_bytes, 1000usize.pow(4))
305 }
306}
307
308impl ByteLength {
309 pub fn max(self, other: Self) -> Self {
311 Self(self.0.max(other.0))
312 }
313
314 pub fn min(self, other: Self) -> Self {
316 Self(self.0.min(other.0))
317 }
318}
319
320impl fmt::Debug for ByteLength {
321 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
322 if f.alternate() {
323 f.debug_tuple("ByteLength").field(&self.0).finish()
324 } else {
325 write!(f, "ByteLength({self})")
326 }
327 }
328}
329
330impl fmt::Display for ByteLength {
332 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
333 if f.alternate() {
336 if self.0 >= 1024usize.pow(4) {
337 write!(f, "{:.2}TiB", self.tebis())
338 } else if self.0 >= 1024usize.pow(3) {
339 write!(f, "{:.2}GiB", self.gibis())
340 } else if self.0 >= 1024usize.pow(2) {
341 write!(f, "{:.2}MiB", self.mebis())
342 } else if self.0 >= 1024 {
343 write!(f, "{:.2}KiB", self.kibis())
344 } else {
345 write!(f, "{}B", self.bytes())
346 }
347 } else if self.0 >= 1000usize.pow(4) {
348 write!(f, "{:.2}TB", self.teras())
349 } else if self.0 >= 1000usize.pow(3) {
350 write!(f, "{:.2}GB", self.gigas())
351 } else if self.0 >= 1000usize.pow(2) {
352 write!(f, "{:.2}MB", self.megas())
353 } else if self.0 >= 1000 {
354 write!(f, "{:.2}kB", self.kilos())
355 } else {
356 write!(f, "{}B", self.bytes())
357 }
358 }
359}
360
361impl<S: Into<Factor>> ops::Mul<S> for ByteLength {
362 type Output = Self;
363
364 fn mul(mut self, rhs: S) -> Self {
365 self.0 = (self.0 as f64 * rhs.into().0 as f64) as usize;
366 self
367 }
368}
369impl<S: Into<Factor>> ops::MulAssign<S> for ByteLength {
370 fn mul_assign(&mut self, rhs: S) {
371 *self = *self * rhs;
372 }
373}
374impl<S: Into<Factor>> ops::Div<S> for ByteLength {
375 type Output = Self;
376
377 fn div(mut self, rhs: S) -> Self {
378 self.0 = (self.0 as f64 / rhs.into().0 as f64) as usize;
379 self
380 }
381}
382impl<S: Into<Factor>> ops::DivAssign<S> for ByteLength {
383 fn div_assign(&mut self, rhs: S) {
384 *self = *self / rhs;
385 }
386}