diesel/pg/types/
money.rs
1use std::ops::{Add, AddAssign, Sub, SubAssign};
3
4use crate::deserialize::{self, FromSql, FromSqlRow};
5use crate::expression::AsExpression;
6use crate::pg::{Pg, PgValue};
7use crate::serialize::{self, Output, ToSql};
8use crate::sql_types::{BigInt, Money};
9
10#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, AsExpression, FromSqlRow)]
22#[diesel(sql_type = Money)]
23pub struct PgMoney(pub i64);
24
25#[cfg(feature = "postgres_backend")]
26impl FromSql<Money, Pg> for PgMoney {
27 fn from_sql(bytes: PgValue<'_>) -> deserialize::Result<Self> {
28 FromSql::<BigInt, Pg>::from_sql(bytes).map(PgMoney)
29 }
30}
31
32#[cfg(feature = "postgres_backend")]
33impl ToSql<Money, Pg> for PgMoney {
34 fn to_sql<'b>(&'b self, out: &mut Output<'b, '_, Pg>) -> serialize::Result {
35 ToSql::<BigInt, Pg>::to_sql(&self.0, out)
36 }
37}
38
39impl Add for PgMoney {
40 type Output = Self;
41 fn add(self, rhs: PgMoney) -> Self::Output {
45 self.0
46 .checked_add(rhs.0)
47 .map(PgMoney)
48 .expect("overflow adding money amounts")
49 }
50}
51
52impl AddAssign for PgMoney {
53 fn add_assign(&mut self, rhs: PgMoney) {
57 self.0 = self
58 .0
59 .checked_add(rhs.0)
60 .expect("overflow adding money amounts")
61 }
62}
63
64impl Sub for PgMoney {
65 type Output = Self;
66 fn sub(self, rhs: PgMoney) -> Self::Output {
70 self.0
71 .checked_sub(rhs.0)
72 .map(PgMoney)
73 .expect("underflow subtracting money amounts")
74 }
75}
76
77impl SubAssign for PgMoney {
78 fn sub_assign(&mut self, rhs: PgMoney) {
82 self.0 = self
83 .0
84 .checked_sub(rhs.0)
85 .expect("underflow subtracting money amounts")
86 }
87}
88
89#[cfg(feature = "quickcheck")]
90mod quickcheck_impls {
91 extern crate quickcheck;
92
93 use self::quickcheck::{Arbitrary, Gen};
94 use super::PgMoney;
95
96 impl Arbitrary for PgMoney {
97 fn arbitrary(g: &mut Gen) -> Self {
98 PgMoney(i64::arbitrary(g))
99 }
100 }
101}
102
103#[test]
104fn add_money() {
105 let c1 = PgMoney(123);
106 let c2 = PgMoney(456);
107 assert_eq!(PgMoney(579), c1 + c2);
108}
109
110#[test]
111fn add_assign_money() {
112 let mut c1 = PgMoney(123);
113 c1 += PgMoney(456);
114 assert_eq!(PgMoney(579), c1);
115}
116
117#[test]
118#[should_panic(expected = "overflow adding money amounts")]
119fn add_money_overflow() {
120 let c1 = PgMoney(i64::MAX);
121 let c2 = PgMoney(1);
122 let _overflow = c1 + c2;
123}
124
125#[test]
126#[should_panic(expected = "overflow adding money amounts")]
127fn add_assign_money_overflow() {
128 let mut c1 = PgMoney(i64::MAX);
129 c1 += PgMoney(1);
130}
131
132#[test]
133fn sub_money() {
134 let c1 = PgMoney(123);
135 let c2 = PgMoney(456);
136 assert_eq!(PgMoney(-333), c1 - c2);
137}
138
139#[test]
140fn sub_assign_money() {
141 let mut c1 = PgMoney(123);
142 c1 -= PgMoney(456);
143 assert_eq!(PgMoney(-333), c1);
144}
145
146#[test]
147#[should_panic(expected = "underflow subtracting money amounts")]
148fn sub_money_underflow() {
149 let c1 = PgMoney(i64::MIN);
150 let c2 = PgMoney(1);
151 let _underflow = c1 - c2;
152}
153
154#[test]
155#[should_panic(expected = "underflow subtracting money amounts")]
156fn sub_assign_money_underflow() {
157 let mut c1 = PgMoney(i64::MIN);
158 c1 -= PgMoney(1);
159}