prusto_rs/types/
decimal.rs

1use std::str::FromStr;
2
3use serde::de::{self, Deserialize, DeserializeSeed, Deserializer};
4
5use super::{Context, Error, Presto, PrestoTy};
6
7#[derive(Debug, Default, Eq, PartialEq, Clone)]
8pub struct Decimal<const P: usize, const S: usize> {
9    inner: bigdecimal::BigDecimal,
10}
11
12impl<const P: usize, const S: usize> Decimal<P, S> {
13    pub fn into_bigdecimal(self) -> bigdecimal::BigDecimal {
14        self.inner
15    }
16}
17
18impl<const P: usize, const S: usize> FromStr for Decimal<P, S> {
19    type Err = Error;
20
21    fn from_str(s: &str) -> Result<Self, Self::Err> {
22        bigdecimal::BigDecimal::from_str(s)
23            .map(|inner| Self { inner })
24            .map_err(|e| Error::ParseDecimalFailed(format!("{}", e)))
25    }
26}
27
28impl<const P: usize, const S: usize> Presto for Decimal<P, S> {
29    type ValueType<'a> = String;
30    type Seed<'a, 'de> = DecimalSeed<P, S>;
31
32    fn value(&self) -> Self::ValueType<'_> {
33        format!("{}", self.inner)
34    }
35    fn ty() -> PrestoTy {
36        PrestoTy::Decimal(P, S)
37    }
38    fn seed<'a, 'de>(_ctx: &'a Context) -> Self::Seed<'a, 'de> {
39        DecimalSeed
40    }
41
42    fn empty() -> Self {
43        Default::default()
44    }
45}
46
47pub struct DecimalSeed<const P: usize, const S: usize>;
48
49impl<'de, const P: usize, const S: usize> DeserializeSeed<'de> for DecimalSeed<P, S> {
50    type Value = Decimal<P, S>;
51    fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
52    where
53        D: Deserializer<'de>,
54    {
55        let s = <&'de str as Deserialize<'de>>::deserialize(deserializer)?;
56        let d = bigdecimal::BigDecimal::from_str(s).map_err(de::Error::custom)?;
57
58        Ok(Decimal { inner: d })
59    }
60}
61
62#[cfg(test)]
63mod tests {
64    use super::*;
65
66    #[test]
67    fn smoke() {
68        let data = "1123412341234123412341234.2222222220";
69        let d = Decimal::<40, 10>::from_str(data).unwrap();
70        let s = format!("{}", d.into_bigdecimal());
71        assert_eq!(s, data);
72    }
73}