#[cfg(feature = "decimal128")]
use decimal::d128;
use std::fmt;
#[derive(Clone, PartialEq, PartialOrd)]
pub struct Decimal128 {
#[cfg(not(feature = "decimal128"))]
pub(crate) bytes: [u8; 128 / 8],
#[cfg(feature = "decimal128")]
inner: decimal::d128,
}
#[cfg(feature = "decimal128")]
impl Decimal128 {
#[allow(clippy::should_implement_trait)]
pub fn from_str(s: &str) -> Decimal128 {
Decimal128 {
inner: s.parse::<d128>().expect("Invalid Decimal128 string"),
}
}
pub fn from_i32(d: i32) -> Decimal128 {
Decimal128 {
inner: From::from(d),
}
}
pub fn from_u32(d: u32) -> Decimal128 {
Decimal128 {
inner: From::from(d),
}
}
#[allow(clippy::wrong_self_convention)]
#[deprecated(since = "0.15.0", note = "Replaced by `to_i32`")]
pub fn into_i32(&self) -> i32 {
Into::into(self.inner)
}
pub fn to_i32(&self) -> i32 {
Into::into(self.inner)
}
#[allow(clippy::wrong_self_convention)]
#[deprecated(since = "0.15.0", note = "Replaced by `to_u32`")]
pub fn into_u32(&self) -> u32 {
Into::into(self.inner)
}
pub fn to_u32(&self) -> u32 {
Into::into(self.inner)
}
pub fn zero() -> Decimal128 {
Decimal128 {
inner: d128::zero(),
}
}
#[doc(hidden)]
pub unsafe fn from_raw_bytes_le(mut raw: [u8; 16]) -> Decimal128 {
if cfg!(target_endian = "big") {
raw.reverse();
}
Decimal128 {
inner: d128::from_raw_bytes(raw),
}
}
#[doc(hidden)]
pub fn to_raw_bytes_le(&self) -> [u8; 16] {
let mut buf = self.inner.to_raw_bytes();
if cfg!(target_endian = "big") {
buf.reverse();
}
buf
}
pub fn is_nan(&self) -> bool {
self.inner.is_nan()
}
pub fn is_zero(&self) -> bool {
self.inner.is_zero()
}
}
impl fmt::Debug for Decimal128 {
#[cfg(feature = "decimal128")]
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "Decimal128(\"{:?}\")", self.inner)
}
#[cfg(not(feature = "decimal128"))]
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "Decimal128(...)")
}
}
impl fmt::Display for Decimal128 {
#[cfg(feature = "decimal128")]
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self.inner)
}
#[cfg(not(feature = "decimal128"))]
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{:?}", self)
}
}
#[cfg(feature = "decimal128")]
impl fmt::LowerHex for Decimal128 {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
<d128 as fmt::LowerHex>::fmt(&self.inner, f)
}
}
#[cfg(feature = "decimal128")]
impl fmt::LowerExp for Decimal128 {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
<d128 as fmt::LowerExp>::fmt(&self.inner, f)
}
}
#[cfg(feature = "decimal128")]
impl std::str::FromStr for Decimal128 {
type Err = ();
fn from_str(s: &str) -> Result<Decimal128, ()> {
Ok(Decimal128::from_str(s))
}
}
#[cfg(feature = "decimal128")]
impl Into<d128> for Decimal128 {
fn into(self) -> d128 {
self.inner
}
}
#[cfg(feature = "decimal128")]
impl From<d128> for Decimal128 {
fn from(d: d128) -> Decimal128 {
Decimal128 { inner: d }
}
}
#[cfg(feature = "decimal128")]
impl Default for Decimal128 {
fn default() -> Decimal128 {
Decimal128::zero()
}
}
#[cfg(test)]
#[cfg(feature = "decimal128")]
mod test {
use super::*;
#[test]
fn decimal128_string() {
assert!(Decimal128::from_str("0").is_zero());
assert!(!Decimal128::from_str("12").is_nan());
assert!(!Decimal128::from_str("-76").is_nan());
assert!(!Decimal128::from_str("12.70").is_nan());
assert!(!Decimal128::from_str("+0.003").is_nan());
assert!(!Decimal128::from_str("017.").is_nan());
assert!(!Decimal128::from_str(".5").is_nan());
assert!(!Decimal128::from_str("4E+9").is_nan());
assert!(!Decimal128::from_str("0.73e-7").is_nan());
assert!(!Decimal128::from_str("Inf").is_nan());
assert!(!Decimal128::from_str("-infinity").is_nan());
assert!(Decimal128::from_str("NaN").is_nan());
}
#[test]
fn decimal128_i32() {
let num: i32 = 89;
let dec128 = Decimal128::from_i32(num);
assert!(!dec128.is_nan());
assert!(!dec128.is_zero());
assert_eq!(dec128.to_i32(), num);
}
#[test]
fn decimal128_u32() {
let num: u32 = 89;
let dec128 = Decimal128::from_u32(num);
assert!(!dec128.is_nan());
assert!(!dec128.is_zero());
assert_eq!(dec128.to_u32(), num);
}
#[test]
fn decimal128_0() {
let dec128 = Decimal128::zero();
assert!(dec128.is_zero());
}
#[test]
fn decimal128_is_zero() {
let dec128 = Decimal128::from_i32(234);
assert!(!dec128.is_zero());
let dec128_0 = Decimal128::from_i32(0);
assert!(dec128_0.is_zero());
}
#[test]
fn decimal128_is_nan() {
let dec128 = Decimal128::from_str("NaN");
assert!(dec128.is_nan());
let dec128 = Decimal128::from_i32(234);
assert!(!dec128.is_nan());
}
}