mod impls;
mod number_writer;
mod tests;
use {
core::{
convert::TryFrom,
fmt::{self, Display, Formatter},
},
crate::Error,
};
#[cfg(feature="std")]
pub(crate) use self::number_writer::*;
#[cfg(feature="std")]
#[cfg(any(
target_pointer_width = "8", target_pointer_width = "16", target_pointer_width = "32", target_pointer_width = "64",
target_pointer_width = "128",
))]
pub(crate) const MAX_INT_DIGITS: usize = 40;
#[cfg(feature="std")]
#[cfg(not(any(
target_pointer_width = "8", target_pointer_width = "16", target_pointer_width = "32", target_pointer_width = "64",
target_pointer_width = "128",
)))]
pub(crate) const MAX_INT_DIGITS: usize = core::mem::size_of::<usize>() * 3;
#[cfg(feature="std")]
#[test]
fn tests() {
use alloc::string::ToString;
assert!(MAX_INT_DIGITS >= u128::max_value().to_string().len());
assert!(MAX_INT_DIGITS >= i128::min_value().to_string().len());
assert!(MAX_INT_DIGITS >= usize::max_value().to_string().len());
assert!(MAX_INT_DIGITS >= isize::min_value().to_string().len());
}
#[derive(Debug, Clone)]
pub struct Number {
inner: Inner,
}
#[derive(Debug, Clone)]
enum Inner {
I32(i32), I64(i64), I128(i128), ISize(isize),
U32(u32), U64(u64), U128(u128), USize(usize),
F32(f32), F64(f64),
}
impl Display for Number {
fn fmt(&self, f: &mut Formatter) -> Result<(), fmt::Error> {
match self.inner {
Inner::I32(i) => i.fmt(f),
Inner::U32(u) => u.fmt(f),
Inner::I64(i) => i.fmt(f),
Inner::U64(u) => u.fmt(f),
Inner::I128(i) => i.fmt(f),
Inner::U128(u) => u.fmt(f),
Inner::ISize(i) => i.fmt(f),
Inner::USize(u) => u.fmt(f),
Inner::F32(x) => x.fmt(f),
Inner::F64(x) => x.fmt(f),
}
}
}
macro_rules! impl_from_small_ints_for_number { ($($ty: ty, $code: tt,)+) => {
$(
impl From<$ty> for Number {
fn from(n: $ty) -> Self {
Self {
inner: Inner::$code(n.into()),
}
}
}
)+
}}
impl_from_small_ints_for_number! {
i8, I32, i16, I32,
u8, U32, u16, U32,
}
macro_rules! impl_from_primitives_for_number { ($($ty: ty, $code: tt,)+) => {
$(
impl From<$ty> for Number {
fn from(n: $ty) -> Self {
Self {
inner: Inner::$code(n),
}
}
}
)+
}}
impl_from_primitives_for_number! {
i32, I32, i64, I64, i128, I128, isize, ISize,
u32, U32, u64, U64, u128, U128, usize, USize,
f32, F32, f64, F64,
}
macro_rules! impl_try_from_number_for_integers { ($($ty: ty,)+) => {
$(
impl TryFrom<&Number> for $ty {
type Error = Error;
fn try_from(n: &Number) -> Result<Self, Self::Error> {
match n.inner {
Inner::I32(i) => Self::try_from(i).map_err(|e| Error::from(__!("{}", e))),
Inner::I64(i) => Self::try_from(i).map_err(|e| Error::from(__!("{}", e))),
Inner::I128(i) => Self::try_from(i).map_err(|e| Error::from(__!("{}", e))),
Inner::ISize(i) => Self::try_from(i).map_err(|e| Error::from(__!("{}", e))),
Inner::U32(u) => Self::try_from(u).map_err(|e| Error::from(__!("{}", e))),
Inner::U64(u) => Self::try_from(u).map_err(|e| Error::from(__!("{}", e))),
Inner::U128(u) => Self::try_from(u).map_err(|e| Error::from(__!("{}", e))),
Inner::USize(u) => Self::try_from(u).map_err(|e| Error::from(__!("{}", e))),
_ => Err(Error::from(__!("Floating numbers are not supported"))),
}
}
}
impl TryFrom<Number> for $ty {
type Error = Error;
fn try_from(n: Number) -> Result<Self, Self::Error> {
Self::try_from(&n)
}
}
)+
}}
impl_try_from_number_for_integers! {
i8, i16, i32, i64, i128, isize,
u8, u16, u32, u64, u128, usize,
}
impl TryFrom<&Number> for f32 {
type Error = Error;
fn try_from(n: &Number) -> Result<Self, Self::Error> {
match n.inner {
Inner::F32(f) => Ok(f),
_ => Err(Error::from(__!("Not supported"))),
}
}
}
impl TryFrom<Number> for f32 {
type Error = Error;
fn try_from(n: Number) -> Result<Self, Self::Error> {
Self::try_from(&n)
}
}
impl TryFrom<&Number> for f64 {
type Error = Error;
fn try_from(n: &Number) -> Result<Self, Self::Error> {
match n.inner {
Inner::I32(i) => Ok(Self::from(i)),
Inner::U32(u) => Ok(Self::from(u)),
Inner::F32(f) => Ok(Self::from(f)),
Inner::F64(f) => Ok(f),
_ => Err(Error::from(__!("Not supported"))),
}
}
}
impl TryFrom<Number> for f64 {
type Error = Error;
fn try_from(n: Number) -> Result<Self, Self::Error> {
Self::try_from(&n)
}
}