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(#[automatically_derived]
impl ::core::fmt::Debug for PgMoney {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::debug_tuple_field1_finish(f, "PgMoney",
&&self.0)
}
}Debug, #[automatically_derived]
impl ::core::clone::Clone for PgMoney {
#[inline]
fn clone(&self) -> PgMoney {
let _: ::core::clone::AssertParamIsClone<i64>;
*self
}
}Clone, #[automatically_derived]
impl ::core::marker::Copy for PgMoney { }Copy, #[automatically_derived]
impl ::core::cmp::PartialEq for PgMoney {
#[inline]
fn eq(&self, other: &PgMoney) -> bool { self.0 == other.0 }
}PartialEq, #[automatically_derived]
impl ::core::cmp::Eq for PgMoney {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_receiver_is_total_eq(&self) -> () {
let _: ::core::cmp::AssertParamIsEq<i64>;
}
}Eq, #[automatically_derived]
impl ::core::hash::Hash for PgMoney {
#[inline]
fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) -> () {
::core::hash::Hash::hash(&self.0, state)
}
}Hash, #[automatically_derived]
impl ::core::cmp::PartialOrd for PgMoney {
#[inline]
fn partial_cmp(&self, other: &PgMoney)
-> ::core::option::Option<::core::cmp::Ordering> {
::core::cmp::PartialOrd::partial_cmp(&self.0, &other.0)
}
}PartialOrd, #[automatically_derived]
impl ::core::cmp::Ord for PgMoney {
#[inline]
fn cmp(&self, other: &PgMoney) -> ::core::cmp::Ordering {
::core::cmp::Ord::cmp(&self.0, &other.0)
}
}Ord, const _: () =
{
use diesel;
impl<'__expr> diesel::expression::AsExpression<Money> for
&'__expr PgMoney {
type Expression =
diesel::internal::derives::as_expression::Bound<Money, Self>;
fn as_expression(self)
->
<Self as
diesel::expression::AsExpression<Money>>::Expression {
diesel::internal::derives::as_expression::Bound::new(self)
}
}
impl<'__expr>
diesel::expression::AsExpression<diesel::sql_types::Nullable<Money>>
for &'__expr PgMoney {
type Expression =
diesel::internal::derives::as_expression::Bound<diesel::sql_types::Nullable<Money>,
Self>;
fn as_expression(self)
->
<Self as
diesel::expression::AsExpression<diesel::sql_types::Nullable<Money>>>::Expression {
diesel::internal::derives::as_expression::Bound::new(self)
}
}
impl<'__expr, '__expr2> diesel::expression::AsExpression<Money> for
&'__expr2 &'__expr PgMoney {
type Expression =
diesel::internal::derives::as_expression::Bound<Money, Self>;
fn as_expression(self)
->
<Self as
diesel::expression::AsExpression<Money>>::Expression {
diesel::internal::derives::as_expression::Bound::new(self)
}
}
impl<'__expr, '__expr2>
diesel::expression::AsExpression<diesel::sql_types::Nullable<Money>>
for &'__expr2 &'__expr PgMoney {
type Expression =
diesel::internal::derives::as_expression::Bound<diesel::sql_types::Nullable<Money>,
Self>;
fn as_expression(self)
->
<Self as
diesel::expression::AsExpression<diesel::sql_types::Nullable<Money>>>::Expression {
diesel::internal::derives::as_expression::Bound::new(self)
}
}
impl<__DB>
diesel::serialize::ToSql<diesel::sql_types::Nullable<Money>, __DB>
for PgMoney where __DB: diesel::backend::Backend,
Self: diesel::serialize::ToSql<Money, __DB> {
fn to_sql<'__b>(&'__b self,
out: &mut diesel::serialize::Output<'__b, '_, __DB>)
-> diesel::serialize::Result {
diesel::serialize::ToSql::<Money, __DB>::to_sql(self, out)
}
}
impl diesel::expression::AsExpression<Money> for PgMoney {
type Expression =
diesel::internal::derives::as_expression::Bound<Money, Self>;
fn as_expression(self)
->
<Self as
diesel::expression::AsExpression<Money>>::Expression {
diesel::internal::derives::as_expression::Bound::new(self)
}
}
impl diesel::expression::AsExpression<diesel::sql_types::Nullable<Money>>
for PgMoney {
type Expression =
diesel::internal::derives::as_expression::Bound<diesel::sql_types::Nullable<Money>,
Self>;
fn as_expression(self)
->
<Self as
diesel::expression::AsExpression<diesel::sql_types::Nullable<Money>>>::Expression {
diesel::internal::derives::as_expression::Bound::new(self)
}
}
};AsExpression, const _: () =
{
use diesel;
impl<__DB, __ST> diesel::deserialize::Queryable<__ST, __DB> for
PgMoney where __DB: diesel::backend::Backend,
__ST: diesel::sql_types::SingleValue,
Self: diesel::deserialize::FromSql<__ST, __DB> {
type Row = Self;
fn build(row: Self) -> diesel::deserialize::Result<Self> {
diesel::deserialize::Result::Ok(row)
}
}
};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#[cfg(test)]
104mod tests {
105 use super::PgMoney;
106
107 #[diesel_test_helper::test]
108 fn add_money() {
109 let c1 = PgMoney(123);
110 let c2 = PgMoney(456);
111 assert_eq!(PgMoney(579), c1 + c2);
112 }
113
114 #[diesel_test_helper::test]
115 fn add_assign_money() {
116 let mut c1 = PgMoney(123);
117 c1 += PgMoney(456);
118 assert_eq!(PgMoney(579), c1);
119 }
120
121 #[diesel_test_helper::test]
122 #[should_panic(expected = "overflow adding money amounts")]
123 fn add_money_overflow() {
124 let c1 = PgMoney(i64::MAX);
125 let c2 = PgMoney(1);
126 let _overflow = c1 + c2;
127 }
128
129 #[diesel_test_helper::test]
130 #[should_panic(expected = "overflow adding money amounts")]
131 fn add_assign_money_overflow() {
132 let mut c1 = PgMoney(i64::MAX);
133 c1 += PgMoney(1);
134 }
135
136 #[diesel_test_helper::test]
137 fn sub_money() {
138 let c1 = PgMoney(123);
139 let c2 = PgMoney(456);
140 assert_eq!(PgMoney(-333), c1 - c2);
141 }
142
143 #[diesel_test_helper::test]
144 fn sub_assign_money() {
145 let mut c1 = PgMoney(123);
146 c1 -= PgMoney(456);
147 assert_eq!(PgMoney(-333), c1);
148 }
149
150 #[diesel_test_helper::test]
151 #[should_panic(expected = "underflow subtracting money amounts")]
152 fn sub_money_underflow() {
153 let c1 = PgMoney(i64::MIN);
154 let c2 = PgMoney(1);
155 let _underflow = c1 - c2;
156 }
157
158 #[diesel_test_helper::test]
159 #[should_panic(expected = "underflow subtracting money amounts")]
160 fn sub_assign_money_underflow() {
161 let mut c1 = PgMoney(i64::MIN);
162 c1 -= PgMoney(1);
163 }
164}