1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95
use crate::*; use core::fmt; use rust_decimal::prelude::*; use serde::{de::Deserializer, Deserialize, Serialize}; use std::str::FromStr; macro_rules! decimal_scalar { ($stype:ident, $scalar:literal, $scale:literal) => { #[derive(Clone, Copy, Debug, Serialize, Deserialize, PartialEq)] pub struct $stype(Decimal); impl FromStr for $stype { type Err = Error; fn from_str(s: &str) -> Result<Self> { match Decimal::from_str(s).or_else(|_| Decimal::from_scientific(s)) { Ok(data) if data.scale() > 8 => Err(Error::decimals(s)), Ok(data) => Ok(Self(data)), Err(_) => Err(Error::decimals(s)), } } } impl fmt::Display for $stype { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { self.0.fmt(f) } } impl $stype { pub fn new(d: Decimal) -> Self { Self(d) } pub fn get_decimal(&self) -> Decimal { self.0 } pub fn deserialize<'de, D>(d: D) -> std::result::Result<Self, D::Error> where D: Deserializer<'de>, { let val = u64::deserialize(d)?; Ok(Self::from(val)) } } impl From<u64> for $stype { fn from(v: u64) -> Self { if let Some(mut data) = Decimal::from_u64(v) { data.set_scale($scale).unwrap(); return Self(data); } panic!("u64 could not be converted into Decimal") } } impl From<$stype> for u64 { fn from(v: $stype) -> Self { if let Some(scaled_dec) = v.0.checked_mul($scalar.into()) { if let Some(num) = scaled_dec.to_u64() { return num; } } panic!("Invalid scaled decimal construction") } } impl From<i32> for $stype { fn from(v: i32) -> Self { if let Some(mut data) = Decimal::from_i32(v) { data.set_scale($scale).unwrap(); return Self(data); } panic!("u64 could not be converted into Decimal") } } impl From<$stype> for i32 { fn from(v: $stype) -> Self { if let Some(scaled_dec) = v.0.checked_mul($scalar.into()) { if let Some(num) = scaled_dec.to_i32() { return num; } } panic!("Invalid scaled decimal construction") } } }; } decimal_scalar!(Hnt, 100_000_000, 8); decimal_scalar!(Hst, 100_000_000, 8); decimal_scalar!(Usd, 100_000_000, 8); decimal_scalar!(Dbi, 10, 1);