use crate::{
DecimalType, ParseDecimalError,
primitive::{Byte, Decimal, Int, Integer, Long, Short},
};
use strum_macros::Display;
#[cfg(feature = "alloc")]
use ::alloc::format;
#[derive(Clone, Debug, Display, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[cfg_attr(
feature = "borsh",
derive(borsh::BorshSerialize, borsh::BorshDeserialize)
)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub enum DecimalValue {
#[cfg_attr(feature = "alloc", strum(to_string = "{0}"))]
Decimal(Decimal),
#[cfg_attr(feature = "alloc", strum(to_string = "{0}"))]
Integer(Integer),
#[cfg_attr(feature = "alloc", strum(to_string = "{0}"))]
Long(Long),
#[cfg_attr(feature = "alloc", strum(to_string = "{0}"))]
Int(Int),
#[cfg_attr(feature = "alloc", strum(to_string = "{0}"))]
Short(Short),
#[cfg_attr(feature = "alloc", strum(to_string = "{0}"))]
Byte(Byte),
}
impl DecimalValue {
pub fn as_f64(&self) -> f64 {
use DecimalValue::*;
match self {
Decimal(d) => return d.as_f64(),
Integer(n) => *n as _,
Long(n) => *n as _,
Int(n) => *n as _,
Short(n) => *n as _,
Byte(n) => *n as _,
}
}
pub fn to_f64(&self) -> Option<f64> {
Some(self.as_f64())
}
pub fn r#type(&self) -> DecimalType {
use DecimalValue::*;
match self {
Decimal(_) => DecimalType::Decimal,
Integer(_) => DecimalType::Integer,
Long(_) => DecimalType::Long,
Int(_) => DecimalType::Int,
Short(_) => DecimalType::Short,
Byte(_) => DecimalType::Byte,
}
}
pub fn widen(&self) -> Option<Self> {
use DecimalValue::*;
match self {
Decimal(_) => None, Integer(n) => (*n).try_into().ok(),
Long(n) => Some(Integer(*n as _)),
Int(n) => Some(Long(*n as _)),
Short(n) => Some(Int(*n as _)),
Byte(n) => Some(Short(*n as _)),
}
}
pub fn narrow(&self) -> Option<Self> {
use DecimalValue::*;
match self {
Decimal(d) if !d.is_integer() => None,
Decimal(d) => i128::try_from(d).ok().map(Integer),
Integer(n) => i64::try_from(*n).ok().map(Long),
Long(n) => i32::try_from(*n).ok().map(Int),
Int(n) => i16::try_from(*n).ok().map(Short),
Short(n) => i8::try_from(*n).ok().map(Byte),
Byte(_) => None, }
}
#[cfg(feature = "serde")]
pub fn to_json(&self) -> Option<serde_json::Value> {
Some(self.clone().into_json())
}
#[cfg(feature = "serde")]
pub fn into_json(self) -> serde_json::Value {
use DecimalValue::*;
match self {
Decimal(d) => d.as_f64().into(), Integer(n) => (n as f64).into(), Long(n) => n.into(),
Int(n) => n.into(),
Short(n) => n.into(),
Byte(n) => n.into(),
}
}
}
impl From<i8> for DecimalValue {
fn from(input: i8) -> Self {
Self::Byte(input.into())
}
}
impl From<i16> for DecimalValue {
fn from(input: i16) -> Self {
Self::Short(input.into())
}
}
impl From<i32> for DecimalValue {
fn from(input: i32) -> Self {
Self::Int(input.into())
}
}
impl From<i64> for DecimalValue {
fn from(input: i64) -> Self {
Self::Long(input.into())
}
}
impl From<i128> for DecimalValue {
fn from(input: i128) -> Self {
Self::Integer(input.into())
}
}
impl From<isize> for DecimalValue {
fn from(input: isize) -> Self {
Self::Integer((input as i128).into()) }
}
impl From<Decimal> for DecimalValue {
fn from(input: Decimal) -> Self {
Self::Decimal(input)
}
}
impl From<&Decimal> for DecimalValue {
fn from(input: &Decimal) -> Self {
Self::Decimal(input.clone())
}
}
#[cfg(feature = "rust_decimal")]
impl From<rust_decimal::Decimal> for DecimalValue {
fn from(input: rust_decimal::Decimal) -> Self {
Self::Decimal(input.into())
}
}
#[cfg(feature = "rust_decimal")]
impl From<&rust_decimal::Decimal> for DecimalValue {
fn from(input: &rust_decimal::Decimal) -> Self {
Self::Decimal(input.clone().into())
}
}
impl TryFrom<f32> for DecimalValue {
type Error = ParseDecimalError;
fn try_from(input: f32) -> Result<Self, Self::Error> {
Ok(Self::Decimal(input.try_into()?))
}
}
impl TryFrom<f64> for DecimalValue {
type Error = ParseDecimalError;
fn try_from(input: f64) -> Result<Self, Self::Error> {
Ok(Self::Decimal(input.try_into()?))
}
}
#[cfg(feature = "serde")]
impl From<DecimalValue> for serde_json::Value {
fn from(input: DecimalValue) -> Self {
input.into_json()
}
}
#[cfg(feature = "serde")]
impl From<&DecimalValue> for serde_json::Value {
fn from(input: &DecimalValue) -> Self {
input.clone().into_json()
}
}