Skip to main content

sqlx_xugu/types/
bytes.rs

1use crate::arguments::XuguArgumentValue;
2use crate::protocol::text::ColumnType;
3use crate::{Xugu, XuguTypeInfo, XuguValueRef};
4use bytes::Bytes;
5use sqlx_core::decode::Decode;
6use sqlx_core::encode::{Encode, IsNull};
7use sqlx_core::error::{BoxDynError, UnexpectedNullError};
8use sqlx_core::types::Type;
9use sqlx_core::value::ValueRef;
10use std::borrow::Cow;
11
12impl Type<Xugu> for [u8] {
13    fn type_info() -> XuguTypeInfo {
14        XuguTypeInfo::binary(ColumnType::BLOB)
15    }
16
17    fn compatible(ty: &XuguTypeInfo) -> bool {
18        matches!(
19            ty.r#type,
20            ColumnType::BLOB
21                | ColumnType::BLOB_I
22                | ColumnType::BLOB_M
23                | ColumnType::BLOB_OM
24                | ColumnType::BLOB_S
25                | ColumnType::CHAR
26                | ColumnType::NCHAR
27                | ColumnType::CLOB
28                | ColumnType::BINARY
29                | ColumnType::GUID
30        )
31    }
32}
33
34impl<'q> Encode<'q, Xugu> for &'q [u8] {
35    fn encode_by_ref(&self, args: &mut Vec<XuguArgumentValue<'q>>) -> Result<IsNull, BoxDynError> {
36        if self.is_empty() {
37            args.push(XuguArgumentValue::Bin(Cow::Borrowed(b"\0")));
38        } else {
39            args.push(XuguArgumentValue::Bin(Cow::Borrowed(self)));
40        }
41
42        Ok(IsNull::No)
43    }
44}
45
46impl<'q> Decode<'q, Xugu> for &'q [u8] {
47    fn decode(value: XuguValueRef<'q>) -> Result<Self, BoxDynError> {
48        value.as_bytes().map(map_empty)
49    }
50}
51
52impl Type<Xugu> for Box<[u8]> {
53    fn type_info() -> XuguTypeInfo {
54        <&[u8] as Type<Xugu>>::type_info()
55    }
56
57    fn compatible(ty: &XuguTypeInfo) -> bool {
58        <&[u8] as Type<Xugu>>::compatible(ty)
59    }
60}
61
62impl Encode<'_, Xugu> for Box<[u8]> {
63    fn encode(self, args: &mut Vec<XuguArgumentValue<'_>>) -> Result<IsNull, BoxDynError> {
64        if self.is_empty() {
65            args.push(XuguArgumentValue::Bin(Cow::Borrowed(b"\0")));
66        } else {
67            args.push(XuguArgumentValue::Bin(Cow::Owned(self.into_vec())));
68        }
69
70        Ok(IsNull::No)
71    }
72
73    fn encode_by_ref(&self, args: &mut Vec<XuguArgumentValue<'_>>) -> Result<IsNull, BoxDynError> {
74        if self.is_empty() {
75            args.push(XuguArgumentValue::Bin(Cow::Borrowed(b"\0")));
76        } else {
77            args.push(XuguArgumentValue::Bin(Cow::Owned(self.clone().into_vec())));
78        }
79
80        Ok(IsNull::No)
81    }
82}
83
84impl<'r> Decode<'r, Xugu> for Box<[u8]> {
85    fn decode(value: XuguValueRef<'r>) -> Result<Self, BoxDynError> {
86        value.as_bytes().map(map_empty).map(Box::from)
87    }
88}
89
90impl Type<Xugu> for Cow<'_, [u8]> {
91    fn type_info() -> XuguTypeInfo {
92        <&[u8] as Type<Xugu>>::type_info()
93    }
94
95    fn compatible(ty: &XuguTypeInfo) -> bool {
96        <&[u8] as Type<Xugu>>::compatible(ty)
97    }
98}
99
100impl<'q> Encode<'q, Xugu> for Cow<'q, [u8]> {
101    fn encode(self, args: &mut Vec<XuguArgumentValue<'q>>) -> Result<IsNull, BoxDynError> {
102        if self.is_empty() {
103            args.push(XuguArgumentValue::Bin(Cow::Borrowed(b"\0")));
104        } else {
105            args.push(XuguArgumentValue::Bin(self));
106        }
107
108        Ok(IsNull::No)
109    }
110
111    fn encode_by_ref(&self, args: &mut Vec<XuguArgumentValue<'q>>) -> Result<IsNull, BoxDynError> {
112        if self.is_empty() {
113            args.push(XuguArgumentValue::Bin(Cow::Borrowed(b"\0")));
114        } else {
115            args.push(XuguArgumentValue::Bin(self.clone()));
116        }
117
118        Ok(IsNull::No)
119    }
120}
121
122impl<'r> Decode<'r, Xugu> for Cow<'r, [u8]> {
123    fn decode(value: XuguValueRef<'r>) -> Result<Self, BoxDynError> {
124        value.as_bytes().map(map_empty).map(Cow::Borrowed)
125    }
126}
127
128impl Type<Xugu> for Vec<u8> {
129    fn type_info() -> XuguTypeInfo {
130        <[u8] as Type<Xugu>>::type_info()
131    }
132
133    fn compatible(ty: &XuguTypeInfo) -> bool {
134        <&[u8] as Type<Xugu>>::compatible(ty)
135    }
136}
137
138impl Encode<'_, Xugu> for Vec<u8> {
139    fn encode(self, args: &mut Vec<XuguArgumentValue<'_>>) -> Result<IsNull, BoxDynError> {
140        if self.is_empty() {
141            args.push(XuguArgumentValue::Bin(Cow::Borrowed(b"\0")));
142        } else {
143            args.push(XuguArgumentValue::Bin(Cow::Owned(self)));
144        }
145
146        Ok(IsNull::No)
147    }
148
149    fn encode_by_ref(&self, args: &mut Vec<XuguArgumentValue<'_>>) -> Result<IsNull, BoxDynError> {
150        if self.is_empty() {
151            args.push(XuguArgumentValue::Bin(Cow::Borrowed(b"\0")));
152        } else {
153            args.push(XuguArgumentValue::Bin(Cow::Owned(self.clone())));
154        }
155
156        Ok(IsNull::No)
157    }
158}
159
160impl Decode<'_, Xugu> for Vec<u8> {
161    fn decode(value: XuguValueRef<'_>) -> Result<Self, BoxDynError> {
162        value.as_bytes().map(map_empty).map(ToOwned::to_owned)
163    }
164}
165
166impl Type<Xugu> for Bytes {
167    fn type_info() -> XuguTypeInfo {
168        <&[u8] as Type<Xugu>>::type_info()
169    }
170
171    fn compatible(ty: &XuguTypeInfo) -> bool {
172        <&[u8] as Type<Xugu>>::compatible(ty)
173    }
174}
175
176impl Encode<'_, Xugu> for Bytes {
177    fn encode(self, args: &mut Vec<XuguArgumentValue<'_>>) -> Result<IsNull, BoxDynError> {
178        if self.is_empty() {
179            args.push(XuguArgumentValue::Bin(Cow::Borrowed(b"\0")));
180        } else {
181            args.push(XuguArgumentValue::Bytes(self));
182        }
183
184        Ok(IsNull::No)
185    }
186
187    fn encode_by_ref(&self, args: &mut Vec<XuguArgumentValue<'_>>) -> Result<IsNull, BoxDynError> {
188        if self.is_empty() {
189            args.push(XuguArgumentValue::Bin(Cow::Borrowed(b"\0")));
190        } else {
191            args.push(XuguArgumentValue::Bytes(self.clone()));
192        }
193
194        Ok(IsNull::No)
195    }
196}
197
198impl Decode<'_, Xugu> for Bytes {
199    fn decode(value: XuguValueRef<'_>) -> Result<Self, BoxDynError> {
200        let v = ValueRef::to_owned(&value);
201        match v.value {
202            Some(v) => {
203                if b"\0".as_slice() == v {
204                    return Ok(Bytes::new());
205                }
206                Ok(v)
207            }
208            None => Err(UnexpectedNullError.into()),
209        }
210    }
211}
212
213// 处理空字节
214fn map_empty(s: &[u8]) -> &[u8] {
215    if s == b"\0" {
216        return b"";
217    }
218    s
219}