zng_unit/
byte.rs

1use std::{fmt, ops};
2
3use super::Factor;
4
5/// Extension methods for initializing [`ByteLength`] values.
6pub trait ByteUnits {
7    /// Bytes.
8    ///
9    /// See [`ByteLength`] for more details.
10    fn bytes(self) -> ByteLength;
11    /// Kibi-bytes.
12    ///
13    /// See [`ByteLength::from_kibi`] for more details.
14    fn kibibytes(self) -> ByteLength;
15    /// Kilo-bytes.
16    ///
17    /// See [`ByteLength::from_kilo`] for more details.
18    fn kilobytes(self) -> ByteLength;
19
20    /// Mebi-bytes.
21    ///
22    /// See [`ByteLength::from_mebi`] for more details.
23    fn mebibytes(self) -> ByteLength;
24    /// Mega-bytes.
25    ///
26    /// See [`ByteLength::from_mega`] for more details.
27    fn megabytes(self) -> ByteLength;
28
29    /// Gibi-bytes.
30    ///
31    /// See [`ByteLength::from_gibi`] for more details.
32    fn gibibytes(self) -> ByteLength;
33    /// Giga-bytes.
34    ///
35    /// See [`ByteLength::from_giga`] for more details.
36    fn gigabytes(self) -> ByteLength;
37
38    /// Tebi-bytes.
39    ///
40    /// See [`ByteLength::from_tebi`] for more details.
41    fn tebibytes(self) -> ByteLength;
42    /// Tera-bytes.
43    ///
44    /// See [`ByteLength::from_tera`] for more details.
45    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/// A length in bytes.
86///
87/// The value is stored in bytes, you can use associated functions to convert from other units or
88/// you can use the [`ByteUnits`] extension methods to initialize from an integer literal.
89#[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    /// Length in bytes.
123    ///
124    /// This is the same as `.0`.
125    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    /// Length in kibi-bytes.
134    pub fn kibis(self) -> f64 {
135        self.scaled(1024.0)
136    }
137
138    /// Length in kilo-bytes.
139    pub fn kilos(self) -> f64 {
140        self.scaled(1000.0)
141    }
142
143    /// Length in mebi-bytes.
144    pub fn mebis(self) -> f64 {
145        self.scaled(1024.0f64.powi(2))
146    }
147
148    /// Length in mega-bytes.
149    pub fn megas(self) -> f64 {
150        self.scaled(1000.0f64.powi(2))
151    }
152
153    /// Length in gibi-bytes.
154    pub fn gibis(self) -> f64 {
155        self.scaled(1024.0f64.powi(3))
156    }
157
158    /// Length in giga-bytes.
159    pub fn gigas(self) -> f64 {
160        self.scaled(1000.0f64.powi(3))
161    }
162
163    /// Length in tebi-bytes.
164    pub fn tebis(self) -> f64 {
165        self.scaled(1024.0f64.powi(4))
166    }
167
168    /// Length in tera-bytes.
169    pub fn teras(self) -> f64 {
170        self.scaled(1000.0f64.powi(4))
171    }
172
173    /// Maximum representable byte length.
174    pub const MAX: ByteLength = ByteLength(usize::MAX);
175
176    /// Adds the two lengths without overflowing or wrapping.
177    pub const fn saturating_add(self, rhs: ByteLength) -> ByteLength {
178        ByteLength(self.0.saturating_add(rhs.0))
179    }
180
181    /// Subtracts the two lengths without overflowing or wrapping.
182    pub const fn saturating_sub(self, rhs: ByteLength) -> ByteLength {
183        ByteLength(self.0.saturating_sub(rhs.0))
184    }
185
186    /// Multiplies the two lengths without overflowing or wrapping.
187    pub const fn saturating_mul(self, rhs: ByteLength) -> ByteLength {
188        ByteLength(self.0.saturating_mul(rhs.0))
189    }
190
191    // unstable
192    ///// Divides the two lengths without overflowing or wrapping.
193    //pub fn saturating_div(self, rhs: ByteLength) -> ByteLength {
194    //    ByteLength(self.0.saturating_div(rhs.0))
195    //}
196
197    /// Adds the two lengths wrapping overflows.
198    pub const fn wrapping_add(self, rhs: ByteLength) -> ByteLength {
199        ByteLength(self.0.wrapping_add(rhs.0))
200    }
201
202    /// Subtracts the two lengths wrapping overflows.
203    pub const fn wrapping_sub(self, rhs: ByteLength) -> ByteLength {
204        ByteLength(self.0.wrapping_sub(rhs.0))
205    }
206
207    /// Multiplies the two lengths wrapping overflows.
208    pub const fn wrapping_mul(self, rhs: ByteLength) -> ByteLength {
209        ByteLength(self.0.wrapping_mul(rhs.0))
210    }
211
212    /// Divides the two lengths wrapping overflows.
213    pub const fn wrapping_div(self, rhs: ByteLength) -> ByteLength {
214        ByteLength(self.0.wrapping_div(rhs.0))
215    }
216
217    /// Adds the two lengths, returns `None` if the sum overflows.
218    pub fn checked_add(self, rhs: ByteLength) -> Option<ByteLength> {
219        self.0.checked_add(rhs.0).map(ByteLength)
220    }
221
222    /// Subtracts the two lengths, returns `None` if the subtraction overflows.
223    pub fn checked_sub(self, rhs: ByteLength) -> Option<ByteLength> {
224        self.0.checked_sub(rhs.0).map(ByteLength)
225    }
226
227    /// Multiplies the two lengths, returns `None` if the sum overflows.
228    pub fn checked_mul(self, rhs: ByteLength) -> Option<ByteLength> {
229        self.0.checked_mul(rhs.0).map(ByteLength)
230    }
231
232    /// Divides the two lengths, returns `None` if the subtraction overflows.
233    pub fn checked_div(self, rhs: ByteLength) -> Option<ByteLength> {
234        self.0.checked_div(rhs.0).map(ByteLength)
235    }
236}
237
238/// Constructors
239impl ByteLength {
240    /// From bytes.
241    ///
242    /// This is the same as `ByteLength(bytes)`.
243    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    /// From kibi-bytes.
252    ///
253    /// 1 kibi-byte equals 1024 bytes.
254    pub const fn from_kibi(kibi_bytes: usize) -> Self {
255        Self::new(kibi_bytes, 1024)
256    }
257
258    /// From kilo-bytes.
259    ///
260    /// 1 kilo-byte equals 1000 bytes.
261    pub const fn from_kilo(kibi_bytes: usize) -> Self {
262        Self::new(kibi_bytes, 1000)
263    }
264
265    /// From mebi-bytes.
266    ///
267    /// 1 mebi-byte equals 1024² bytes.
268    pub const fn from_mebi(mebi_bytes: usize) -> Self {
269        Self::new(mebi_bytes, 1024usize.pow(2))
270    }
271
272    /// From mega-bytes.
273    ///
274    /// 1 mega-byte equals 1000² bytes.
275    pub const fn from_mega(mebi_bytes: usize) -> Self {
276        Self::new(mebi_bytes, 1000usize.pow(2))
277    }
278
279    /// From gibi-bytes.
280    ///
281    /// 1 gibi-byte equals 1024³ bytes.
282    pub const fn from_gibi(gibi_bytes: usize) -> Self {
283        Self::new(gibi_bytes, 1024usize.pow(3))
284    }
285
286    /// From giga-bytes.
287    ///
288    /// 1 giga-byte equals 1000³ bytes.
289    pub const fn from_giga(giga_bytes: usize) -> Self {
290        Self::new(giga_bytes, 1000usize.pow(3))
291    }
292
293    /// From tebi-bytes.
294    ///
295    /// 1 tebi-byte equals 1024^4 bytes.
296    pub const fn from_tebi(gibi_bytes: usize) -> Self {
297        Self::new(gibi_bytes, 1024usize.pow(4))
298    }
299
300    /// From tera-bytes.
301    ///
302    /// 1 tera-byte equals 1000^4 bytes.
303    pub const fn from_tera(tera_bytes: usize) -> Self {
304        Self::new(tera_bytes, 1000usize.pow(4))
305    }
306}
307
308impl ByteLength {
309    /// Compares and returns the maximum of two lengths.
310    pub fn max(self, other: Self) -> Self {
311        Self(self.0.max(other.0))
312    }
313
314    /// Compares and returns the minimum of two lengths.
315    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
330/// Alternative mode prints in binary units (kibi, mebi, gibi, tebi)
331impl fmt::Display for ByteLength {
332    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
333        // alternate uses 0..=1000 units, normal used 0..=1024 units.
334
335        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}