mod adjusted;
mod built_in_traits;
mod constants;
mod decimal;
mod parse;
#[cfg(feature = "rocket")]
mod rocket_traits;
#[cfg(feature = "schemars")]
mod schemars_traits;
#[cfg(feature = "serde")]
mod serde_traits;
use core::fmt::{self, Alignment, Display, Formatter, Write};
pub use adjusted::*;
use rust_decimal::prelude::*;
use crate::{
common::{ceil_f32, ceil_f64},
Unit,
};
#[cfg(feature = "u128")]
const RONNABIT: u128 = 1_000_000_000_000_000_000_000_000_000;
#[cfg(feature = "u128")]
#[derive(Debug, Clone, Copy, PartialOrd, Ord, PartialEq, Eq, Hash, Default)]
pub struct Bit(u128);
#[cfg(not(feature = "u128"))]
#[derive(Debug, Clone, Copy, PartialOrd, Ord, PartialEq, Eq, Hash, Default)]
pub struct Bit(u64);
impl Display for Bit {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
if f.alternate() {
let precision = f.precision().unwrap_or(3);
let (mut value, unit) = self.get_recoverable_unit(false, precision);
value = value.normalize();
let space_length = if f.sign_plus() {
4 - unit.as_str().len()
} else if f.sign_minus() {
0
} else {
1
};
if let Some(mut width) = f.width() {
let l = unit.as_str().len() + space_length;
if width > l + 1 {
width -= l;
let alignment = f.align().unwrap_or(Alignment::Left);
match alignment {
Alignment::Left | Alignment::Center => {
f.write_fmt(format_args!("{value:<width$}"))?
},
Alignment::Right => f.write_fmt(format_args!("{value:>width$}"))?,
}
} else {
f.write_fmt(format_args!("{value}"))?;
}
} else {
f.write_fmt(format_args!("{value}"))?;
}
for _ in 0..space_length {
f.write_char(' ')?;
}
f.write_fmt(format_args!("{unit}"))
} else {
Display::fmt(&self.0, f)
}
}
}
impl Bit {
#[inline]
pub const fn from_u128(size: u128) -> Option<Self> {
#[cfg(feature = "u128")]
{
if size < RONNABIT {
Some(Bit(size))
} else {
None
}
}
#[cfg(not(feature = "u128"))]
{
if size <= u64::MAX as u128 {
Some(Bit(size as u64))
} else {
None
}
}
}
#[inline]
pub const unsafe fn from_u128_unsafe(size: u128) -> Self {
#[cfg(feature = "u128")]
{
Bit(size)
}
#[cfg(not(feature = "u128"))]
{
Bit(size as u64)
}
}
#[inline]
pub const fn from_u64(size: u64) -> Self {
#[cfg(feature = "u128")]
{
Bit(size as u128)
}
#[cfg(not(feature = "u128"))]
{
Bit(size)
}
}
#[inline]
pub fn from_f64(size: f64) -> Option<Self> {
if size >= 0.0 {
#[cfg(feature = "u128")]
{
let size = ceil_f64(size) as u128;
if size < RONNABIT {
Some(Bit(size))
} else {
None
}
}
#[cfg(not(feature = "u128"))]
{
let size = ceil_f64(size) as u64;
if size < u64::MAX {
Some(Bit(size))
} else {
None
}
}
} else {
None
}
}
#[inline]
pub fn from_f32(size: f32) -> Option<Self> {
if size >= 0.0 {
#[cfg(feature = "u128")]
{
let size = ceil_f32(size) as u128;
if size < RONNABIT {
Some(Bit(size))
} else {
None
}
}
#[cfg(not(feature = "u128"))]
{
let size = ceil_f32(size) as u64;
if size < u64::MAX {
Some(Bit(size))
} else {
None
}
}
} else {
None
}
}
#[inline]
pub const fn from_i128(size: i128) -> Option<Self> {
if size >= 0 {
Self::from_u128(size as u128)
} else {
None
}
}
#[inline]
pub const fn from_i64(size: i64) -> Option<Self> {
if size >= 0 {
Some(Self::from_u64(size as u64))
} else {
None
}
}
}
impl Bit {
#[inline]
pub const fn from_u128_with_unit(size: u128, unit: Unit) -> Option<Self> {
let v = {
match unit {
Unit::Bit => size,
_ => match size.checked_mul(unit.as_bits_u128()) {
Some(v) => v,
None => return None,
},
}
};
Self::from_u128(v)
}
#[inline]
pub const fn from_u64_with_unit(size: u64, unit: Unit) -> Option<Self> {
#[cfg(feature = "u128")]
{
Self::from_u128_with_unit(size as u128, unit)
}
#[cfg(not(feature = "u128"))]
{
let v = {
match unit {
Unit::Bit => size,
_ => match size.checked_mul(unit.as_bits_u64()) {
Some(v) => v,
None => return None,
},
}
};
Some(Self::from_u64(v))
}
}
#[inline]
pub fn from_f64_with_unit(size: f64, unit: Unit) -> Option<Self> {
match Decimal::from_f64(size) {
Some(size) => Self::from_decimal_with_unit(size, unit),
None => None,
}
}
#[inline]
pub fn from_f32_with_unit(size: f32, unit: Unit) -> Option<Self> {
match Decimal::from_f32(size) {
Some(size) => Self::from_decimal_with_unit(size, unit),
None => None,
}
}
#[inline]
pub const fn from_i128_with_unit(size: i128, unit: Unit) -> Option<Self> {
if size >= 0 {
Self::from_u128_with_unit(size as u128, unit)
} else {
None
}
}
#[inline]
pub const fn from_i64_with_unit(size: i64, unit: Unit) -> Option<Self> {
if size >= 0 {
Self::from_u64_with_unit(size as u64, unit)
} else {
None
}
}
}
impl Bit {
#[inline]
pub const fn as_u128(self) -> u128 {
#[cfg(feature = "u128")]
{
self.0
}
#[cfg(not(feature = "u128"))]
{
self.0 as u128
}
}
#[inline]
pub const fn as_u64(self) -> u64 {
#[cfg(feature = "u128")]
{
if self.0 <= u64::MAX as u128 {
self.0 as u64
} else {
u64::MAX
}
}
#[cfg(not(feature = "u128"))]
{
self.0
}
}
#[inline]
pub const fn as_u64_checked(self) -> Option<u64> {
#[cfg(feature = "u128")]
{
if self.0 <= u64::MAX as u128 {
Some(self.0 as u64)
} else {
None
}
}
#[cfg(not(feature = "u128"))]
{
Some(self.0)
}
}
}
impl Bit {
#[inline]
pub const fn add(self, rhs: Bit) -> Option<Bit> {
match self.0.checked_add(rhs.0) {
Some(v) => Some(Bit(v)),
None => None,
}
}
#[inline]
pub const fn subtract(self, rhs: Bit) -> Option<Bit> {
match self.0.checked_sub(rhs.0) {
Some(v) => Some(Bit(v)),
None => None,
}
}
#[allow(unexpected_cfgs)]
#[inline]
pub const fn multiply(self, rhs: usize) -> Option<Bit> {
#[cfg(feature = "u128")]
{
match self.0.checked_mul(rhs as u128) {
Some(v) => Some(Bit(v)),
None => None,
}
}
#[cfg(not(feature = "u128"))]
{
#[cfg(target_pointer_width = "128")]
{
if rhs > u64::MAX as usize {
return None;
}
}
match self.0.checked_mul(rhs as u64) {
Some(v) => Some(Bit(v)),
None => None,
}
}
}
#[allow(unexpected_cfgs)]
#[inline]
pub const fn divide(self, rhs: usize) -> Option<Bit> {
#[cfg(feature = "u128")]
{
match self.0.checked_div(rhs as u128) {
Some(v) => Some(Bit(v)),
None => None,
}
}
#[cfg(not(feature = "u128"))]
{
#[cfg(target_pointer_width = "128")]
{
if rhs > u64::MAX as usize {
return None;
}
}
match self.0.checked_div(rhs as u64) {
Some(v) => Some(Bit(v)),
None => None,
}
}
}
#[inline]
pub(crate) const fn mul_8(self) -> Bit {
Bit(self.0 * 8)
}
}
impl Bit {
#[inline]
pub const fn get_exact_unit(self, allow_in_bytes: bool) -> (u128, Unit) {
let bits_v = self.as_u128();
let a = if allow_in_bytes { Unit::get_multiples() } else { Unit::get_multiples_bits() };
let mut i = a.len() - 1;
loop {
let unit = a[i];
let unit_v = unit.as_bits_u128();
if bits_v >= unit_v && bits_v % unit_v == 0 {
return (bits_v / unit_v, unit);
}
if i == 0 {
break;
}
i -= 1;
}
(bits_v, Unit::Bit)
}
}