macro_rules! impl_decimal_common {
($Ty:ident, $name:literal) => {
impl<const DIGITS: u8> core::str::FromStr for $Ty<DIGITS> {
type Err = crate::AmountErrorKind;
fn from_str(src: &str) -> Result<Self, Self::Err> {
Self::from_str_rounded(src, crate::Rounding::HalfUp)
}
}
impl<const DIGITS: u8> From<&str> for $Ty<DIGITS> {
fn from(src: &str) -> Self {
<Self as core::str::FromStr>::from_str(src).unwrap()
}
}
impl<const DIGITS: u8> core::ops::AddAssign for $Ty<DIGITS> {
#[inline]
fn add_assign(&mut self, rhs: Self) {
*self = *self + rhs;
}
}
impl<const DIGITS: u8> core::ops::SubAssign for $Ty<DIGITS> {
#[inline]
fn sub_assign(&mut self, rhs: Self) {
*self = *self - rhs;
}
}
impl<const DIGITS: u8> core::ops::MulAssign for $Ty<DIGITS> {
#[inline]
fn mul_assign(&mut self, rhs: Self) {
*self = *self * rhs;
}
}
impl<const DIGITS: u8> core::ops::DivAssign for $Ty<DIGITS> {
#[inline]
fn div_assign(&mut self, rhs: Self) {
*self = *self / rhs;
}
}
impl<const DIGITS: u8> core::ops::RemAssign for $Ty<DIGITS> {
#[inline]
fn rem_assign(&mut self, rhs: Self) {
*self = *self % rhs;
}
}
impl<const DIGITS: u8> core::iter::Sum for $Ty<DIGITS> {
fn sum<I: Iterator<Item = Self>>(iter: I) -> Self {
iter.fold(Self::ZERO, |a, b| a + b)
}
}
impl<'a, const DIGITS: u8> core::iter::Sum<&'a $Ty<DIGITS>> for $Ty<DIGITS> {
fn sum<I: Iterator<Item = &'a Self>>(iter: I) -> Self {
iter.fold(Self::ZERO, |a, b| a + *b)
}
}
impl<const DIGITS: u8> core::iter::Product for $Ty<DIGITS> {
fn product<I: Iterator<Item = Self>>(iter: I) -> Self {
iter.fold(Self::ONE, |a, b| a * b)
}
}
impl<'a, const DIGITS: u8> core::iter::Product<&'a $Ty<DIGITS>> for $Ty<DIGITS> {
fn product<I: Iterator<Item = &'a Self>>(iter: I) -> Self {
iter.fold(Self::ONE, |a, b| a * *b)
}
}
impl<const DIGITS: u8> core::fmt::Display for $Ty<DIGITS> {
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
let mut buf = [0u8; 128];
let (neg, mag) = self.sign_mag4();
match crate::limbs::str_mag(
&mag,
neg,
DIGITS as usize,
f.precision(),
crate::AmountSign::None,
&mut buf,
) {
Some(s) => f.pad_integral(!neg, "", s),
_ => f.write_str("Amount::ERROR"),
}
}
}
#[cfg(feature = "serde")]
impl<const DIGITS: u8> serde::Serialize for $Ty<DIGITS> {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
serializer.collect_str(self)
}
}
#[cfg(feature = "serde")]
impl<'de, const DIGITS: u8> serde::Deserialize<'de> for $Ty<DIGITS> {
fn deserialize<Deser>(deserializer: Deser) -> Result<Self, Deser::Error>
where
Deser: serde::Deserializer<'de>,
{
struct DecimalVisitor<const D: u8>;
impl<'de, const D: u8> serde::de::Visitor<'de> for DecimalVisitor<D> {
type Value = $Ty<D>;
fn expecting(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
f.write_str("a string representation of a decimal number")
}
fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
where
E: serde::de::Error,
{
core::str::FromStr::from_str(value).map_err(serde::de::Error::custom)
}
}
deserializer.deserialize_str(DecimalVisitor::<DIGITS>)
}
}
#[cfg(feature = "ufmt")]
impl<const DIGITS: u8> ufmt::uDisplay for $Ty<DIGITS> {
fn fmt<W>(&self, f: &mut ufmt::Formatter<'_, W>) -> Result<(), W::Error>
where
W: ufmt::uWrite + ?Sized,
{
let mut buf = [0u8; 128];
let (neg, mag) = self.sign_mag4();
match crate::limbs::str_mag(
&mag,
neg,
DIGITS as usize,
None,
crate::AmountSign::Negative,
&mut buf,
) {
Some(s) => f.write_str(s),
None => f.write_str("Amount::ERROR"),
}
}
}
#[cfg(feature = "ufmt")]
impl<const DIGITS: u8> ufmt::uDebug for $Ty<DIGITS> {
fn fmt<W>(&self, f: &mut ufmt::Formatter<'_, W>) -> Result<(), W::Error>
where
W: ufmt::uWrite + ?Sized,
{
let mut buf = [0u8; 96];
let (neg, mag) = self.sign_mag4();
f.write_str(concat!($name, "("))?;
match crate::limbs::str_mag(
&mag,
neg,
0,
None,
crate::AmountSign::Negative,
&mut buf,
) {
Some(s) => f.write_str(s)?,
None => f.write_str("ERROR")?,
}
f.write_str(")")
}
}
};
}
pub(crate) use impl_decimal_common;