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