macro_rules! decl_decimal_dyn_impl {
(
$Type:ident,
$Storage:ty,
$width_variant:ident,
$raw_variant:ident,
$max_scale:literal,
scales = [$($scale:literal)+]
) => {
impl<const SCALE: u32> $crate::types::traits::dyn_decimal::DynDecimal for $crate::$Type<SCALE> {
fn width(&self) -> $crate::types::traits::dyn_decimal::DecimalWidth {
$crate::types::traits::dyn_decimal::DecimalWidth::$width_variant
}
fn scale_dyn(&self) -> u32 { SCALE }
fn max_scale(&self) -> u32 { $max_scale }
fn raw_storage(&self) -> $crate::types::traits::dyn_decimal::RawStorage {
$crate::types::traits::dyn_decimal::RawStorage::$raw_variant(self.0)
}
fn as_any(&self) -> &dyn ::core::any::Any { self }
fn clone_box(&self) -> ::alloc::boxed::Box<dyn $crate::types::traits::dyn_decimal::DynDecimal> {
::alloc::boxed::Box::new(*self)
}
fn is_zero(&self) -> bool {
*self == <Self as $crate::DecimalArithmetic>::ZERO
}
fn is_one(&self) -> bool {
*self == <Self as $crate::DecimalArithmetic>::ONE
}
fn is_positive(&self) -> bool {
<Self as $crate::DecimalArithmetic>::is_positive(*self)
}
fn is_negative(&self) -> bool {
<Self as $crate::DecimalArithmetic>::is_negative(*self)
}
fn signum(&self) -> ::alloc::boxed::Box<dyn $crate::types::traits::dyn_decimal::DynDecimal> {
::alloc::boxed::Box::new(<Self as $crate::DecimalArithmetic>::signum(*self))
}
fn abs(&self) -> ::alloc::boxed::Box<dyn $crate::types::traits::dyn_decimal::DynDecimal> {
::alloc::boxed::Box::new(<Self as $crate::DecimalArithmetic>::abs(*self))
}
fn neg(&self) -> ::alloc::boxed::Box<dyn $crate::types::traits::dyn_decimal::DynDecimal> {
::alloc::boxed::Box::new(-*self)
}
fn add(
&self,
rhs: &dyn $crate::types::traits::dyn_decimal::DynDecimal,
) -> Option<::alloc::boxed::Box<dyn $crate::types::traits::dyn_decimal::DynDecimal>> {
if rhs.width() != $crate::types::traits::dyn_decimal::DecimalWidth::$width_variant {
return None;
}
let target_scale = SCALE.max(rhs.scale_dyn());
let lhs_box = $crate::types::traits::dyn_decimal::DynDecimal::rescale_to(self, target_scale)?;
let rhs_box = rhs.rescale_to(target_scale)?;
match target_scale {
$(
$scale => {
let l = *lhs_box.as_any()
.downcast_ref::<$crate::$Type<$scale>>()?;
let r = *rhs_box.as_any()
.downcast_ref::<$crate::$Type<$scale>>()?;
<$crate::$Type<$scale> as $crate::DecimalArithmetic>::checked_add(l, r)
.map(|res| ::alloc::boxed::Box::new(res)
as ::alloc::boxed::Box<dyn $crate::types::traits::dyn_decimal::DynDecimal>)
}
)+
_ => None,
}
}
fn sub(
&self,
rhs: &dyn $crate::types::traits::dyn_decimal::DynDecimal,
) -> Option<::alloc::boxed::Box<dyn $crate::types::traits::dyn_decimal::DynDecimal>> {
if rhs.width() != $crate::types::traits::dyn_decimal::DecimalWidth::$width_variant {
return None;
}
let target_scale = SCALE.max(rhs.scale_dyn());
let lhs_box = $crate::types::traits::dyn_decimal::DynDecimal::rescale_to(self, target_scale)?;
let rhs_box = rhs.rescale_to(target_scale)?;
match target_scale {
$(
$scale => {
let l = *lhs_box.as_any()
.downcast_ref::<$crate::$Type<$scale>>()?;
let r = *rhs_box.as_any()
.downcast_ref::<$crate::$Type<$scale>>()?;
<$crate::$Type<$scale> as $crate::DecimalArithmetic>::checked_sub(l, r)
.map(|res| ::alloc::boxed::Box::new(res)
as ::alloc::boxed::Box<dyn $crate::types::traits::dyn_decimal::DynDecimal>)
}
)+
_ => None,
}
}
fn mul(
&self,
rhs: &dyn $crate::types::traits::dyn_decimal::DynDecimal,
) -> Option<::alloc::boxed::Box<dyn $crate::types::traits::dyn_decimal::DynDecimal>> {
if rhs.width() != $crate::types::traits::dyn_decimal::DecimalWidth::$width_variant {
return None;
}
let target_scale = SCALE.max(rhs.scale_dyn());
let lhs_box = $crate::types::traits::dyn_decimal::DynDecimal::rescale_to(self, target_scale)?;
let rhs_box = rhs.rescale_to(target_scale)?;
match target_scale {
$(
$scale => {
let l = *lhs_box.as_any()
.downcast_ref::<$crate::$Type<$scale>>()?;
let r = *rhs_box.as_any()
.downcast_ref::<$crate::$Type<$scale>>()?;
<$crate::$Type<$scale> as $crate::DecimalArithmetic>::checked_mul(l, r)
.map(|res| ::alloc::boxed::Box::new(res)
as ::alloc::boxed::Box<dyn $crate::types::traits::dyn_decimal::DynDecimal>)
}
)+
_ => None,
}
}
fn div(
&self,
rhs: &dyn $crate::types::traits::dyn_decimal::DynDecimal,
) -> Option<::alloc::boxed::Box<dyn $crate::types::traits::dyn_decimal::DynDecimal>> {
if rhs.width() != $crate::types::traits::dyn_decimal::DecimalWidth::$width_variant {
return None;
}
let target_scale = SCALE.max(rhs.scale_dyn());
let lhs_box = $crate::types::traits::dyn_decimal::DynDecimal::rescale_to(self, target_scale)?;
let rhs_box = rhs.rescale_to(target_scale)?;
match target_scale {
$(
$scale => {
let l = *lhs_box.as_any()
.downcast_ref::<$crate::$Type<$scale>>()?;
let r = *rhs_box.as_any()
.downcast_ref::<$crate::$Type<$scale>>()?;
<$crate::$Type<$scale> as $crate::DecimalArithmetic>::checked_div(l, r)
.map(|res| ::alloc::boxed::Box::new(res)
as ::alloc::boxed::Box<dyn $crate::types::traits::dyn_decimal::DynDecimal>)
}
)+
_ => None,
}
}
fn rem(
&self,
rhs: &dyn $crate::types::traits::dyn_decimal::DynDecimal,
) -> Option<::alloc::boxed::Box<dyn $crate::types::traits::dyn_decimal::DynDecimal>> {
if rhs.width() != $crate::types::traits::dyn_decimal::DecimalWidth::$width_variant {
return None;
}
let target_scale = SCALE.max(rhs.scale_dyn());
let lhs_box = $crate::types::traits::dyn_decimal::DynDecimal::rescale_to(self, target_scale)?;
let rhs_box = rhs.rescale_to(target_scale)?;
match target_scale {
$(
$scale => {
let l = *lhs_box.as_any()
.downcast_ref::<$crate::$Type<$scale>>()?;
let r = *rhs_box.as_any()
.downcast_ref::<$crate::$Type<$scale>>()?;
<$crate::$Type<$scale> as $crate::DecimalArithmetic>::checked_rem(l, r)
.map(|res| ::alloc::boxed::Box::new(res)
as ::alloc::boxed::Box<dyn $crate::types::traits::dyn_decimal::DynDecimal>)
}
)+
_ => None,
}
}
fn rescale_to(
&self,
target_scale: u32,
) -> Option<::alloc::boxed::Box<dyn $crate::types::traits::dyn_decimal::DynDecimal>> {
$crate::types::traits::dyn_decimal::DynDecimal::rescale_to_with(
self,
target_scale,
$crate::support::rounding::DEFAULT_ROUNDING_MODE,
)
}
fn rescale_to_with(
&self,
target_scale: u32,
mode: $crate::support::rounding::RoundingMode,
) -> Option<::alloc::boxed::Box<dyn $crate::types::traits::dyn_decimal::DynDecimal>> {
if target_scale > SCALE && target_scale <= $max_scale {
let shift = target_scale - SCALE;
let multiplier = (10 as $Storage).pow(shift);
self.0.checked_mul(multiplier)?;
}
match target_scale {
$(
$scale => Some(::alloc::boxed::Box::new(self.rescale_with::<$scale>(mode))
as ::alloc::boxed::Box<dyn $crate::types::traits::dyn_decimal::DynDecimal>),
)+
_ => None,
}
}
fn eq_dyn(&self, rhs: &dyn $crate::types::traits::dyn_decimal::DynDecimal) -> bool {
if rhs.width() != $crate::types::traits::dyn_decimal::DecimalWidth::$width_variant {
return false;
}
let target_scale = SCALE.max(rhs.scale_dyn());
let lhs_box = match $crate::types::traits::dyn_decimal::DynDecimal::rescale_to(self, target_scale) {
Some(b) => b,
None => return false,
};
let rhs_box = match rhs.rescale_to(target_scale) {
Some(b) => b,
None => return false,
};
match target_scale {
$(
$scale => {
let l = match lhs_box.as_any()
.downcast_ref::<$crate::$Type<$scale>>() {
Some(v) => *v,
None => return false,
};
let r = match rhs_box.as_any()
.downcast_ref::<$crate::$Type<$scale>>() {
Some(v) => *v,
None => return false,
};
l == r
}
)+
_ => false,
}
}
fn cmp_dyn(
&self,
rhs: &dyn $crate::types::traits::dyn_decimal::DynDecimal,
) -> Option<::core::cmp::Ordering> {
if rhs.width() != $crate::types::traits::dyn_decimal::DecimalWidth::$width_variant {
return None;
}
let target_scale = SCALE.max(rhs.scale_dyn());
let lhs_box = $crate::types::traits::dyn_decimal::DynDecimal::rescale_to(self, target_scale)?;
let rhs_box = rhs.rescale_to(target_scale)?;
match target_scale {
$(
$scale => {
let l = *lhs_box.as_any()
.downcast_ref::<$crate::$Type<$scale>>()?;
let r = *rhs_box.as_any()
.downcast_ref::<$crate::$Type<$scale>>()?;
Some(l.cmp(&r))
}
)+
_ => None,
}
}
fn display(&self) -> ::alloc::string::String {
::alloc::format!("{}", self)
}
#[cfg(feature = "std")]
fn to_f64(&self) -> f64 {
<Self as $crate::DecimalConvert>::to_f64(*self)
}
fn to_int(&self) -> i64 {
<Self as $crate::DecimalConvert>::to_int(*self)
}
}
};
}
pub(crate) use decl_decimal_dyn_impl;