1use std::convert::TryInto;
2
3use byteorder::{ByteOrder, LittleEndian};
4
5use cdbc::decode::Decode;
6use cdbc::encode::{Encode, IsNull};
7use cdbc::error::BoxDynError;
8use crate::protocol::text::{ColumnFlags, ColumnType};
9use crate::{MySql, MySqlTypeInfo, MySqlValueFormat, MySqlValueRef};
10use cdbc::types::Type;
11
12fn int_compatible(ty: &MySqlTypeInfo) -> bool {
13 matches!(
14 ty.r#type,
15 ColumnType::Tiny
16 | ColumnType::Short
17 | ColumnType::Long
18 | ColumnType::Int24
19 | ColumnType::LongLong
20 ) && !ty.flags.contains(ColumnFlags::UNSIGNED)
21}
22
23impl Type<MySql> for i8 {
24 fn type_info() -> MySqlTypeInfo {
25 MySqlTypeInfo::binary(ColumnType::Tiny)
26 }
27
28 fn compatible(ty: &MySqlTypeInfo) -> bool {
29 int_compatible(ty)
30 }
31}
32
33impl Type<MySql> for i16 {
34 fn type_info() -> MySqlTypeInfo {
35 MySqlTypeInfo::binary(ColumnType::Short)
36 }
37
38 fn compatible(ty: &MySqlTypeInfo) -> bool {
39 int_compatible(ty)
40 }
41}
42
43impl Type<MySql> for i32 {
44 fn type_info() -> MySqlTypeInfo {
45 MySqlTypeInfo::binary(ColumnType::Long)
46 }
47
48 fn compatible(ty: &MySqlTypeInfo) -> bool {
49 int_compatible(ty)
50 }
51}
52
53impl Type<MySql> for i64 {
54 fn type_info() -> MySqlTypeInfo {
55 MySqlTypeInfo::binary(ColumnType::LongLong)
56 }
57
58 fn compatible(ty: &MySqlTypeInfo) -> bool {
59 int_compatible(ty)
60 }
61}
62
63impl Encode<'_, MySql> for i8 {
64 fn encode_by_ref(&self, buf: &mut Vec<u8>) -> IsNull {
65 buf.extend(&self.to_le_bytes());
66
67 IsNull::No
68 }
69}
70
71impl Encode<'_, MySql> for i16 {
72 fn encode_by_ref(&self, buf: &mut Vec<u8>) -> IsNull {
73 buf.extend(&self.to_le_bytes());
74
75 IsNull::No
76 }
77}
78
79impl Encode<'_, MySql> for i32 {
80 fn encode_by_ref(&self, buf: &mut Vec<u8>) -> IsNull {
81 buf.extend(&self.to_le_bytes());
82
83 IsNull::No
84 }
85}
86
87impl Encode<'_, MySql> for i64 {
88 fn encode_by_ref(&self, buf: &mut Vec<u8>) -> IsNull {
89 buf.extend(&self.to_le_bytes());
90
91 IsNull::No
92 }
93}
94
95fn int_decode(value: MySqlValueRef<'_>) -> Result<i64, BoxDynError> {
96 Ok(match value.format() {
97 MySqlValueFormat::Text => value.as_str()?.parse()?,
98 MySqlValueFormat::Binary => {
99 let buf = value.as_bytes()?;
100 LittleEndian::read_int(buf, buf.len())
101 }
102 })
103}
104
105impl Decode<'_, MySql> for i8 {
106 fn decode(value: MySqlValueRef<'_>) -> Result<Self, BoxDynError> {
107 int_decode(value)?.try_into().map_err(Into::into)
108 }
109}
110
111impl Decode<'_, MySql> for i16 {
112 fn decode(value: MySqlValueRef<'_>) -> Result<Self, BoxDynError> {
113 int_decode(value)?.try_into().map_err(Into::into)
114 }
115}
116
117impl Decode<'_, MySql> for i32 {
118 fn decode(value: MySqlValueRef<'_>) -> Result<Self, BoxDynError> {
119 int_decode(value)?.try_into().map_err(Into::into)
120 }
121}
122
123impl Decode<'_, MySql> for i64 {
124 fn decode(value: MySqlValueRef<'_>) -> Result<Self, BoxDynError> {
125 int_decode(value)
126 }
127}