byte_unit/byte/
mod.rs

1mod adjusted;
2mod built_in_traits;
3mod constants;
4mod decimal;
5mod parse;
6#[cfg(feature = "rocket")]
7mod rocket_traits;
8#[cfg(feature = "schemars")]
9mod schemars_traits;
10#[cfg(feature = "serde")]
11mod serde_traits;
12
13use core::fmt::{self, Alignment, Display, Formatter, Write};
14
15pub use adjusted::*;
16use rust_decimal::prelude::*;
17
18use crate::{
19    common::{ceil_f32, ceil_f64},
20    Unit,
21};
22
23#[cfg(feature = "u128")]
24const RONNABYTE: u128 = 1_000_000_000_000_000_000_000_000_000; // RB
25
26#[cfg(feature = "u128")]
27#[derive(Debug, Clone, Copy, PartialOrd, Ord, PartialEq, Eq, Hash, Default)]
28/// Representing the size in bytes.
29pub struct Byte(u128);
30
31#[cfg(not(feature = "u128"))]
32#[derive(Debug, Clone, Copy, PartialOrd, Ord, PartialEq, Eq, Hash, Default)]
33/// Representing the size in bytes.
34pub struct Byte(u64);
35
36impl Display for Byte {
37    /// Formats the value using the given formatter.
38    ///
39    /// # Examples
40    ///
41    /// ```
42    /// use byte_unit::{Byte, Unit};
43    ///
44    /// let byte = Byte::from_u64_with_unit(1555, Unit::KB).unwrap();
45    ///
46    /// assert_eq!("1555000", byte.to_string());
47    /// ```
48    ///
49    /// ```
50    /// use byte_unit::{Byte, UnitType};
51    ///
52    /// let byte_based_2 = Byte::from_u64(10240);
53    /// let byte_based_10 = Byte::from_u64(10000);
54    ///
55    /// assert_eq!("10240", format!("{byte_based_2}"));
56    /// assert_eq!("10000", format!("{byte_based_10}"));
57    ///
58    /// // with an exact unit
59    /// assert_eq!("10 KiB", format!("{byte_based_2:#}"));
60    /// assert_eq!("10 KB", format!("{byte_based_10:#}"));
61    ///
62    /// // with an exact unit, no spaces between the value and the unit
63    /// assert_eq!("10KiB", format!("{byte_based_2:-#}"));
64    /// assert_eq!("10KB", format!("{byte_based_10:-#}"));
65    ///
66    /// // with a width, left alignment
67    /// assert_eq!("10     KiB", format!("{byte_based_2:#10}"));
68    /// assert_eq!("10      KB", format!("{byte_based_10:#10}"));
69    ///
70    /// // with a width, right alignment
71    /// assert_eq!("    10 KiB", format!("{byte_based_2:>#10}"));
72    /// assert_eq!("     10 KB", format!("{byte_based_10:>#10}"));
73    ///
74    /// // with a width, right alignment, more spaces between the value and the unit
75    /// assert_eq!("    10 KiB", format!("{byte_based_2:>+#10}"));
76    /// assert_eq!("    10  KB", format!("{byte_based_10:>+#10}"));
77    /// ```
78    ///
79    /// ```
80    /// use byte_unit::{Byte, UnitType};
81    ///
82    /// let byte = Byte::from_u64(3211776);
83    ///
84    /// assert_eq!("3211776", format!("{byte}"));
85    ///
86    /// // with a unit, still precisely
87    /// assert_eq!("3136.5 KiB", format!("{byte:#}"));
88    ///
89    /// // with a unit and a larger precision (default is 3), still precisely
90    /// assert_eq!("3.211776 MB", format!("{byte:#.6}"));
91    ///
92    /// // with a unit and a smaller precision (default is 3), still precisely
93    /// assert_eq!("3211776 B", format!("{byte:#.0}"));
94    /// ```
95    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
96        if f.alternate() {
97            let precision = f.precision().unwrap_or(3);
98
99            let (mut value, unit) = self.get_recoverable_unit(false, precision);
100
101            value = value.normalize();
102
103            let space_length = if f.sign_plus() {
104                4 - unit.as_str().len()
105            } else if f.sign_minus() {
106                0
107            } else {
108                1
109            };
110
111            if let Some(mut width) = f.width() {
112                let l = unit.as_str().len() + space_length;
113
114                if width > l + 1 {
115                    width -= l;
116
117                    let alignment = f.align().unwrap_or(Alignment::Left);
118
119                    match alignment {
120                        Alignment::Left | Alignment::Center => {
121                            f.write_fmt(format_args!("{value:<width$}"))?
122                        },
123                        Alignment::Right => f.write_fmt(format_args!("{value:>width$}"))?,
124                    }
125                } else {
126                    f.write_fmt(format_args!("{value}"))?;
127                }
128            } else {
129                f.write_fmt(format_args!("{value}"))?;
130            }
131
132            for _ in 0..space_length {
133                f.write_char(' ')?;
134            }
135
136            f.write_fmt(format_args!("{unit}"))
137        } else {
138            Display::fmt(&self.0, f)
139        }
140    }
141}
142
143/// Associated functions for building `Byte` instances.
144impl Byte {
145    /// Create a new `Byte` instance from a size in bytes.
146    ///
147    /// # Examples
148    ///
149    /// ```
150    /// # use byte_unit::Byte;
151    /// let byte = Byte::from_u128(15000000).unwrap(); // 15 MB
152    /// ```
153    ///
154    /// # Points to Note
155    ///
156    /// * If the input **size** is too large (the maximum is **10<sup>27</sup> - 1** if the `u128` feature is enabled, or **2<sup>64</sup> - 1** otherwise), this function will return `None`.
157    #[inline]
158    pub const fn from_u128(size: u128) -> Option<Self> {
159        #[cfg(feature = "u128")]
160        {
161            if size < RONNABYTE {
162                Some(Byte(size))
163            } else {
164                None
165            }
166        }
167
168        #[cfg(not(feature = "u128"))]
169        {
170            if size <= u64::MAX as u128 {
171                Some(Byte(size as u64))
172            } else {
173                None
174            }
175        }
176    }
177
178    /// Create a new `Byte` instance from a size in bytes.
179    ///
180    /// # Examples
181    ///
182    /// ```
183    /// # use byte_unit::Byte;
184    /// let byte = unsafe { Byte::from_u128_unsafe(15000000) }; // 15 MB
185    /// ```
186    ///
187    /// # Safety
188    /// You must ensure the input **size** is not too large (the maximum is **10<sup>27</sup> - 1** if the `u128` feature is enabled, or **2<sup>64</sup> - 1** otherwise) on your own.
189    #[inline]
190    pub const unsafe fn from_u128_unsafe(size: u128) -> Self {
191        #[cfg(feature = "u128")]
192        {
193            Byte(size)
194        }
195
196        #[cfg(not(feature = "u128"))]
197        {
198            Byte(size as u64)
199        }
200    }
201
202    /// Create a new `Byte` instance from a size in bytes.
203    ///
204    /// # Examples
205    ///
206    /// ```
207    /// # use byte_unit::Byte;
208    /// let byte = Byte::from_u64(15000000); // 15 MB
209    /// ```
210    #[inline]
211    pub const fn from_u64(size: u64) -> Self {
212        #[cfg(feature = "u128")]
213        {
214            Byte(size as u128)
215        }
216
217        #[cfg(not(feature = "u128"))]
218        {
219            Byte(size)
220        }
221    }
222
223    /// Create a new `Byte` instance from a size in bytes.
224    ///
225    /// # Examples
226    ///
227    /// ```
228    /// # use byte_unit::Byte;
229    /// let byte = Byte::from_f64(15000000.0).unwrap(); // 15 MB
230    /// ```
231    ///
232    /// # Points to Note
233    ///
234    /// * If the input **size** is too large (the maximum is **10<sup>27</sup> - 1** if the `u128` feature is enabled, or **2<sup>64</sup> - 1** otherwise) or not greater than or equal to **0**, this function will return `None`.
235    /// * The fractional part will be rounded up.
236    #[inline]
237    pub fn from_f64(size: f64) -> Option<Self> {
238        if size >= 0.0 {
239            #[cfg(feature = "u128")]
240            {
241                let size = ceil_f64(size) as u128;
242
243                if size < RONNABYTE {
244                    Some(Byte(size))
245                } else {
246                    None
247                }
248            }
249
250            #[cfg(not(feature = "u128"))]
251            {
252                let size = ceil_f64(size) as u64;
253
254                if size < u64::MAX {
255                    Some(Byte(size))
256                } else {
257                    None
258                }
259            }
260        } else {
261            None
262        }
263    }
264
265    /// Create a new `Byte` instance from a size in bytes.
266    ///
267    /// # Examples
268    ///
269    /// ```
270    /// # use byte_unit::Byte;
271    /// let byte = Byte::from_f32(15000000.0).unwrap(); // 15 MB
272    /// ```
273    ///
274    /// # Points to Note
275    ///
276    /// * If the input **size** is too large (the maximum is **10<sup>27</sup> - 1** if the `u128` feature is enabled, or **2<sup>64</sup> - 1** otherwise) or not greater than or equal to **0**, this function will return `None`.
277    /// * The fractional part will be rounded up.
278    #[inline]
279    pub fn from_f32(size: f32) -> Option<Self> {
280        if size >= 0.0 {
281            #[cfg(feature = "u128")]
282            {
283                let size = ceil_f32(size) as u128;
284
285                if size < RONNABYTE {
286                    Some(Byte(size))
287                } else {
288                    None
289                }
290            }
291
292            #[cfg(not(feature = "u128"))]
293            {
294                let size = ceil_f32(size) as u64;
295
296                if size < u64::MAX {
297                    Some(Byte(size))
298                } else {
299                    None
300                }
301            }
302        } else {
303            None
304        }
305    }
306
307    /// Create a new `Byte` instance from a size in bytes.
308    ///
309    /// # Examples
310    ///
311    /// ```
312    /// # use byte_unit::Byte;
313    /// let byte = Byte::from_i128(15000000).unwrap(); // 15 MB
314    /// ```
315    ///
316    /// # Points to Note
317    ///
318    /// * If the input **size** is too large (the maximum is **10<sup>27</sup> - 1** if the `u128` feature is enabled, or **2<sup>64</sup> - 1** otherwise) or negative, this function will return `None`.
319    #[inline]
320    pub const fn from_i128(size: i128) -> Option<Self> {
321        if size >= 0 {
322            Self::from_u128(size as u128)
323        } else {
324            None
325        }
326    }
327
328    /// Create a new `Byte` instance from a size in bytes.
329    ///
330    /// # Examples
331    ///
332    /// ```
333    /// # use byte_unit::Byte;
334    /// let byte = Byte::from_i64(15000000).unwrap(); // 15 MB
335    /// ```
336    ///
337    /// # Points to Note
338    ///
339    /// * If the input **size** is negative, this function will return `None`.
340    #[inline]
341    pub const fn from_i64(size: i64) -> Option<Self> {
342        if size >= 0 {
343            Some(Self::from_u64(size as u64))
344        } else {
345            None
346        }
347    }
348}
349
350/// Associated functions for building `Byte` instances (with `Unit`).
351impl Byte {
352    /// Create a new `Byte` instance from a size of bytes with a unit.
353    ///
354    /// # Examples
355    ///
356    /// ```
357    /// use byte_unit::{Byte, Unit};
358    ///
359    /// let byte = Byte::from_u128_with_unit(15, Unit::MB).unwrap(); // 15 MB
360    /// ```
361    ///
362    /// # Points to Note
363    ///
364    /// * If the calculated byte is too large, this function will return `None`.
365    /// * If the input **unit** is `Bit`, the calculated byte will be rounded up.
366    #[inline]
367    pub const fn from_u128_with_unit(size: u128, unit: Unit) -> Option<Self> {
368        let v = {
369            match unit {
370                Unit::Bit => {
371                    if size & 11 > 0 {
372                        (size >> 3) + 1
373                    } else {
374                        size >> 3
375                    }
376                },
377                Unit::B => size,
378                _ => match size.checked_mul(unit.as_bytes_u128()) {
379                    Some(v) => v,
380                    None => return None,
381                },
382            }
383        };
384
385        Self::from_u128(v)
386    }
387
388    /// Create a new `Byte` instance from a size of bytes with a unit.
389    ///
390    /// # Examples
391    ///
392    /// ```
393    /// use byte_unit::{Byte, Unit};
394    ///
395    /// let byte = Byte::from_u64_with_unit(15, Unit::MB).unwrap(); // 15 MB
396    /// ```
397    ///
398    /// # Points to Note
399    ///
400    /// * If the calculated byte is too large, this function will return `None`.
401    /// * If the input **unit** is `Bit`, the calculated byte will be rounded up.
402    #[inline]
403    pub const fn from_u64_with_unit(size: u64, unit: Unit) -> Option<Self> {
404        #[cfg(feature = "u128")]
405        {
406            Self::from_u128_with_unit(size as u128, unit)
407        }
408
409        #[cfg(not(feature = "u128"))]
410        {
411            let v = {
412                match unit {
413                    Unit::Bit => {
414                        if size & 11 > 0 {
415                            (size >> 3) + 1
416                        } else {
417                            size >> 3
418                        }
419                    },
420                    Unit::B => size,
421                    _ => match size.checked_mul(unit.as_bytes_u64()) {
422                        Some(v) => v,
423                        None => return None,
424                    },
425                }
426            };
427
428            Some(Self::from_u64(v))
429        }
430    }
431
432    /// Create a new `Byte` instance from a size of bytes with a unit.
433    ///
434    /// # Examples
435    ///
436    /// ```
437    /// use byte_unit::{Byte, Unit};
438    ///
439    /// let byte = Byte::from_f64_with_unit(15.0, Unit::MB).unwrap(); // 15 MB
440    /// ```
441    ///
442    /// # Points to Note
443    ///
444    /// * If the calculated byte is too large or not greater than or equal to **0**, this function will return `None`.
445    /// * The calculated byte will be rounded up.
446    #[inline]
447    pub fn from_f64_with_unit(size: f64, unit: Unit) -> Option<Self> {
448        match Decimal::from_f64(size) {
449            Some(size) => Self::from_decimal_with_unit(size, unit),
450            None => None,
451        }
452    }
453
454    /// Create a new `Byte` instance from a size of bytes with a unit.
455    ///
456    /// # Examples
457    ///
458    /// ```
459    /// use byte_unit::{Byte, Unit};
460    ///
461    /// let byte = Byte::from_f32_with_unit(15.0, Unit::MB).unwrap(); // 15 MB
462    /// ```
463    ///
464    /// # Points to Note
465    ///
466    /// * If the calculated byte is too large or not greater than or equal to **0**, this function will return `None`.
467    /// * The calculated byte will be rounded up.
468    #[inline]
469    pub fn from_f32_with_unit(size: f32, unit: Unit) -> Option<Self> {
470        match Decimal::from_f32(size) {
471            Some(size) => Self::from_decimal_with_unit(size, unit),
472            None => None,
473        }
474    }
475
476    /// Create a new `Byte` instance from a size of bytes with a unit.
477    ///
478    /// # Examples
479    ///
480    /// ```
481    /// use byte_unit::{Byte, Unit};
482    ///
483    /// let byte = Byte::from_i128_with_unit(15, Unit::MB).unwrap(); // 15 MB
484    /// ```
485    ///
486    /// # Points to Note
487    ///
488    /// * If the calculated byte is too large or negative, this function will return `None`.
489    /// * The calculated byte will be rounded up.
490    #[inline]
491    pub const fn from_i128_with_unit(size: i128, unit: Unit) -> Option<Self> {
492        if size >= 0 {
493            Self::from_u128_with_unit(size as u128, unit)
494        } else {
495            None
496        }
497    }
498
499    /// Create a new `Byte` instance from a size of bytes with a unit.
500    ///
501    /// # Examples
502    ///
503    /// ```
504    /// use byte_unit::{Byte, Unit};
505    ///
506    /// let byte = Byte::from_i64_with_unit(15, Unit::MB).unwrap(); // 15 MB
507    /// ```
508    ///
509    /// # Points to Note
510    ///
511    /// * If the calculated byte is too large or negative, this function will return `None`.
512    /// * The calculated byte will be rounded up.
513    #[inline]
514    pub const fn from_i64_with_unit(size: i64, unit: Unit) -> Option<Self> {
515        if size >= 0 {
516            Self::from_u64_with_unit(size as u64, unit)
517        } else {
518            None
519        }
520    }
521}
522
523/// Methods for converting a `Byte` instance into a primitive integer.
524impl Byte {
525    /// Retrieve the byte represented by this `Byte` instance.
526    ///
527    /// # Examples
528    ///
529    /// ```
530    /// use byte_unit::Byte;
531    ///
532    /// let byte = Byte::parse_str("123Kib", true).unwrap();
533    ///
534    /// let result = byte.as_u128();
535    ///
536    /// assert_eq!(125952, result);
537    /// ```
538    ///
539    /// ```
540    /// use byte_unit::Byte;
541    ///
542    /// let byte = Byte::parse_str("123Kib", false).unwrap();
543    ///
544    /// let result = byte.as_u128();
545    ///
546    /// assert_eq!(15744, result);
547    /// ```
548    #[inline]
549    pub const fn as_u128(self) -> u128 {
550        #[cfg(feature = "u128")]
551        {
552            self.0
553        }
554
555        #[cfg(not(feature = "u128"))]
556        {
557            self.0 as u128
558        }
559    }
560
561    /// Retrieve the byte represented by this `Byte` instance. When the `u128` feature is enabled, if the byte is actually greater than **2<sup>64</sup> - 1**, it will return **2<sup>64</sup> - 1**.
562    ///
563    /// # Examples
564    ///
565    /// ```
566    /// use byte_unit::Byte;
567    ///
568    /// let byte = Byte::parse_str("1kb", true).unwrap();
569    ///
570    /// let result = byte.as_u64();
571    ///
572    /// assert_eq!(1000, result);
573    /// ```
574    ///
575    /// ```
576    /// # #[cfg(feature = "u128")]
577    /// # {
578    /// use byte_unit::Byte;
579    ///
580    /// let byte = Byte::parse_str("1zb", true).unwrap();
581    ///
582    /// let result = byte.as_u64();
583    ///
584    /// assert_eq!(u64::MAX, result);
585    /// # }
586    /// ```
587    #[inline]
588    pub const fn as_u64(self) -> u64 {
589        #[cfg(feature = "u128")]
590        {
591            if self.0 <= u64::MAX as u128 {
592                self.0 as u64
593            } else {
594                u64::MAX
595            }
596        }
597
598        #[cfg(not(feature = "u128"))]
599        {
600            self.0
601        }
602    }
603
604    /// Retrieve the byte represented by this `Byte` instance.
605    ///
606    /// # Examples
607    ///
608    /// ```
609    /// use byte_unit::Byte;
610    ///
611    /// let byte = Byte::parse_str("1kb", true).unwrap();
612    ///
613    /// let result = byte.as_u64_checked();
614    ///
615    /// assert_eq!(Some(1000), result);
616    /// ```
617    ///
618    /// ```
619    /// # #[cfg(feature = "u128")]
620    /// # {
621    /// use byte_unit::Byte;
622    ///
623    /// let byte = Byte::parse_str("1zb", true).unwrap();
624    ///
625    /// let result = byte.as_u64_checked();
626    ///
627    /// assert_eq!(None, result);
628    /// # }
629    /// ```
630    #[inline]
631    pub const fn as_u64_checked(self) -> Option<u64> {
632        #[cfg(feature = "u128")]
633        {
634            if self.0 <= u64::MAX as u128 {
635                Some(self.0 as u64)
636            } else {
637                None
638            }
639        }
640
641        #[cfg(not(feature = "u128"))]
642        {
643            Some(self.0)
644        }
645    }
646}
647
648/// Methods for calculation.
649impl Byte {
650    /// Add another `Byte` instance.
651    ///
652    /// # Examples
653    ///
654    /// ```
655    /// use byte_unit::Byte;
656    ///
657    /// let byte_1 = Byte::from_u64(1024);
658    /// let byte_2 = Byte::from_u64(512);
659    ///
660    /// let byte = byte_1.add(byte_2).unwrap();
661    ///
662    /// assert_eq!(1536, byte.as_u64());
663    /// ```
664    ///
665    /// # Points to Note
666    ///
667    /// * If the calculated byte is too large, this function will return `None`.
668    #[inline]
669    pub const fn add(self, rhs: Byte) -> Option<Byte> {
670        match self.0.checked_add(rhs.0) {
671            Some(v) => Some(Byte(v)),
672            None => None,
673        }
674    }
675
676    /// Subtract another `Byte` instance.
677    ///
678    /// # Examples
679    ///
680    /// ```
681    /// use byte_unit::Byte;
682    ///
683    /// let byte_1 = Byte::from_u64(1024);
684    /// let byte_2 = Byte::from_u64(512);
685    ///
686    /// let byte = byte_1.subtract(byte_2).unwrap();
687    ///
688    /// assert_eq!(512, byte.as_u64());
689    /// ```
690    ///
691    /// # Points to Note
692    ///
693    /// * If the right-hand side is bigger then this `Byte` instance, this function will return `None`.
694    #[inline]
695    pub const fn subtract(self, rhs: Byte) -> Option<Byte> {
696        match self.0.checked_sub(rhs.0) {
697            Some(v) => Some(Byte(v)),
698            None => None,
699        }
700    }
701
702    /// Multiplied by an unsigned integer.
703    ///
704    /// # Examples
705    ///
706    /// ```
707    /// use byte_unit::Byte;
708    ///
709    /// let count = 100;
710    /// let byte = Byte::from_u64(1024);
711    ///
712    /// let total_byte = byte.multiply(100).unwrap();
713    ///
714    /// assert_eq!(102400, total_byte.as_u64());
715    /// ```
716    ///
717    /// # Points to Note
718    ///
719    /// * If the calculated byte is too large, this function will return `None`.
720    #[allow(unexpected_cfgs)]
721    #[inline]
722    pub const fn multiply(self, rhs: usize) -> Option<Byte> {
723        #[cfg(feature = "u128")]
724        {
725            match self.0.checked_mul(rhs as u128) {
726                Some(v) => Some(Byte(v)),
727                None => None,
728            }
729        }
730
731        #[cfg(not(feature = "u128"))]
732        {
733            #[cfg(target_pointer_width = "128")]
734            {
735                if rhs > u64::MAX as usize {
736                    return None;
737                }
738            }
739
740            match self.0.checked_mul(rhs as u64) {
741                Some(v) => Some(Byte(v)),
742                None => None,
743            }
744        }
745    }
746
747    /// Divided by an unsigned integer.
748    ///
749    /// # Examples
750    ///
751    /// ```
752    /// use byte_unit::Byte;
753    ///
754    /// let count = 100;
755    /// let byte = Byte::from_u64(1024);
756    ///
757    /// let total_byte = byte.divide(100).unwrap();
758    ///
759    /// assert_eq!(10, total_byte.as_u64());
760    /// ```
761    ///
762    /// # Points to Note
763    ///
764    /// * If the input right-hand side is zero, this function will return `None`.
765    /// * The result will be rounded down.
766    #[allow(unexpected_cfgs)]
767    #[inline]
768    pub const fn divide(self, rhs: usize) -> Option<Byte> {
769        #[cfg(feature = "u128")]
770        {
771            match self.0.checked_div(rhs as u128) {
772                Some(v) => Some(Byte(v)),
773                None => None,
774            }
775        }
776
777        #[cfg(not(feature = "u128"))]
778        {
779            #[cfg(target_pointer_width = "128")]
780            {
781                if rhs > u64::MAX as usize {
782                    return None;
783                }
784            }
785
786            match self.0.checked_div(rhs as u64) {
787                Some(v) => Some(Byte(v)),
788                None => None,
789            }
790        }
791    }
792
793    #[inline]
794    pub(crate) const fn div_8(self) -> Byte {
795        Byte(self.0 / 8)
796    }
797}
798
799/// Methods for finding an unit.
800impl Byte {
801    /// Obtain the largest unit which is the greatest factor of this `Byte` instance.
802    ///
803    /// # Examples
804    ///
805    /// ```
806    /// use byte_unit::{Byte, Unit};
807    ///
808    /// let byte = Byte::from_u64(3145728);
809    ///
810    /// let (n, unit) = byte.get_exact_unit(true);
811    ///
812    /// assert_eq!(3, n);
813    /// assert_eq!(Unit::MiB, unit);
814    /// ```
815    ///
816    /// ```
817    /// use byte_unit::{Byte, Unit};
818    ///
819    /// let byte = Byte::from_u64(375000);
820    ///
821    /// let (n, unit) = byte.get_exact_unit(true);
822    ///
823    /// assert_eq!(3, n);
824    /// assert_eq!(Unit::Mbit, unit);
825    /// ```
826    ///
827    /// ```
828    /// use byte_unit::{Byte, Unit};
829    ///
830    /// let byte = Byte::from_u64(375000);
831    ///
832    /// let (n, unit) = byte.get_exact_unit(false);
833    ///
834    /// assert_eq!(375, n);
835    /// assert_eq!(Unit::KB, unit);
836    /// ```
837    #[inline]
838    pub const fn get_exact_unit(self, allow_in_bits: bool) -> (u128, Unit) {
839        let bytes_v = self.as_u128();
840
841        let a = if allow_in_bits { Unit::get_multiples() } else { Unit::get_multiples_bytes() };
842        let mut i = a.len() - 1;
843
844        loop {
845            let unit = a[i];
846
847            let unit_v = unit.as_bytes_u128();
848
849            if bytes_v >= unit_v && bytes_v % unit_v == 0 {
850                return (bytes_v / unit_v, unit);
851            }
852
853            if i == 0 {
854                break;
855            }
856
857            i -= 1;
858        }
859
860        (bytes_v, Unit::B)
861    }
862}