mod built_in_traits;
#[cfg(feature = "rocket")]
mod rocket_traits;
#[cfg(feature = "schemars")]
mod schemars_traits;
#[cfg(feature = "serde")]
mod serde_traits;
use core::{
cmp::Ordering,
fmt::{self, Alignment, Display, Formatter, Write},
};
use super::{Byte, Unit};
use crate::{common::round_fractional_part_f64, UnitType};
#[derive(Debug, Clone, Copy)]
pub struct AdjustedByte {
pub(crate) value: f64,
pub(crate) unit: Unit,
}
impl PartialEq for AdjustedByte {
#[inline]
fn eq(&self, other: &AdjustedByte) -> bool {
let s = self.get_byte();
let o = other.get_byte();
s.eq(&o)
}
}
impl Eq for AdjustedByte {}
impl PartialOrd for AdjustedByte {
#[inline]
fn partial_cmp(&self, other: &AdjustedByte) -> Option<Ordering> {
Some(self.cmp(other))
}
}
impl Ord for AdjustedByte {
#[inline]
fn cmp(&self, other: &AdjustedByte) -> Ordering {
let s = self.get_byte();
let o = other.get_byte();
s.cmp(&o)
}
}
impl Display for AdjustedByte {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
let Self {
value,
unit,
} = self;
let handle_basic_precision = |precision: usize, f: &mut Formatter<'_>| -> fmt::Result {
if f.alternate() {
let value = round_fractional_part_f64(*value, precision);
f.write_fmt(format_args!("{value}"))
} else if matches!(unit, Unit::Bit | Unit::B) {
f.write_fmt(format_args!("{value}"))
} else {
f.write_fmt(format_args!("{value:.precision$}"))
}
};
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 let Some(precision) = f.precision() {
if width > l + 1 {
width -= l;
let alignment = f.align().unwrap_or(Alignment::Left);
if f.alternate() {
let value = round_fractional_part_f64(*value, precision);
match alignment {
Alignment::Left | Alignment::Center => {
f.write_fmt(format_args!("{value:<width$}"))?
},
Alignment::Right => f.write_fmt(format_args!("{value:>width$}"))?,
}
} else {
match alignment {
Alignment::Left | Alignment::Center => {
f.write_fmt(format_args!("{value:<width$.precision$}"))?
},
Alignment::Right => {
f.write_fmt(format_args!("{value:>width$.precision$}"))?
},
}
}
} else {
handle_basic_precision(precision, f)?;
}
} else 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 if let Some(precision) = f.precision() {
handle_basic_precision(precision, f)?;
} else {
f.write_fmt(format_args!("{value}"))?;
}
for _ in 0..space_length {
f.write_char(' ')?;
}
f.write_fmt(format_args!("{unit}"))
}
}
impl AdjustedByte {
#[inline]
pub const fn get_value(&self) -> f64 {
self.value
}
#[inline]
pub const fn get_unit(&self) -> Unit {
self.unit
}
#[inline]
pub fn get_byte(&self) -> Byte {
Byte::from_f64_with_unit(self.value, self.unit).unwrap()
}
}
impl Byte {
#[inline]
pub fn get_adjusted_unit(self, unit: Unit) -> AdjustedByte {
let byte_v = self.as_u128();
let value = match unit {
Unit::Bit => (byte_v << 3) as f64,
Unit::B => byte_v as f64,
_ => byte_v as f64 / unit.as_bytes_u128() as f64,
};
AdjustedByte {
value,
unit,
}
}
pub fn get_appropriate_unit(&self, unit_type: UnitType) -> AdjustedByte {
let a = Unit::get_multiples_bytes();
let (skip, step) = match unit_type {
UnitType::Binary => (0, 2),
UnitType::Decimal => (1, 2),
UnitType::Both => (0, 1),
};
let bytes_v = self.as_u128();
for unit in a.iter().rev().skip(skip).step_by(step) {
if bytes_v >= unit.as_bytes_u128() {
return self.get_adjusted_unit(*unit);
}
}
self.get_adjusted_unit(Unit::B)
}
}