Skip to main content

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    Unit,
20    common::{ceil_f32, ceil_f64},
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 { Some(Byte(size)) } else { None }
162        }
163
164        #[cfg(not(feature = "u128"))]
165        {
166            if size <= u64::MAX as u128 { Some(Byte(size as u64)) } else { None }
167        }
168    }
169
170    /// Create a new `Byte` instance from a size in bytes.
171    ///
172    /// # Examples
173    ///
174    /// ```
175    /// # use byte_unit::Byte;
176    /// let byte = unsafe { Byte::from_u128_unsafe(15000000) }; // 15 MB
177    /// ```
178    ///
179    /// # Safety
180    /// 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.
181    #[inline]
182    pub const unsafe fn from_u128_unsafe(size: u128) -> Self {
183        #[cfg(feature = "u128")]
184        {
185            Byte(size)
186        }
187
188        #[cfg(not(feature = "u128"))]
189        {
190            Byte(size as u64)
191        }
192    }
193
194    /// Create a new `Byte` instance from a size in bytes.
195    ///
196    /// # Examples
197    ///
198    /// ```
199    /// # use byte_unit::Byte;
200    /// let byte = Byte::from_u64(15000000); // 15 MB
201    /// ```
202    #[inline]
203    pub const fn from_u64(size: u64) -> Self {
204        #[cfg(feature = "u128")]
205        {
206            Byte(size as u128)
207        }
208
209        #[cfg(not(feature = "u128"))]
210        {
211            Byte(size)
212        }
213    }
214
215    /// Create a new `Byte` instance from a size in bytes.
216    ///
217    /// # Examples
218    ///
219    /// ```
220    /// # use byte_unit::Byte;
221    /// let byte = Byte::from_f64(15000000.0).unwrap(); // 15 MB
222    /// ```
223    ///
224    /// # Points to Note
225    ///
226    /// * 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`.
227    /// * The fractional part will be rounded up.
228    #[inline]
229    pub fn from_f64(size: f64) -> Option<Self> {
230        if size >= 0.0 {
231            #[cfg(feature = "u128")]
232            {
233                let size = ceil_f64(size) as u128;
234
235                if size < RONNABYTE { Some(Byte(size)) } else { None }
236            }
237
238            #[cfg(not(feature = "u128"))]
239            {
240                let size = ceil_f64(size) as u64;
241
242                if size < u64::MAX { Some(Byte(size)) } else { None }
243            }
244        } else {
245            None
246        }
247    }
248
249    /// Create a new `Byte` instance from a size in bytes.
250    ///
251    /// # Examples
252    ///
253    /// ```
254    /// # use byte_unit::Byte;
255    /// let byte = Byte::from_f32(15000000.0).unwrap(); // 15 MB
256    /// ```
257    ///
258    /// # Points to Note
259    ///
260    /// * 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`.
261    /// * The fractional part will be rounded up.
262    #[inline]
263    pub fn from_f32(size: f32) -> Option<Self> {
264        if size >= 0.0 {
265            #[cfg(feature = "u128")]
266            {
267                let size = ceil_f32(size) as u128;
268
269                if size < RONNABYTE { Some(Byte(size)) } else { None }
270            }
271
272            #[cfg(not(feature = "u128"))]
273            {
274                let size = ceil_f32(size) as u64;
275
276                if size < u64::MAX { Some(Byte(size)) } else { None }
277            }
278        } else {
279            None
280        }
281    }
282
283    /// Create a new `Byte` instance from a size in bytes.
284    ///
285    /// # Examples
286    ///
287    /// ```
288    /// # use byte_unit::Byte;
289    /// let byte = Byte::from_i128(15000000).unwrap(); // 15 MB
290    /// ```
291    ///
292    /// # Points to Note
293    ///
294    /// * 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`.
295    #[inline]
296    pub const fn from_i128(size: i128) -> Option<Self> {
297        if size >= 0 { Self::from_u128(size as u128) } else { None }
298    }
299
300    /// Create a new `Byte` instance from a size in bytes.
301    ///
302    /// # Examples
303    ///
304    /// ```
305    /// # use byte_unit::Byte;
306    /// let byte = Byte::from_i64(15000000).unwrap(); // 15 MB
307    /// ```
308    ///
309    /// # Points to Note
310    ///
311    /// * If the input **size** is negative, this function will return `None`.
312    #[inline]
313    pub const fn from_i64(size: i64) -> Option<Self> {
314        if size >= 0 { Some(Self::from_u64(size as u64)) } else { None }
315    }
316}
317
318/// Associated functions for building `Byte` instances (with `Unit`).
319impl Byte {
320    /// Create a new `Byte` instance from a size of bytes with a unit.
321    ///
322    /// # Examples
323    ///
324    /// ```
325    /// use byte_unit::{Byte, Unit};
326    ///
327    /// let byte = Byte::from_u128_with_unit(15, Unit::MB).unwrap(); // 15 MB
328    /// ```
329    ///
330    /// # Points to Note
331    ///
332    /// * If the calculated byte is too large, this function will return `None`.
333    /// * If the input **unit** is `Bit`, the calculated byte will be rounded up.
334    #[inline]
335    pub const fn from_u128_with_unit(size: u128, unit: Unit) -> Option<Self> {
336        let v = {
337            match unit {
338                Unit::Bit => {
339                    if size & 7 > 0 {
340                        (size >> 3) + 1
341                    } else {
342                        size >> 3
343                    }
344                },
345                Unit::B => size,
346                _ => match size.checked_mul(unit.as_bytes_u128()) {
347                    Some(v) => v,
348                    None => return None,
349                },
350            }
351        };
352
353        Self::from_u128(v)
354    }
355
356    /// Create a new `Byte` instance from a size of bytes with a unit.
357    ///
358    /// # Examples
359    ///
360    /// ```
361    /// use byte_unit::{Byte, Unit};
362    ///
363    /// let byte = Byte::from_u64_with_unit(15, Unit::MB).unwrap(); // 15 MB
364    /// ```
365    ///
366    /// # Points to Note
367    ///
368    /// * If the calculated byte is too large, this function will return `None`.
369    /// * If the input **unit** is `Bit`, the calculated byte will be rounded up.
370    #[inline]
371    pub const fn from_u64_with_unit(size: u64, unit: Unit) -> Option<Self> {
372        #[cfg(feature = "u128")]
373        {
374            Self::from_u128_with_unit(size as u128, unit)
375        }
376
377        #[cfg(not(feature = "u128"))]
378        {
379            let v = {
380                match unit {
381                    Unit::Bit => {
382                        if size & 7 > 0 {
383                            (size >> 3) + 1
384                        } else {
385                            size >> 3
386                        }
387                    },
388                    Unit::B => size,
389                    _ => match size.checked_mul(unit.as_bytes_u64()) {
390                        Some(v) => v,
391                        None => return None,
392                    },
393                }
394            };
395
396            Some(Self::from_u64(v))
397        }
398    }
399
400    /// Create a new `Byte` instance from a size of bytes with a unit.
401    ///
402    /// # Examples
403    ///
404    /// ```
405    /// use byte_unit::{Byte, Unit};
406    ///
407    /// let byte = Byte::from_f64_with_unit(15.0, Unit::MB).unwrap(); // 15 MB
408    /// ```
409    ///
410    /// # Points to Note
411    ///
412    /// * If the calculated byte is too large or not greater than or equal to **0**, this function will return `None`.
413    /// * The calculated byte will be rounded up.
414    #[inline]
415    pub fn from_f64_with_unit(size: f64, unit: Unit) -> Option<Self> {
416        match Decimal::from_f64(size) {
417            Some(size) => Self::from_decimal_with_unit(size, unit),
418            None => None,
419        }
420    }
421
422    /// Create a new `Byte` instance from a size of bytes with a unit.
423    ///
424    /// # Examples
425    ///
426    /// ```
427    /// use byte_unit::{Byte, Unit};
428    ///
429    /// let byte = Byte::from_f32_with_unit(15.0, Unit::MB).unwrap(); // 15 MB
430    /// ```
431    ///
432    /// # Points to Note
433    ///
434    /// * If the calculated byte is too large or not greater than or equal to **0**, this function will return `None`.
435    /// * The calculated byte will be rounded up.
436    #[inline]
437    pub fn from_f32_with_unit(size: f32, unit: Unit) -> Option<Self> {
438        match Decimal::from_f32(size) {
439            Some(size) => Self::from_decimal_with_unit(size, unit),
440            None => None,
441        }
442    }
443
444    /// Create a new `Byte` instance from a size of bytes with a unit.
445    ///
446    /// # Examples
447    ///
448    /// ```
449    /// use byte_unit::{Byte, Unit};
450    ///
451    /// let byte = Byte::from_i128_with_unit(15, Unit::MB).unwrap(); // 15 MB
452    /// ```
453    ///
454    /// # Points to Note
455    ///
456    /// * If the calculated byte is too large or negative, this function will return `None`.
457    /// * The calculated byte will be rounded up.
458    #[inline]
459    pub const fn from_i128_with_unit(size: i128, unit: Unit) -> Option<Self> {
460        if size >= 0 { Self::from_u128_with_unit(size as u128, unit) } else { None }
461    }
462
463    /// Create a new `Byte` instance from a size of bytes with a unit.
464    ///
465    /// # Examples
466    ///
467    /// ```
468    /// use byte_unit::{Byte, Unit};
469    ///
470    /// let byte = Byte::from_i64_with_unit(15, Unit::MB).unwrap(); // 15 MB
471    /// ```
472    ///
473    /// # Points to Note
474    ///
475    /// * If the calculated byte is too large or negative, this function will return `None`.
476    /// * The calculated byte will be rounded up.
477    #[inline]
478    pub const fn from_i64_with_unit(size: i64, unit: Unit) -> Option<Self> {
479        if size >= 0 { Self::from_u64_with_unit(size as u64, unit) } else { None }
480    }
481}
482
483/// Methods for converting a `Byte` instance into a primitive integer.
484impl Byte {
485    /// Retrieve the byte represented by this `Byte` instance.
486    ///
487    /// # Examples
488    ///
489    /// ```
490    /// use byte_unit::Byte;
491    ///
492    /// let byte = Byte::parse_str("123Kib", true).unwrap();
493    ///
494    /// let result = byte.as_u128();
495    ///
496    /// assert_eq!(125952, result);
497    /// ```
498    ///
499    /// ```
500    /// use byte_unit::Byte;
501    ///
502    /// let byte = Byte::parse_str("123Kib", false).unwrap();
503    ///
504    /// let result = byte.as_u128();
505    ///
506    /// assert_eq!(15744, result);
507    /// ```
508    #[inline]
509    pub const fn as_u128(self) -> u128 {
510        #[cfg(feature = "u128")]
511        {
512            self.0
513        }
514
515        #[cfg(not(feature = "u128"))]
516        {
517            self.0 as u128
518        }
519    }
520
521    /// 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**.
522    ///
523    /// # Examples
524    ///
525    /// ```
526    /// use byte_unit::Byte;
527    ///
528    /// let byte = Byte::parse_str("1kb", true).unwrap();
529    ///
530    /// let result = byte.as_u64();
531    ///
532    /// assert_eq!(1000, result);
533    /// ```
534    ///
535    /// ```
536    /// # #[cfg(feature = "u128")]
537    /// # {
538    /// use byte_unit::Byte;
539    ///
540    /// let byte = Byte::parse_str("1zb", true).unwrap();
541    ///
542    /// let result = byte.as_u64();
543    ///
544    /// assert_eq!(u64::MAX, result);
545    /// # }
546    /// ```
547    #[inline]
548    pub const fn as_u64(self) -> u64 {
549        #[cfg(feature = "u128")]
550        {
551            if self.0 <= u64::MAX as u128 { self.0 as u64 } else { u64::MAX }
552        }
553
554        #[cfg(not(feature = "u128"))]
555        {
556            self.0
557        }
558    }
559
560    /// Retrieve the byte represented by this `Byte` instance.
561    ///
562    /// # Examples
563    ///
564    /// ```
565    /// use byte_unit::Byte;
566    ///
567    /// let byte = Byte::parse_str("1kb", true).unwrap();
568    ///
569    /// let result = byte.as_u64_checked();
570    ///
571    /// assert_eq!(Some(1000), result);
572    /// ```
573    ///
574    /// ```
575    /// # #[cfg(feature = "u128")]
576    /// # {
577    /// use byte_unit::Byte;
578    ///
579    /// let byte = Byte::parse_str("1zb", true).unwrap();
580    ///
581    /// let result = byte.as_u64_checked();
582    ///
583    /// assert_eq!(None, result);
584    /// # }
585    /// ```
586    #[inline]
587    pub const fn as_u64_checked(self) -> Option<u64> {
588        #[cfg(feature = "u128")]
589        {
590            if self.0 <= u64::MAX as u128 { Some(self.0 as u64) } else { None }
591        }
592
593        #[cfg(not(feature = "u128"))]
594        {
595            Some(self.0)
596        }
597    }
598}
599
600/// Methods for calculation.
601impl Byte {
602    /// Add another `Byte` instance.
603    ///
604    /// # Examples
605    ///
606    /// ```
607    /// use byte_unit::Byte;
608    ///
609    /// let byte_1 = Byte::from_u64(1024);
610    /// let byte_2 = Byte::from_u64(512);
611    ///
612    /// let byte = byte_1.add(byte_2).unwrap();
613    ///
614    /// assert_eq!(1536, byte.as_u64());
615    /// ```
616    ///
617    /// # Points to Note
618    ///
619    /// * If the calculated byte is too large, this function will return `None`.
620    #[inline]
621    pub const fn add(self, rhs: Byte) -> Option<Byte> {
622        match self.0.checked_add(rhs.0) {
623            Some(v) => Some(Byte(v)),
624            None => None,
625        }
626    }
627
628    /// Subtract another `Byte` instance.
629    ///
630    /// # Examples
631    ///
632    /// ```
633    /// use byte_unit::Byte;
634    ///
635    /// let byte_1 = Byte::from_u64(1024);
636    /// let byte_2 = Byte::from_u64(512);
637    ///
638    /// let byte = byte_1.subtract(byte_2).unwrap();
639    ///
640    /// assert_eq!(512, byte.as_u64());
641    /// ```
642    ///
643    /// # Points to Note
644    ///
645    /// * If the right-hand side is bigger then this `Byte` instance, this function will return `None`.
646    #[inline]
647    pub const fn subtract(self, rhs: Byte) -> Option<Byte> {
648        match self.0.checked_sub(rhs.0) {
649            Some(v) => Some(Byte(v)),
650            None => None,
651        }
652    }
653
654    /// Multiplied by an unsigned integer.
655    ///
656    /// # Examples
657    ///
658    /// ```
659    /// use byte_unit::Byte;
660    ///
661    /// let count = 100;
662    /// let byte = Byte::from_u64(1024);
663    ///
664    /// let total_byte = byte.multiply(100).unwrap();
665    ///
666    /// assert_eq!(102400, total_byte.as_u64());
667    /// ```
668    ///
669    /// # Points to Note
670    ///
671    /// * If the calculated byte is too large, this function will return `None`.
672    #[allow(unexpected_cfgs)]
673    #[inline]
674    pub const fn multiply(self, rhs: usize) -> Option<Byte> {
675        #[cfg(feature = "u128")]
676        {
677            match self.0.checked_mul(rhs as u128) {
678                Some(v) => Some(Byte(v)),
679                None => None,
680            }
681        }
682
683        #[cfg(not(feature = "u128"))]
684        {
685            #[cfg(target_pointer_width = "128")]
686            {
687                if rhs > u64::MAX as usize {
688                    return None;
689                }
690            }
691
692            match self.0.checked_mul(rhs as u64) {
693                Some(v) => Some(Byte(v)),
694                None => None,
695            }
696        }
697    }
698
699    /// Divided by an unsigned integer.
700    ///
701    /// # Examples
702    ///
703    /// ```
704    /// use byte_unit::Byte;
705    ///
706    /// let count = 100;
707    /// let byte = Byte::from_u64(1024);
708    ///
709    /// let total_byte = byte.divide(100).unwrap();
710    ///
711    /// assert_eq!(10, total_byte.as_u64());
712    /// ```
713    ///
714    /// # Points to Note
715    ///
716    /// * If the input right-hand side is zero, this function will return `None`.
717    /// * The result will be rounded down.
718    #[allow(unexpected_cfgs)]
719    #[inline]
720    pub const fn divide(self, rhs: usize) -> Option<Byte> {
721        #[cfg(feature = "u128")]
722        {
723            match self.0.checked_div(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_div(rhs as u64) {
739                Some(v) => Some(Byte(v)),
740                None => None,
741            }
742        }
743    }
744
745    #[inline]
746    pub(crate) const fn div_8(self) -> Byte {
747        Byte(self.0 / 8)
748    }
749}
750
751/// Methods for finding an unit.
752impl Byte {
753    /// Obtain the largest unit which is the greatest factor of this `Byte` instance.
754    ///
755    /// # Examples
756    ///
757    /// ```
758    /// use byte_unit::{Byte, Unit};
759    ///
760    /// let byte = Byte::from_u64(3145728);
761    ///
762    /// let (n, unit) = byte.get_exact_unit(true);
763    ///
764    /// assert_eq!(3, n);
765    /// assert_eq!(Unit::MiB, unit);
766    /// ```
767    ///
768    /// ```
769    /// use byte_unit::{Byte, Unit};
770    ///
771    /// let byte = Byte::from_u64(375000);
772    ///
773    /// let (n, unit) = byte.get_exact_unit(true);
774    ///
775    /// assert_eq!(3, n);
776    /// assert_eq!(Unit::Mbit, unit);
777    /// ```
778    ///
779    /// ```
780    /// use byte_unit::{Byte, Unit};
781    ///
782    /// let byte = Byte::from_u64(375000);
783    ///
784    /// let (n, unit) = byte.get_exact_unit(false);
785    ///
786    /// assert_eq!(375, n);
787    /// assert_eq!(Unit::KB, unit);
788    /// ```
789    #[inline]
790    pub const fn get_exact_unit(self, allow_in_bits: bool) -> (u128, Unit) {
791        let bytes_v = self.as_u128();
792
793        let a = if allow_in_bits { Unit::get_multiples() } else { Unit::get_multiples_bytes() };
794        let mut i = a.len() - 1;
795
796        loop {
797            let unit = a[i];
798
799            let unit_v = unit.as_bytes_u128();
800
801            if bytes_v >= unit_v && bytes_v % unit_v == 0 {
802                return (bytes_v / unit_v, unit);
803            }
804
805            if i == 0 {
806                break;
807            }
808
809            i -= 1;
810        }
811
812        (bytes_v, Unit::B)
813    }
814}