1use crate::arguments::XuguArgumentValue;
2use crate::error::BoxDynError;
3use crate::protocol::text::{ColumnFlags, ColumnType};
4use crate::{Xugu, XuguTypeInfo, XuguValueRef};
5use byteorder::{BigEndian, ByteOrder};
6use sqlx_core::decode::Decode;
7use sqlx_core::encode::{Encode, IsNull};
8use sqlx_core::types::Type;
9use std::borrow::Cow;
10
11fn uint_compatible(ty: &XuguTypeInfo) -> bool {
12 matches!(
13 ty.r#type,
14 ColumnType::TINYINT
15 | ColumnType::SMALLINT
16 | ColumnType::INTEGER
17 | ColumnType::BIGINT
18 | ColumnType::BOOLEAN
19 ) && !ty.flags.contains(ColumnFlags::IS_LOB)
20}
21
22impl Type<Xugu> for u8 {
23 fn type_info() -> XuguTypeInfo {
24 XuguTypeInfo::binary(ColumnType::TINYINT)
25 }
26
27 fn compatible(ty: &XuguTypeInfo) -> bool {
28 uint_compatible(ty)
29 }
30}
31
32impl Type<Xugu> for u16 {
33 fn type_info() -> XuguTypeInfo {
34 XuguTypeInfo::binary(ColumnType::SMALLINT)
35 }
36
37 fn compatible(ty: &XuguTypeInfo) -> bool {
38 uint_compatible(ty)
39 }
40}
41
42impl Type<Xugu> for u32 {
43 fn type_info() -> XuguTypeInfo {
44 XuguTypeInfo::binary(ColumnType::INTEGER)
45 }
46
47 fn compatible(ty: &XuguTypeInfo) -> bool {
48 uint_compatible(ty)
49 }
50}
51
52impl Type<Xugu> for u64 {
53 fn type_info() -> XuguTypeInfo {
54 XuguTypeInfo::binary(ColumnType::BIGINT)
55 }
56
57 fn compatible(ty: &XuguTypeInfo) -> bool {
58 uint_compatible(ty)
59 }
60}
61
62impl Encode<'_, Xugu> for u8 {
63 fn encode_by_ref(&self, args: &mut Vec<XuguArgumentValue<'_>>) -> Result<IsNull, BoxDynError> {
64 let buf = self.to_be_bytes().to_vec();
65 args.push(XuguArgumentValue::Bin(Cow::Owned(buf)));
66
67 Ok(IsNull::No)
68 }
69}
70
71impl Encode<'_, Xugu> for u16 {
72 fn encode_by_ref(&self, args: &mut Vec<XuguArgumentValue<'_>>) -> Result<IsNull, BoxDynError> {
73 let buf = self.to_be_bytes().to_vec();
74 args.push(XuguArgumentValue::Bin(Cow::Owned(buf)));
75
76 Ok(IsNull::No)
77 }
78}
79
80impl Encode<'_, Xugu> for u32 {
81 fn encode_by_ref(&self, args: &mut Vec<XuguArgumentValue<'_>>) -> Result<IsNull, BoxDynError> {
82 let buf = self.to_be_bytes().to_vec();
83 args.push(XuguArgumentValue::Bin(Cow::Owned(buf)));
84
85 Ok(IsNull::No)
86 }
87}
88
89impl Encode<'_, Xugu> for u64 {
90 fn encode_by_ref(&self, args: &mut Vec<XuguArgumentValue<'_>>) -> Result<IsNull, BoxDynError> {
91 let buf = self.to_be_bytes().to_vec();
92 args.push(XuguArgumentValue::Bin(Cow::Owned(buf)));
93
94 Ok(IsNull::No)
95 }
96}
97
98fn uint_decode(value: XuguValueRef<'_>) -> Result<u64, BoxDynError> {
99 let buf = value.as_bytes()?;
100
101 if buf.is_empty() {
103 return Err("empty buffer".into());
104 }
105
106 if buf.len() > 8 {
107 return Err(format!(
108 "expected no more than 8 bytes for integer value, got {}",
109 buf.len()
110 )
111 .into());
112 }
113
114 if value.type_info.r#type == ColumnType::BOOLEAN {
115 return <bool as Decode<Xugu>>::decode(value).map(|x| x as u64);
116 }
117
118 Ok(BigEndian::read_uint(buf, buf.len()))
119}
120
121impl Decode<'_, Xugu> for u8 {
122 fn decode(value: XuguValueRef<'_>) -> Result<Self, BoxDynError> {
123 uint_decode(value)?.try_into().map_err(Into::into)
124 }
125}
126
127impl Decode<'_, Xugu> for u16 {
128 fn decode(value: XuguValueRef<'_>) -> Result<Self, BoxDynError> {
129 uint_decode(value)?.try_into().map_err(Into::into)
130 }
131}
132
133impl Decode<'_, Xugu> for u32 {
134 fn decode(value: XuguValueRef<'_>) -> Result<Self, BoxDynError> {
135 uint_decode(value)?.try_into().map_err(Into::into)
136 }
137}
138
139impl Decode<'_, Xugu> for u64 {
140 fn decode(value: XuguValueRef<'_>) -> Result<Self, BoxDynError> {
141 uint_decode(value)
142 }
143}