use rust_decimal::prelude::*;
use super::Bit;
use crate::{common::is_zero_remainder_decimal, Unit};
impl Bit {
#[inline]
pub fn from_decimal(size: Decimal) -> Option<Self> {
if size >= Decimal::ZERO {
#[cfg(feature = "u128")]
{
let size = size.ceil();
match size.to_u128() {
Some(n) => Self::from_u128(n),
None => None,
}
}
#[cfg(not(feature = "u128"))]
{
let size = size.ceil();
size.to_u64().map(Self::from_u64)
}
} else {
None
}
}
}
impl Bit {
#[inline]
pub fn from_decimal_with_unit(size: Decimal, unit: Unit) -> Option<Self> {
let v = {
match unit {
Unit::Bit => size,
_ => size.checked_mul(Decimal::from(unit.as_bits_u128()))?,
}
};
Self::from_decimal(v)
}
}
impl Bit {
#[inline]
pub fn get_recoverable_unit(
self,
allow_in_bytes: bool,
mut precision: usize,
) -> (Decimal, Unit) {
let bits_v = self.as_u128();
let bits_vd = Decimal::from(bits_v);
let a = if allow_in_bytes { Unit::get_multiples() } else { Unit::get_multiples_bits() };
let mut i = a.len() - 1;
if precision >= 28 {
precision = 28;
}
loop {
let unit = a[i];
let unit_v = unit.as_bits_u128();
if bits_v >= unit_v {
let unit_vd = Decimal::from(unit_v);
if let Some(quotient) = is_zero_remainder_decimal(bits_vd, unit_vd, precision) {
return (quotient, unit);
}
}
if i == 0 {
break;
}
i -= 1;
}
(bits_vd, Unit::Bit)
}
}