1use std::{
2 fmt,
3 ops::{Deref, DerefMut},
4 str::FromStr,
5};
6
7use sqlx::{
8 Decode, Encode,
9 encode::IsNull,
10 mysql::{MySql, MySqlTypeInfo, MySqlValueRef},
11 postgres::{PgArgumentBuffer, PgHasArrayType, PgTypeInfo, PgValueRef, Postgres},
12 sqlite::{Sqlite, SqliteArgumentsBuffer, SqliteTypeInfo, SqliteValueRef},
13 types::{Decimal as Inner, Type},
14};
15
16#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
17#[repr(transparent)]
18pub struct Decimal(pub Inner);
19
20impl Deref for Decimal {
21 type Target = Inner;
22
23 fn deref(&self) -> &Self::Target {
24 &self.0
25 }
26}
27
28impl DerefMut for Decimal {
29 fn deref_mut(&mut self) -> &mut Self::Target {
30 &mut self.0
31 }
32}
33
34impl From<Inner> for Decimal {
35 fn from(v: Inner) -> Self {
36 Self(v)
37 }
38}
39
40impl From<Decimal> for Inner {
41 fn from(v: Decimal) -> Self {
42 v.0
43 }
44}
45
46impl fmt::Display for Decimal {
47 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
48 fmt::Display::fmt(&self.0, f)
49 }
50}
51
52impl FromStr for Decimal {
53 type Err = <Inner as FromStr>::Err;
54
55 fn from_str(s: &str) -> Result<Self, Self::Err> {
56 Inner::from_str(s).map(Self)
57 }
58}
59
60impl Type<Sqlite> for Decimal {
63 fn type_info() -> SqliteTypeInfo {
64 <String as Type<Sqlite>>::type_info()
65 }
66
67 fn compatible(ty: &SqliteTypeInfo) -> bool {
68 <String as Type<Sqlite>>::compatible(ty)
69 }
70}
71
72impl Encode<'_, Sqlite> for Decimal {
73 fn encode_by_ref(
74 &self,
75 buf: &mut SqliteArgumentsBuffer,
76 ) -> Result<IsNull, Box<dyn std::error::Error + Send + Sync>> {
77 <String as Encode<Sqlite>>::encode(self.0.to_string(), buf)
78 }
79}
80
81impl<'r> Decode<'r, Sqlite> for Decimal {
82 fn decode(value: SqliteValueRef<'r>) -> Result<Self, Box<dyn std::error::Error + Send + Sync>> {
83 let s = <String as Decode<Sqlite>>::decode(value)?;
84 Inner::from_str(&s).map(Self).map_err(Into::into)
85 }
86}
87
88impl Type<Postgres> for Decimal {
91 fn type_info() -> PgTypeInfo {
92 <Inner as Type<Postgres>>::type_info()
93 }
94
95 fn compatible(ty: &PgTypeInfo) -> bool {
96 <Inner as Type<Postgres>>::compatible(ty)
97 }
98}
99
100impl PgHasArrayType for Decimal {
101 fn array_type_info() -> PgTypeInfo {
102 <Inner as PgHasArrayType>::array_type_info()
103 }
104}
105
106impl Encode<'_, Postgres> for Decimal {
107 fn encode_by_ref(
108 &self,
109 buf: &mut PgArgumentBuffer,
110 ) -> Result<IsNull, Box<dyn std::error::Error + Send + Sync>> {
111 <Inner as Encode<Postgres>>::encode_by_ref(&self.0, buf)
112 }
113}
114
115impl<'r> Decode<'r, Postgres> for Decimal {
116 fn decode(value: PgValueRef<'r>) -> Result<Self, Box<dyn std::error::Error + Send + Sync>> {
117 <Inner as Decode<Postgres>>::decode(value).map(Self)
118 }
119}
120
121impl Type<MySql> for Decimal {
124 fn type_info() -> MySqlTypeInfo {
125 <Inner as Type<MySql>>::type_info()
126 }
127
128 fn compatible(ty: &MySqlTypeInfo) -> bool {
129 <Inner as Type<MySql>>::compatible(ty)
130 }
131}
132
133impl Encode<'_, MySql> for Decimal {
134 fn encode_by_ref(
135 &self,
136 buf: &mut Vec<u8>,
137 ) -> Result<IsNull, Box<dyn std::error::Error + Send + Sync>> {
138 <Inner as Encode<MySql>>::encode_by_ref(&self.0, buf)
139 }
140}
141
142impl<'r> Decode<'r, MySql> for Decimal {
143 fn decode(value: MySqlValueRef<'r>) -> Result<Self, Box<dyn std::error::Error + Send + Sync>> {
144 <Inner as Decode<MySql>>::decode(value).map(Self)
145 }
146}