prusto_rs/types/
decimal.rs1use 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}