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
213fn map_empty(s: &[u8]) -> &[u8] {
215 if s == b"\0" {
216 return b"";
217 }
218 s
219}