byte_unit/bit/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 RONNABIT: 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 bits.
29pub struct Bit(u128);
30
31#[cfg(not(feature = "u128"))]
32#[derive(Debug, Clone, Copy, PartialOrd, Ord, PartialEq, Eq, Hash, Default)]
33/// Representing the size in bits.
34pub struct Bit(u64);
35
36impl Display for Bit {
37 /// Formats the value using the given formatter.
38 ///
39 /// # Examples
40 ///
41 /// ```
42 /// use byte_unit::{Bit, Unit};
43 ///
44 /// let bit = Bit::from_u64_with_unit(1555, Unit::Kbit).unwrap();
45 ///
46 /// assert_eq!("1555000", bit.to_string());
47 /// ```
48 ///
49 /// ```
50 /// use byte_unit::{Bit, UnitType};
51 ///
52 /// let bit_based_2 = Bit::from_u64(10240);
53 /// let bit_based_10 = Bit::from_u64(10000);
54 ///
55 /// assert_eq!("10240", format!("{bit_based_2}"));
56 /// assert_eq!("10000", format!("{bit_based_10}"));
57 ///
58 /// // with an exact unit
59 /// assert_eq!("10 Kib", format!("{bit_based_2:#}"));
60 /// assert_eq!("10 Kb", format!("{bit_based_10:#}"));
61 ///
62 /// // with an exact unit, no spaces between the value and the unit
63 /// assert_eq!("10Kib", format!("{bit_based_2:-#}"));
64 /// assert_eq!("10Kb", format!("{bit_based_10:-#}"));
65 ///
66 /// // with a width, left alignment
67 /// assert_eq!("10 Kib", format!("{bit_based_2:#10}"));
68 /// assert_eq!("10 Kb", format!("{bit_based_10:#10}"));
69 ///
70 /// // with a width, right alignment
71 /// assert_eq!(" 10 Kib", format!("{bit_based_2:>#10}"));
72 /// assert_eq!(" 10 Kb", format!("{bit_based_10:>#10}"));
73 ///
74 /// // with a width, right alignment, more spaces between the value and the unit
75 /// assert_eq!(" 10 Kib", format!("{bit_based_2:>+#10}"));
76 /// assert_eq!(" 10 Kb", format!("{bit_based_10:>+#10}"));
77 /// ```
78 ///
79 /// ```
80 /// use byte_unit::{Bit, UnitType};
81 ///
82 /// let bit = Bit::from_u64(3211776);
83 ///
84 /// assert_eq!("3211776", format!("{bit}"));
85 ///
86 /// // with a unit, still precisely
87 /// assert_eq!("3136.5 Kib", format!("{bit:#}"));
88 ///
89 /// // with a unit and a larger precision (default is 3), still precisely
90 /// assert_eq!("3.211776 Mb", format!("{bit:#.6}"));
91 ///
92 /// // with a unit and a smaller precision (default is 3), still precisely
93 /// assert_eq!("3211776 b", format!("{bit:#.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 `Bit` instances.
144impl Bit {
145 /// Create a new `Bit` instance from a size in bits.
146 ///
147 /// # Examples
148 ///
149 /// ```
150 /// # use byte_unit::Bit;
151 /// let bit = Bit::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 < RONNABIT {
162 Some(Bit(size))
163 } else {
164 None
165 }
166 }
167
168 #[cfg(not(feature = "u128"))]
169 {
170 if size <= u64::MAX as u128 {
171 Some(Bit(size as u64))
172 } else {
173 None
174 }
175 }
176 }
177
178 /// Create a new `Bit` instance from a size in bits.
179 ///
180 /// # Examples
181 ///
182 /// ```
183 /// # use byte_unit::Bit;
184 /// let bit = unsafe { Bit::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 Bit(size)
194 }
195
196 #[cfg(not(feature = "u128"))]
197 {
198 Bit(size as u64)
199 }
200 }
201
202 /// Create a new `Bit` instance from a size in bits.
203 ///
204 /// # Examples
205 ///
206 /// ```
207 /// # use byte_unit::Bit;
208 /// let bit = Bit::from_u64(15000000); // 15 Mb
209 /// ```
210 #[inline]
211 pub const fn from_u64(size: u64) -> Self {
212 #[cfg(feature = "u128")]
213 {
214 Bit(size as u128)
215 }
216
217 #[cfg(not(feature = "u128"))]
218 {
219 Bit(size)
220 }
221 }
222
223 /// Create a new `Bit` instance from a size in bits.
224 ///
225 /// # Examples
226 ///
227 /// ```
228 /// # use byte_unit::Bit;
229 /// let bit = Bit::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 < RONNABIT {
244 Some(Bit(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(Bit(size))
256 } else {
257 None
258 }
259 }
260 } else {
261 None
262 }
263 }
264
265 /// Create a new `Bit` instance from a size in bits.
266 ///
267 /// # Examples
268 ///
269 /// ```
270 /// # use byte_unit::Bit;
271 /// let bit = Bit::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 < RONNABIT {
286 Some(Bit(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(Bit(size))
298 } else {
299 None
300 }
301 }
302 } else {
303 None
304 }
305 }
306
307 /// Create a new `Bit` instance from a size in bits.
308 ///
309 /// # Examples
310 ///
311 /// ```
312 /// # use byte_unit::Bit;
313 /// let bit = Bit::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 `Bit` instance from a size in bits.
329 ///
330 /// # Examples
331 ///
332 /// ```
333 /// # use byte_unit::Bit;
334 /// let bit = Bit::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 `Bit` instances (with `Unit`).
351impl Bit {
352 /// Create a new `Bit` instance from a size of bits with a unit.
353 ///
354 /// # Examples
355 ///
356 /// ```
357 /// use byte_unit::{Bit, Unit};
358 ///
359 /// let bit = Bit::from_u128_with_unit(15, Unit::Mbit).unwrap(); // 15 Mb
360 /// ```
361 ///
362 /// # Points to Note
363 ///
364 /// * If the calculated bit is too large, this function will return `None`.
365 #[inline]
366 pub const fn from_u128_with_unit(size: u128, unit: Unit) -> Option<Self> {
367 let v = {
368 match unit {
369 Unit::Bit => size,
370 _ => match size.checked_mul(unit.as_bits_u128()) {
371 Some(v) => v,
372 None => return None,
373 },
374 }
375 };
376
377 Self::from_u128(v)
378 }
379
380 /// Create a new `Bit` instance from a size of bits with a unit.
381 ///
382 /// # Examples
383 ///
384 /// ```
385 /// use byte_unit::{Bit, Unit};
386 ///
387 /// let bit = Bit::from_u64_with_unit(15, Unit::Mbit).unwrap(); // 15 Mb
388 /// ```
389 ///
390 /// # Points to Note
391 ///
392 /// * If the calculated bit is too large, this function will return `None`.
393 /// * If the input **unit** is `Bit`, the calculated bit will be rounded up.
394 #[inline]
395 pub const fn from_u64_with_unit(size: u64, unit: Unit) -> Option<Self> {
396 #[cfg(feature = "u128")]
397 {
398 Self::from_u128_with_unit(size as u128, unit)
399 }
400
401 #[cfg(not(feature = "u128"))]
402 {
403 let v = {
404 match unit {
405 Unit::Bit => size,
406 _ => match size.checked_mul(unit.as_bits_u64()) {
407 Some(v) => v,
408 None => return None,
409 },
410 }
411 };
412
413 Some(Self::from_u64(v))
414 }
415 }
416
417 /// Create a new `Bit` instance from a size of bits with a unit.
418 ///
419 /// # Examples
420 ///
421 /// ```
422 /// use byte_unit::{Bit, Unit};
423 ///
424 /// let bit = Bit::from_f64_with_unit(15.0, Unit::Mbit).unwrap(); // 15 Mb
425 /// ```
426 ///
427 /// # Points to Note
428 ///
429 /// * If the calculated bit is too large or not greater than or equal to **0**, this function will return `None`.
430 /// * The calculated bit will be rounded up.
431 #[inline]
432 pub fn from_f64_with_unit(size: f64, unit: Unit) -> Option<Self> {
433 match Decimal::from_f64(size) {
434 Some(size) => Self::from_decimal_with_unit(size, unit),
435 None => None,
436 }
437 }
438
439 /// Create a new `Bit` instance from a size of bits with a unit.
440 ///
441 /// # Examples
442 ///
443 /// ```
444 /// use byte_unit::{Bit, Unit};
445 ///
446 /// let bit = Bit::from_f32_with_unit(15.0, Unit::Mbit).unwrap(); // 15 Mb
447 /// ```
448 ///
449 /// # Points to Note
450 ///
451 /// * If the calculated bit is too large or not greater than or equal to **0**, this function will return `None`.
452 /// * The calculated bit will be rounded up.
453 #[inline]
454 pub fn from_f32_with_unit(size: f32, unit: Unit) -> Option<Self> {
455 match Decimal::from_f32(size) {
456 Some(size) => Self::from_decimal_with_unit(size, unit),
457 None => None,
458 }
459 }
460
461 /// Create a new `Bit` instance from a size of bits with a unit.
462 ///
463 /// # Examples
464 ///
465 /// ```
466 /// use byte_unit::{Bit, Unit};
467 ///
468 /// let bit = Bit::from_i128_with_unit(15, Unit::Mibit).unwrap(); // 15 Mb
469 /// ```
470 ///
471 /// # Points to Note
472 ///
473 /// * If the calculated bit is too large or negative, this function will return `None`.
474 #[inline]
475 pub const fn from_i128_with_unit(size: i128, unit: Unit) -> Option<Self> {
476 if size >= 0 {
477 Self::from_u128_with_unit(size as u128, unit)
478 } else {
479 None
480 }
481 }
482
483 /// Create a new `Bit` instance from a size of bits with a unit.
484 ///
485 /// # Examples
486 ///
487 /// ```
488 /// use byte_unit::{Bit, Unit};
489 ///
490 /// let bit = Bit::from_i64_with_unit(15, Unit::Mbit).unwrap(); // 15 Mb
491 /// ```
492 ///
493 /// # Points to Note
494 ///
495 /// * If the calculated bit is too large or negative, this function will return `None`.
496 #[inline]
497 pub const fn from_i64_with_unit(size: i64, unit: Unit) -> Option<Self> {
498 if size >= 0 {
499 Self::from_u64_with_unit(size as u64, unit)
500 } else {
501 None
502 }
503 }
504}
505
506/// Methods for converting a `Bit` instance into a primitive integer.
507impl Bit {
508 /// Retrieve the bit represented by this `Bit` instance.
509 ///
510 /// # Examples
511 ///
512 /// ```
513 /// use byte_unit::Bit;
514 ///
515 /// let bit = Bit::parse_str("123KiB").unwrap();
516 ///
517 /// let result = bit.as_u128();
518 ///
519 /// assert_eq!(1007616, result);
520 /// ```
521 ///
522 /// ```
523 /// use byte_unit::Bit;
524 ///
525 /// let bit = Bit::parse_str("123Kib").unwrap();
526 ///
527 /// let result = bit.as_u128();
528 ///
529 /// assert_eq!(125952, result);
530 /// ```
531 #[inline]
532 pub const fn as_u128(self) -> u128 {
533 #[cfg(feature = "u128")]
534 {
535 self.0
536 }
537
538 #[cfg(not(feature = "u128"))]
539 {
540 self.0 as u128
541 }
542 }
543
544 /// Retrieve the bit represented by this `Bit` instance. When the `u128` feature is enabled, if the bit is actually greater than **2<sup>64</sup> - 1**, it will return **2<sup>64</sup> - 1**.
545 ///
546 /// # Examples
547 ///
548 /// ```
549 /// use byte_unit::Bit;
550 ///
551 /// let bit = Bit::parse_str("1kb").unwrap();
552 ///
553 /// let result = bit.as_u64();
554 ///
555 /// assert_eq!(1000, result);
556 /// ```
557 ///
558 /// ```
559 /// # #[cfg(feature = "u128")]
560 /// # {
561 /// use byte_unit::Bit;
562 ///
563 /// let bit = Bit::parse_str("1zb").unwrap();
564 ///
565 /// let result = bit.as_u64();
566 ///
567 /// assert_eq!(u64::MAX, result);
568 /// # }
569 /// ```
570 #[inline]
571 pub const fn as_u64(self) -> u64 {
572 #[cfg(feature = "u128")]
573 {
574 if self.0 <= u64::MAX as u128 {
575 self.0 as u64
576 } else {
577 u64::MAX
578 }
579 }
580
581 #[cfg(not(feature = "u128"))]
582 {
583 self.0
584 }
585 }
586
587 /// Retrieve the bit represented by this `Bit` instance.
588 ///
589 /// # Examples
590 ///
591 /// ```
592 /// use byte_unit::Bit;
593 ///
594 /// let bit = Bit::parse_str("1k").unwrap();
595 ///
596 /// let result = bit.as_u64_checked();
597 ///
598 /// assert_eq!(Some(1000), result);
599 /// ```
600 ///
601 /// ```
602 /// # #[cfg(feature = "u128")]
603 /// # {
604 /// use byte_unit::Bit;
605 ///
606 /// let bit = Bit::parse_str("1zb").unwrap();
607 ///
608 /// let result = bit.as_u64_checked();
609 ///
610 /// assert_eq!(None, result);
611 /// # }
612 /// ```
613 #[inline]
614 pub const fn as_u64_checked(self) -> Option<u64> {
615 #[cfg(feature = "u128")]
616 {
617 if self.0 <= u64::MAX as u128 {
618 Some(self.0 as u64)
619 } else {
620 None
621 }
622 }
623
624 #[cfg(not(feature = "u128"))]
625 {
626 Some(self.0)
627 }
628 }
629}
630
631/// Methods for calculation.
632impl Bit {
633 /// Add another `Bit` instance.
634 ///
635 /// # Examples
636 ///
637 /// ```
638 /// use byte_unit::Bit;
639 ///
640 /// let bit_1 = Bit::from_u64(1024);
641 /// let bit_2 = Bit::from_u64(512);
642 ///
643 /// let bit = bit_1.add(bit_2).unwrap();
644 ///
645 /// assert_eq!(1536, bit.as_u64());
646 /// ```
647 ///
648 /// # Points to Note
649 ///
650 /// * If the calculated bit is too large, this function will return `None`.
651 #[inline]
652 pub const fn add(self, rhs: Bit) -> Option<Bit> {
653 match self.0.checked_add(rhs.0) {
654 Some(v) => Some(Bit(v)),
655 None => None,
656 }
657 }
658
659 /// Subtract another `Bit` instance.
660 ///
661 /// # Examples
662 ///
663 /// ```
664 /// use byte_unit::Bit;
665 ///
666 /// let bit_1 = Bit::from_u64(1024);
667 /// let bit_2 = Bit::from_u64(512);
668 ///
669 /// let bit = bit_1.subtract(bit_2).unwrap();
670 ///
671 /// assert_eq!(512, bit.as_u64());
672 /// ```
673 ///
674 /// # Points to Note
675 ///
676 /// * If the right-hand side is bigger then this `Bit` instance, this function will return `None`.
677 #[inline]
678 pub const fn subtract(self, rhs: Bit) -> Option<Bit> {
679 match self.0.checked_sub(rhs.0) {
680 Some(v) => Some(Bit(v)),
681 None => None,
682 }
683 }
684
685 /// Multiplied by an unsigned integer.
686 ///
687 /// # Examples
688 ///
689 /// ```
690 /// use byte_unit::Bit;
691 ///
692 /// let count = 100;
693 /// let bit = Bit::from_u64(1024);
694 ///
695 /// let total_bit = bit.multiply(100).unwrap();
696 ///
697 /// assert_eq!(102400, total_bit.as_u64());
698 /// ```
699 ///
700 /// # Points to Note
701 ///
702 /// * If the calculated bit is too large, this function will return `None`.
703 #[allow(unexpected_cfgs)]
704 #[inline]
705 pub const fn multiply(self, rhs: usize) -> Option<Bit> {
706 #[cfg(feature = "u128")]
707 {
708 match self.0.checked_mul(rhs as u128) {
709 Some(v) => Some(Bit(v)),
710 None => None,
711 }
712 }
713
714 #[cfg(not(feature = "u128"))]
715 {
716 #[cfg(target_pointer_width = "128")]
717 {
718 if rhs > u64::MAX as usize {
719 return None;
720 }
721 }
722
723 match self.0.checked_mul(rhs as u64) {
724 Some(v) => Some(Bit(v)),
725 None => None,
726 }
727 }
728 }
729
730 /// Divided by an unsigned integer.
731 ///
732 /// # Examples
733 ///
734 /// ```
735 /// use byte_unit::Bit;
736 ///
737 /// let count = 100;
738 /// let bit = Bit::from_u64(1024);
739 ///
740 /// let total_bit = bit.divide(100).unwrap();
741 ///
742 /// assert_eq!(10, total_bit.as_u64());
743 /// ```
744 ///
745 /// # Points to Note
746 ///
747 /// * If the input right-hand side is zero, this function will return `None`.
748 /// * The result will be rounded down.
749 #[allow(unexpected_cfgs)]
750 #[inline]
751 pub const fn divide(self, rhs: usize) -> Option<Bit> {
752 #[cfg(feature = "u128")]
753 {
754 match self.0.checked_div(rhs as u128) {
755 Some(v) => Some(Bit(v)),
756 None => None,
757 }
758 }
759
760 #[cfg(not(feature = "u128"))]
761 {
762 #[cfg(target_pointer_width = "128")]
763 {
764 if rhs > u64::MAX as usize {
765 return None;
766 }
767 }
768
769 match self.0.checked_div(rhs as u64) {
770 Some(v) => Some(Bit(v)),
771 None => None,
772 }
773 }
774 }
775
776 #[inline]
777 pub(crate) const fn mul_8(self) -> Bit {
778 Bit(self.0 * 8)
779 }
780}
781
782/// Methods for finding an unit.
783impl Bit {
784 /// Obtain the largest unit which is the greatest factor of this `Bit` instance.
785 ///
786 /// # Examples
787 ///
788 /// ```
789 /// use byte_unit::{Bit, Unit};
790 ///
791 /// let bit = Bit::from_u64(3145728);
792 ///
793 /// let (n, unit) = bit.get_exact_unit(true);
794 ///
795 /// assert_eq!(3, n);
796 /// assert_eq!(Unit::Mibit, unit);
797 /// ```
798 ///
799 /// ```
800 /// use byte_unit::{Bit, Unit};
801 ///
802 /// let bit = Bit::from_u64(24000000);
803 ///
804 /// let (n, unit) = bit.get_exact_unit(true);
805 ///
806 /// assert_eq!(3, n);
807 /// assert_eq!(Unit::MB, unit);
808 /// ```
809 ///
810 /// ```
811 /// use byte_unit::{Bit, Unit};
812 ///
813 /// let bit = Bit::from_u64(24000000);
814 ///
815 /// let (n, unit) = bit.get_exact_unit(false);
816 ///
817 /// assert_eq!(24, n);
818 /// assert_eq!(Unit::Mbit, unit);
819 /// ```
820 #[inline]
821 pub const fn get_exact_unit(self, allow_in_bytes: bool) -> (u128, Unit) {
822 let bits_v = self.as_u128();
823
824 let a = if allow_in_bytes { Unit::get_multiples() } else { Unit::get_multiples_bits() };
825 let mut i = a.len() - 1;
826
827 loop {
828 let unit = a[i];
829
830 let unit_v = unit.as_bits_u128();
831
832 if bits_v >= unit_v && bits_v % unit_v == 0 {
833 return (bits_v / unit_v, unit);
834 }
835
836 if i == 0 {
837 break;
838 }
839
840 i -= 1;
841 }
842
843 (bits_v, Unit::Bit)
844 }
845}