1use crate::deserialize::{self, Defaultable, FromSql};
2use crate::pg::{Pg, PgValue};
3use crate::serialize::{self, IsNull, Output, ToSql};
4use crate::sql_types;
5use byteorder::{NetworkEndian, ReadBytesExt, WriteBytesExt};
6
7#[cfg(feature = "postgres_backend")]
8impl FromSql<sql_types::Oid, Pg> for u32 {
9 fn from_sql(bytes: PgValue<'_>) -> deserialize::Result<Self> {
10 let mut bytes = bytes.as_bytes();
11 bytes.read_u32::<NetworkEndian>().map_err(Into::into)
12 }
13}
14
15#[cfg(feature = "postgres_backend")]
16impl ToSql<sql_types::Oid, Pg> for u32 {
17 fn to_sql<'b>(&'b self, out: &mut Output<'b, '_, Pg>) -> serialize::Result {
18 out.write_u32::<NetworkEndian>(*self)
19 .map(|_| IsNull::No)
20 .map_err(Into::into)
21 }
22}
23
24#[cfg(feature = "postgres_backend")]
25impl FromSql<sql_types::SmallInt, Pg> for i16 {
26 #[inline(always)]
27 fn from_sql(value: PgValue<'_>) -> deserialize::Result<Self> {
28 let mut bytes = value.as_bytes();
29 if bytes.len() < 2 {
30 return emit_size_error(
31 "Received less than 2 bytes while decoding an i16. \
32 Was an expression of a different type accidentally marked as SmallInt?",
33 );
34 }
35
36 if bytes.len() > 2 {
37 return emit_size_error(
38 "Received more than 2 bytes while decoding an i16. \
39 Was an Integer expression accidentally marked as SmallInt?",
40 );
41 }
42 bytes
43 .read_i16::<NetworkEndian>()
44 .map_err(|e| Box::new(e) as Box<_>)
45 }
46}
47
48#[cfg(feature = "postgres_backend")]
49impl FromSql<sql_types::Integer, Pg> for i32 {
50 #[inline(always)]
51 fn from_sql(value: PgValue<'_>) -> deserialize::Result<Self> {
52 let mut bytes = value.as_bytes();
53 if bytes.len() < 4 {
54 return emit_size_error(
55 "Received less than 4 bytes while decoding an i32. \
56 Was an SmallInt expression accidentally marked as Integer?",
57 );
58 }
59
60 if bytes.len() > 4 {
61 return emit_size_error(
62 "Received more than 4 bytes while decoding an i32. \
63 Was an BigInt expression accidentally marked as Integer?",
64 );
65 }
66 bytes
67 .read_i32::<NetworkEndian>()
68 .map_err(|e| Box::new(e) as Box<_>)
69 }
70}
71
72#[cold]
73#[inline(never)]
74fn emit_size_error<T>(var_name: &str) -> deserialize::Result<T> {
75 deserialize::Result::Err(var_name.into())
76}
77
78#[cfg(feature = "postgres_backend")]
79impl FromSql<sql_types::BigInt, Pg> for i64 {
80 #[inline(always)]
81 fn from_sql(value: PgValue<'_>) -> deserialize::Result<Self> {
82 let mut bytes = value.as_bytes();
83 if bytes.len() < 8 {
84 return emit_size_error(
85 "Received less than 8 bytes while decoding an i64. \
86 Was an Integer expression accidentally marked as BigInt?",
87 );
88 }
89
90 if bytes.len() > 8 {
91 return emit_size_error(
92 "Received more than 8 bytes while decoding an i64. \
93 Was an expression of a different type expression accidentally marked as BigInt?"
94 );
95 }
96 bytes
97 .read_i64::<NetworkEndian>()
98 .map_err(|e| Box::new(e) as Box<_>)
99 }
100}
101
102#[cfg(feature = "postgres_backend")]
103impl ToSql<sql_types::SmallInt, Pg> for i16 {
104 fn to_sql<'b>(&'b self, out: &mut Output<'b, '_, Pg>) -> serialize::Result {
105 out.write_i16::<NetworkEndian>(*self)
106 .map(|_| IsNull::No)
107 .map_err(|e| Box::new(e) as Box<_>)
108 }
109}
110
111#[cfg(feature = "postgres_backend")]
112impl ToSql<sql_types::Integer, Pg> for i32 {
113 fn to_sql<'b>(&'b self, out: &mut Output<'b, '_, Pg>) -> serialize::Result {
114 out.write_i32::<NetworkEndian>(*self)
115 .map(|_| IsNull::No)
116 .map_err(|e| Box::new(e) as Box<_>)
117 }
118}
119
120#[cfg(feature = "postgres_backend")]
121impl ToSql<sql_types::BigInt, Pg> for i64 {
122 fn to_sql<'b>(&'b self, out: &mut Output<'b, '_, Pg>) -> serialize::Result {
123 out.write_i64::<NetworkEndian>(*self)
124 .map(|_| IsNull::No)
125 .map_err(|e| Box::new(e) as Box<_>)
126 }
127}
128
129#[cfg(feature = "postgres_backend")]
130impl Defaultable for i32 {
131 fn default_value() -> Self {
132 Self::default()
133 }
134}
135
136#[cfg(feature = "postgres_backend")]
137impl Defaultable for i64 {
138 fn default_value() -> Self {
139 Self::default()
140 }
141}
142
143#[cfg(test)]
144mod tests {
145 use super::*;
146 use crate::query_builder::bind_collector::ByteWrapper;
147
148 #[diesel_test_helper::test]
149 fn i16_to_sql() {
150 let mut buffer = Vec::new();
151 let mut bytes = Output::test(ByteWrapper(&mut buffer));
152 ToSql::<sql_types::SmallInt, Pg>::to_sql(&1i16, &mut bytes).unwrap();
153 ToSql::<sql_types::SmallInt, Pg>::to_sql(&0i16, &mut bytes).unwrap();
154 ToSql::<sql_types::SmallInt, Pg>::to_sql(&-1i16, &mut bytes).unwrap();
155 assert_eq!(buffer, vec![0, 1, 0, 0, 255, 255]);
156 }
157
158 #[diesel_test_helper::test]
159 fn i32_to_sql() {
160 let mut buffer = Vec::new();
161 let mut bytes = Output::test(ByteWrapper(&mut buffer));
162 ToSql::<sql_types::Integer, Pg>::to_sql(&1i32, &mut bytes).unwrap();
163 ToSql::<sql_types::Integer, Pg>::to_sql(&0i32, &mut bytes).unwrap();
164 ToSql::<sql_types::Integer, Pg>::to_sql(&-1i32, &mut bytes).unwrap();
165 assert_eq!(buffer, vec![0, 0, 0, 1, 0, 0, 0, 0, 255, 255, 255, 255]);
166 }
167
168 #[diesel_test_helper::test]
169 fn i64_to_sql() {
170 let mut buffer = Vec::new();
171 let mut bytes = Output::test(ByteWrapper(&mut buffer));
172 ToSql::<sql_types::BigInt, Pg>::to_sql(&1i64, &mut bytes).unwrap();
173 ToSql::<sql_types::BigInt, Pg>::to_sql(&0i64, &mut bytes).unwrap();
174 ToSql::<sql_types::BigInt, Pg>::to_sql(&-1i64, &mut bytes).unwrap();
175 assert_eq!(
176 buffer,
177 vec![
178 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 255,
179 255,
180 ]
181 );
182 }
183}