mybatis_drive/types/
decimal.rs1use std::any::type_name;
2use std::fmt::Formatter;
3use std::ops::{Deref, DerefMut};
4use std::str::FromStr;
5use bigdecimal_::{BigDecimal, ParseBigDecimalError};
6use rbson::Bson;
7use rbson::spec::BinarySubtype;
8use serde::{Deserializer, Serialize, Serializer};
9use serde::de::{Error, Visitor};
10
11#[derive(Clone, Eq, Hash, Ord, PartialEq, PartialOrd)]
13pub struct Decimal {
14 pub inner: BigDecimal,
15}
16
17impl From<BigDecimal> for Decimal {
18 fn from(arg: BigDecimal) -> Self {
19 Self {
20 inner: arg
21 }
22 }
23}
24
25impl From<&BigDecimal> for Decimal {
26 fn from(arg: &BigDecimal) -> Self {
27 Self {
28 inner: arg.clone()
29 }
30 }
31}
32
33impl serde::Serialize for Decimal {
34 #[inline]
35 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: Serializer {
36 use serde::ser::Error;
37 if type_name::<S::Error>().eq("rbson::ser::error::Error") {
38 return serializer.serialize_str(&format!("Decimal({})", self.inner));
39 }else{
40 return self.inner.serialize(serializer);
41 }
42 }
43}
44
45impl<'de> serde::Deserialize<'de> for Decimal {
47 #[inline]
48 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> where D: Deserializer<'de> {
49 let bson = rbson::Bson::deserialize(deserializer)?;
50 return match bson {
51 Bson::String(s) => {
52 if s.starts_with("Decimal(") && s.ends_with(")") {
53 let inner_data = &s["Decimal(".len()..(s.len() - 1)];
54 return Ok(Self {
55 inner: BigDecimal::from_str(inner_data).or_else(|e| Err(D::Error::custom(e.to_string())))?,
56 });
57 } else {
58 Ok(Self {
59 inner: BigDecimal::from_str(s.as_str()).unwrap_or_default(),
60 })
61 }
62 }
63 Bson::Int32(s) => {
64 Ok(Self {
65 inner: BigDecimal::from(s),
66 })
67 }
68 Bson::Int64(s) => {
69 Ok(Self {
70 inner: BigDecimal::from(s),
71 })
72 }
73 Bson::Decimal128(s) => {
74 Ok(Self {
75 inner: BigDecimal::from_str(&s.to_string()).unwrap_or_default(),
76 })
77 }
78 _ => {
79 Err(D::Error::custom("deserialize unsupported bson type!"))
80 }
81 };
82 }
83}
84
85impl std::fmt::Display for Decimal {
86 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
87 self.inner.fmt(f)
88 }
89}
90
91impl std::fmt::Debug for Decimal {
92 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
93 self.inner.fmt(f)
94 }
95}
96
97impl Deref for Decimal {
98 type Target = BigDecimal;
99
100 fn deref(&self) -> &Self::Target {
101 &self.inner
102 }
103}
104
105impl DerefMut for Decimal {
106 fn deref_mut(&mut self) -> &mut Self::Target {
107 &mut self.inner
108 }
109}
110
111
112impl Decimal {
113 pub fn from(s: &str) -> Self {
114 let b = BigDecimal::from_str(s).unwrap_or_default();
115 Self {
116 inner: b
117 }
118 }
119
120 pub fn from_str(arg: &str) -> Result<Self, crate::error::Error> {
122 let b = BigDecimal::from_str(arg)?;
123 Ok(Self {
124 inner: b
125 })
126 }
127}
128
129#[cfg(test)]
130mod test {
131 use rbson::Bson;
132 use crate::types::Decimal;
133
134 #[test]
135 fn test_ser_de() {
136 let b = Decimal::from("1");
137 let bsons = rbson::to_bson(&b).unwrap();
138 match &bsons{
139 rbson::Bson::String(s)=>{
140 assert_eq!(s,"Decimal(1)");
141 }
142 _ => {
143 panic!("not str");
144 }
145 }
146 let b_de: Decimal = rbson::from_bson(bsons).unwrap();
147 assert_eq!(b, b_de);
148 }
149}