1use crate::deserialize::{self, Defaultable, FromSql, FromSqlRow};
2use crate::expression::AsExpression;
3use crate::pg::{Pg, PgValue};
4use crate::serialize::{self, IsNull, Output, ToSql};
5use crate::sql_types;
6use byteorder::{NetworkEndian, ReadBytesExt, WriteBytesExt};
7use std::error::Error;
8
9#[cfg(feature = "quickcheck")]
10mod quickcheck_impls;
11
12#[derive(#[automatically_derived]
impl ::core::fmt::Debug for PgNumeric {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
match self {
PgNumeric::Positive {
weight: __self_0, scale: __self_1, digits: __self_2 } =>
::core::fmt::Formatter::debug_struct_field3_finish(f,
"Positive", "weight", __self_0, "scale", __self_1, "digits",
&__self_2),
PgNumeric::Negative {
weight: __self_0, scale: __self_1, digits: __self_2 } =>
::core::fmt::Formatter::debug_struct_field3_finish(f,
"Negative", "weight", __self_0, "scale", __self_1, "digits",
&__self_2),
PgNumeric::NaN => ::core::fmt::Formatter::write_str(f, "NaN"),
}
}
}Debug, #[automatically_derived]
impl ::core::default::Default for PgNumeric {
#[inline]
fn default() -> PgNumeric { Self::NaN }
}Default, #[automatically_derived]
impl ::core::clone::Clone for PgNumeric {
#[inline]
fn clone(&self) -> PgNumeric {
match self {
PgNumeric::Positive {
weight: __self_0, scale: __self_1, digits: __self_2 } =>
PgNumeric::Positive {
weight: ::core::clone::Clone::clone(__self_0),
scale: ::core::clone::Clone::clone(__self_1),
digits: ::core::clone::Clone::clone(__self_2),
},
PgNumeric::Negative {
weight: __self_0, scale: __self_1, digits: __self_2 } =>
PgNumeric::Negative {
weight: ::core::clone::Clone::clone(__self_0),
scale: ::core::clone::Clone::clone(__self_1),
digits: ::core::clone::Clone::clone(__self_2),
},
PgNumeric::NaN => PgNumeric::NaN,
}
}
}Clone, #[automatically_derived]
impl ::core::cmp::PartialEq for PgNumeric {
#[inline]
fn eq(&self, other: &PgNumeric) -> bool {
let __self_discr = ::core::intrinsics::discriminant_value(self);
let __arg1_discr = ::core::intrinsics::discriminant_value(other);
__self_discr == __arg1_discr &&
match (self, other) {
(PgNumeric::Positive {
weight: __self_0, scale: __self_1, digits: __self_2 },
PgNumeric::Positive {
weight: __arg1_0, scale: __arg1_1, digits: __arg1_2 }) =>
__self_0 == __arg1_0 && __self_1 == __arg1_1 &&
__self_2 == __arg1_2,
(PgNumeric::Negative {
weight: __self_0, scale: __self_1, digits: __self_2 },
PgNumeric::Negative {
weight: __arg1_0, scale: __arg1_1, digits: __arg1_2 }) =>
__self_0 == __arg1_0 && __self_1 == __arg1_1 &&
__self_2 == __arg1_2,
_ => true,
}
}
}PartialEq, #[automatically_derived]
impl ::core::cmp::Eq for PgNumeric {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_receiver_is_total_eq(&self) -> () {
let _: ::core::cmp::AssertParamIsEq<i16>;
let _: ::core::cmp::AssertParamIsEq<u16>;
let _: ::core::cmp::AssertParamIsEq<Vec<i16>>;
let _: ::core::cmp::AssertParamIsEq<Vec<i16>>;
}
}Eq, const _: () =
{
use diesel;
impl<'__expr> diesel::expression::AsExpression<sql_types::Numeric> for
&'__expr PgNumeric {
type Expression =
diesel::internal::derives::as_expression::Bound<sql_types::Numeric,
Self>;
fn as_expression(self)
->
<Self as
diesel::expression::AsExpression<sql_types::Numeric>>::Expression {
diesel::internal::derives::as_expression::Bound::new(self)
}
}
impl<'__expr>
diesel::expression::AsExpression<diesel::sql_types::Nullable<sql_types::Numeric>>
for &'__expr PgNumeric {
type Expression =
diesel::internal::derives::as_expression::Bound<diesel::sql_types::Nullable<sql_types::Numeric>,
Self>;
fn as_expression(self)
->
<Self as
diesel::expression::AsExpression<diesel::sql_types::Nullable<sql_types::Numeric>>>::Expression {
diesel::internal::derives::as_expression::Bound::new(self)
}
}
impl<'__expr, '__expr2>
diesel::expression::AsExpression<sql_types::Numeric> for
&'__expr2 &'__expr PgNumeric {
type Expression =
diesel::internal::derives::as_expression::Bound<sql_types::Numeric,
Self>;
fn as_expression(self)
->
<Self as
diesel::expression::AsExpression<sql_types::Numeric>>::Expression {
diesel::internal::derives::as_expression::Bound::new(self)
}
}
impl<'__expr, '__expr2>
diesel::expression::AsExpression<diesel::sql_types::Nullable<sql_types::Numeric>>
for &'__expr2 &'__expr PgNumeric {
type Expression =
diesel::internal::derives::as_expression::Bound<diesel::sql_types::Nullable<sql_types::Numeric>,
Self>;
fn as_expression(self)
->
<Self as
diesel::expression::AsExpression<diesel::sql_types::Nullable<sql_types::Numeric>>>::Expression {
diesel::internal::derives::as_expression::Bound::new(self)
}
}
impl<__DB>
diesel::serialize::ToSql<diesel::sql_types::Nullable<sql_types::Numeric>,
__DB> for PgNumeric where __DB: diesel::backend::Backend,
Self: diesel::serialize::ToSql<sql_types::Numeric, __DB> {
fn to_sql<'__b>(&'__b self,
out: &mut diesel::serialize::Output<'__b, '_, __DB>)
-> diesel::serialize::Result {
diesel::serialize::ToSql::<sql_types::Numeric,
__DB>::to_sql(self, out)
}
}
impl diesel::expression::AsExpression<sql_types::Numeric> for
PgNumeric {
type Expression =
diesel::internal::derives::as_expression::Bound<sql_types::Numeric,
Self>;
fn as_expression(self)
->
<Self as
diesel::expression::AsExpression<sql_types::Numeric>>::Expression {
diesel::internal::derives::as_expression::Bound::new(self)
}
}
impl diesel::expression::AsExpression<diesel::sql_types::Nullable<sql_types::Numeric>>
for PgNumeric {
type Expression =
diesel::internal::derives::as_expression::Bound<diesel::sql_types::Nullable<sql_types::Numeric>,
Self>;
fn as_expression(self)
->
<Self as
diesel::expression::AsExpression<diesel::sql_types::Nullable<sql_types::Numeric>>>::Expression {
diesel::internal::derives::as_expression::Bound::new(self)
}
}
};AsExpression, const _: () =
{
use diesel;
impl<__DB, __ST> diesel::deserialize::Queryable<__ST, __DB> for
PgNumeric 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)]
13#[diesel(sql_type = sql_types::Numeric)]
14pub enum PgNumeric {
17 Positive {
19 weight: i16,
21 scale: u16,
23 digits: Vec<i16>,
25 },
26 Negative {
28 weight: i16,
30 scale: u16,
32 digits: Vec<i16>,
34 },
35 #[default]
37 NaN,
38}
39
40#[derive(#[automatically_derived]
#[allow(dead_code)]
impl ::core::fmt::Debug for InvalidNumericSign {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::debug_tuple_field1_finish(f,
"InvalidNumericSign", &&self.0)
}
}Debug, #[automatically_derived]
#[allow(dead_code)]
impl ::core::clone::Clone for InvalidNumericSign {
#[inline]
fn clone(&self) -> InvalidNumericSign {
let _: ::core::clone::AssertParamIsClone<u16>;
*self
}
}Clone, #[automatically_derived]
#[allow(dead_code)]
impl ::core::marker::Copy for InvalidNumericSign { }Copy)]
41#[allow(dead_code)] struct InvalidNumericSign(u16);
43
44impl ::std::fmt::Display for InvalidNumericSign {
45 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> ::std::fmt::Result {
46 f.write_str("sign for numeric field was not one of 0, 0x4000, 0xC000")
47 }
48}
49
50impl Error for InvalidNumericSign {}
51
52#[cfg(feature = "postgres_backend")]
53impl FromSql<sql_types::Numeric, Pg> for PgNumeric {
54 fn from_sql(bytes: PgValue<'_>) -> deserialize::Result<Self> {
55 let mut bytes = bytes.as_bytes();
56 let digit_count = bytes.read_u16::<NetworkEndian>()?;
57 let mut digits = Vec::with_capacity(digit_count as usize);
58 let weight = bytes.read_i16::<NetworkEndian>()?;
59 let sign = bytes.read_u16::<NetworkEndian>()?;
60 let scale = bytes.read_u16::<NetworkEndian>()?;
61 for _ in 0..digit_count {
62 digits.push(bytes.read_i16::<NetworkEndian>()?);
63 }
64
65 match sign {
66 0 => Ok(PgNumeric::Positive {
67 weight,
68 scale,
69 digits,
70 }),
71 0x4000 => Ok(PgNumeric::Negative {
72 weight,
73 scale,
74 digits,
75 }),
76 0xC000 => Ok(PgNumeric::NaN),
77 invalid => Err(Box::new(InvalidNumericSign(invalid))),
78 }
79 }
80}
81
82#[cfg(feature = "postgres_backend")]
83impl ToSql<sql_types::Numeric, Pg> for PgNumeric {
84 fn to_sql<'b>(&'b self, out: &mut Output<'b, '_, Pg>) -> serialize::Result {
85 let sign = match *self {
86 PgNumeric::Positive { .. } => 0,
87 PgNumeric::Negative { .. } => 0x4000,
88 PgNumeric::NaN => 0xC000,
89 };
90 let empty_vec = Vec::new();
91 let digits = match *self {
92 PgNumeric::Positive { ref digits, .. } | PgNumeric::Negative { ref digits, .. } => {
93 digits
94 }
95 PgNumeric::NaN => &empty_vec,
96 };
97 let weight = match *self {
98 PgNumeric::Positive { weight, .. } | PgNumeric::Negative { weight, .. } => weight,
99 PgNumeric::NaN => 0,
100 };
101 let scale = match *self {
102 PgNumeric::Positive { scale, .. } | PgNumeric::Negative { scale, .. } => scale,
103 PgNumeric::NaN => 0,
104 };
105 out.write_u16::<NetworkEndian>(digits.len().try_into()?)?;
106 out.write_i16::<NetworkEndian>(weight)?;
107 out.write_u16::<NetworkEndian>(sign)?;
108 out.write_u16::<NetworkEndian>(scale)?;
109 for digit in digits.iter() {
110 out.write_i16::<NetworkEndian>(*digit)?;
111 }
112
113 Ok(IsNull::No)
114 }
115}
116
117#[cfg(feature = "postgres_backend")]
118impl Defaultable for PgNumeric {
119 fn default_value() -> Self {
120 Self::default()
121 }
122}
123
124#[cfg(feature = "postgres_backend")]
125impl FromSql<sql_types::Float, Pg> for f32 {
126 fn from_sql(value: PgValue<'_>) -> deserialize::Result<Self> {
127 let mut bytes = value.as_bytes();
128
129 if bytes.len() < 4 {
130 return deserialize::Result::Err(
131 "Received less than 4 bytes while decoding an f32. \
132 Was a numeric accidentally marked as float?"
133 .into(),
134 );
135 }
136
137 if bytes.len() > 4 {
138 return deserialize::Result::Err(
139 "Received more than 4 bytes while decoding an f32. \
140 Was a double accidentally marked as float?"
141 .into(),
142 );
143 }
144
145 bytes
146 .read_f32::<NetworkEndian>()
147 .map_err(|e| Box::new(e) as Box<dyn Error + Send + Sync>)
148 }
149}
150
151#[cfg(feature = "postgres_backend")]
152impl FromSql<sql_types::Double, Pg> for f64 {
153 fn from_sql(value: PgValue<'_>) -> deserialize::Result<Self> {
154 let mut bytes = value.as_bytes();
155
156 if bytes.len() < 8 {
157 return deserialize::Result::Err(
158 "Received less than 8 bytes while decoding an f64. \
159 Was a float accidentally marked as double?"
160 .into(),
161 );
162 }
163
164 if bytes.len() > 8 {
165 return deserialize::Result::Err(
166 "Received more than 8 bytes while decoding an f64. \
167 Was a numeric accidentally marked as double?"
168 .into(),
169 );
170 }
171
172 bytes
173 .read_f64::<NetworkEndian>()
174 .map_err(|e| Box::new(e) as Box<dyn Error + Send + Sync>)
175 }
176}
177
178#[cfg(feature = "postgres_backend")]
179impl ToSql<sql_types::Float, Pg> for f32 {
180 fn to_sql<'b>(&'b self, out: &mut Output<'b, '_, Pg>) -> serialize::Result {
181 out.write_f32::<NetworkEndian>(*self)
182 .map(|_| IsNull::No)
183 .map_err(|e| Box::new(e) as Box<dyn Error + Send + Sync>)
184 }
185}
186
187#[cfg(feature = "postgres_backend")]
188impl ToSql<sql_types::Double, Pg> for f64 {
189 fn to_sql<'b>(&'b self, out: &mut Output<'b, '_, Pg>) -> serialize::Result {
190 out.write_f64::<NetworkEndian>(*self)
191 .map(|_| IsNull::No)
192 .map_err(|e| Box::new(e) as Box<dyn Error + Send + Sync>)
193 }
194}