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