1use crate::arguments::XuguArgumentValue;
2use crate::protocol::text::ColumnType;
3use crate::{Xugu, XuguTypeInfo, XuguValueRef};
4use sqlx_core::decode::Decode;
5use sqlx_core::encode::{Encode, IsNull};
6use sqlx_core::error::BoxDynError;
7use sqlx_core::types::Type;
8use std::borrow::Cow;
9
10impl Type<Xugu> for [u8] {
11 fn type_info() -> XuguTypeInfo {
12 XuguTypeInfo::binary(ColumnType::BLOB)
13 }
14
15 fn compatible(ty: &XuguTypeInfo) -> bool {
16 matches!(
17 ty.r#type,
18 ColumnType::BLOB
19 | ColumnType::BLOB_I
20 | ColumnType::BLOB_M
21 | ColumnType::BLOB_OM
22 | ColumnType::BLOB_S
23 | ColumnType::CHAR
24 | ColumnType::NCHAR
25 | ColumnType::CLOB
26 | ColumnType::BINARY
27 | ColumnType::GUID
28 )
29 }
30}
31
32impl<'q> Encode<'q, Xugu> for &'q [u8] {
33 fn encode_by_ref(&self, args: &mut Vec<XuguArgumentValue<'q>>) -> Result<IsNull, BoxDynError> {
34 if self.is_empty() {
35 args.push(XuguArgumentValue::Bin(Cow::Borrowed(b"\0")));
36 } else {
37 args.push(XuguArgumentValue::Bin(Cow::Borrowed(self)));
38 }
39
40 Ok(IsNull::No)
41 }
42}
43
44impl<'q> Decode<'q, Xugu> for &'q [u8] {
45 fn decode(value: XuguValueRef<'q>) -> Result<Self, BoxDynError> {
46 value.as_bytes().map(map_empty)
47 }
48}
49
50impl Type<Xugu> for Box<[u8]> {
51 fn type_info() -> XuguTypeInfo {
52 <&[u8] as Type<Xugu>>::type_info()
53 }
54
55 fn compatible(ty: &XuguTypeInfo) -> bool {
56 <&[u8] as Type<Xugu>>::compatible(ty)
57 }
58}
59
60impl Encode<'_, Xugu> for Box<[u8]> {
61 fn encode(self, args: &mut Vec<XuguArgumentValue<'_>>) -> Result<IsNull, BoxDynError> {
62 if self.is_empty() {
63 args.push(XuguArgumentValue::Bin(Cow::Borrowed(b"\0")));
64 } else {
65 args.push(XuguArgumentValue::Bin(Cow::Owned(self.into_vec())));
66 }
67
68 Ok(IsNull::No)
69 }
70
71 fn encode_by_ref(&self, args: &mut Vec<XuguArgumentValue<'_>>) -> Result<IsNull, BoxDynError> {
72 if self.is_empty() {
73 args.push(XuguArgumentValue::Bin(Cow::Borrowed(b"\0")));
74 } else {
75 args.push(XuguArgumentValue::Bin(Cow::Owned(self.clone().into_vec())));
76 }
77
78 Ok(IsNull::No)
79 }
80}
81
82impl<'r> Decode<'r, Xugu> for Box<[u8]> {
83 fn decode(value: XuguValueRef<'r>) -> Result<Self, BoxDynError> {
84 value.as_bytes().map(map_empty).map(Box::from)
85 }
86}
87
88impl Type<Xugu> for Vec<u8> {
89 fn type_info() -> XuguTypeInfo {
90 <[u8] as Type<Xugu>>::type_info()
91 }
92
93 fn compatible(ty: &XuguTypeInfo) -> bool {
94 <&[u8] as Type<Xugu>>::compatible(ty)
95 }
96}
97
98impl Encode<'_, Xugu> for Vec<u8> {
99 fn encode(self, args: &mut Vec<XuguArgumentValue<'_>>) -> Result<IsNull, BoxDynError> {
100 if self.is_empty() {
101 args.push(XuguArgumentValue::Bin(Cow::Borrowed(b"\0")));
102 } else {
103 args.push(XuguArgumentValue::Bin(Cow::Owned(self)));
104 }
105
106 Ok(IsNull::No)
107 }
108
109 fn encode_by_ref(&self, args: &mut Vec<XuguArgumentValue<'_>>) -> Result<IsNull, BoxDynError> {
110 if self.is_empty() {
111 args.push(XuguArgumentValue::Bin(Cow::Borrowed(b"\0")));
112 } else {
113 args.push(XuguArgumentValue::Bin(Cow::Owned(self.clone())));
114 }
115
116 Ok(IsNull::No)
117 }
118}
119
120impl Decode<'_, Xugu> for Vec<u8> {
121 fn decode(value: XuguValueRef<'_>) -> Result<Self, BoxDynError> {
122 value.as_bytes().map(map_empty).map(ToOwned::to_owned)
123 }
124}
125
126fn map_empty(s: &[u8]) -> &[u8] {
128 if s == b"\0" {
129 return b"";
130 }
131 s
132}