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}