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}