sqlx_postgres/types/
bytes.rs1use crate::decode::Decode;
2use crate::encode::{Encode, IsNull};
3use crate::error::BoxDynError;
4use crate::types::Type;
5use crate::{PgArgumentBuffer, PgHasArrayType, PgTypeInfo, PgValueFormat, PgValueRef, Postgres};
6
7impl PgHasArrayType for u8 {
8 fn array_type_info() -> PgTypeInfo {
9 PgTypeInfo::BYTEA
10 }
11}
12
13impl PgHasArrayType for &'_ [u8] {
14 fn array_type_info() -> PgTypeInfo {
15 PgTypeInfo::BYTEA_ARRAY
16 }
17}
18
19impl<const N: usize> PgHasArrayType for &'_ [u8; N] {
20 fn array_type_info() -> PgTypeInfo {
21 PgTypeInfo::BYTEA_ARRAY
22 }
23}
24
25impl PgHasArrayType for Box<[u8]> {
26 fn array_type_info() -> PgTypeInfo {
27 <[&[u8]] as Type<Postgres>>::type_info()
28 }
29}
30
31impl PgHasArrayType for Vec<u8> {
32 fn array_type_info() -> PgTypeInfo {
33 <[&[u8]] as Type<Postgres>>::type_info()
34 }
35}
36
37impl<const N: usize> PgHasArrayType for [u8; N] {
38 fn array_type_info() -> PgTypeInfo {
39 <[&[u8]] as Type<Postgres>>::type_info()
40 }
41}
42
43impl Encode<'_, Postgres> for &'_ [u8] {
44 fn encode_by_ref(&self, buf: &mut PgArgumentBuffer) -> IsNull {
45 buf.extend_from_slice(self);
46
47 IsNull::No
48 }
49}
50
51impl Encode<'_, Postgres> for Box<[u8]> {
52 fn encode_by_ref(&self, buf: &mut PgArgumentBuffer) -> IsNull {
53 <&[u8] as Encode<Postgres>>::encode(self.as_ref(), buf)
54 }
55}
56
57impl Encode<'_, Postgres> for Vec<u8> {
58 fn encode_by_ref(&self, buf: &mut PgArgumentBuffer) -> IsNull {
59 <&[u8] as Encode<Postgres>>::encode(self, buf)
60 }
61}
62
63impl<const N: usize> Encode<'_, Postgres> for [u8; N] {
64 fn encode_by_ref(&self, buf: &mut PgArgumentBuffer) -> IsNull {
65 <&[u8] as Encode<Postgres>>::encode(self.as_slice(), buf)
66 }
67}
68
69impl<'r> Decode<'r, Postgres> for &'r [u8] {
70 fn decode(value: PgValueRef<'r>) -> Result<Self, BoxDynError> {
71 match value.format() {
72 PgValueFormat::Binary => value.as_bytes(),
73 PgValueFormat::Text => {
74 Err("unsupported decode to `&[u8]` of BYTEA in a simple query; use a prepared query or decode to `Vec<u8>`".into())
75 }
76 }
77 }
78}
79
80fn text_hex_decode_input(value: PgValueRef<'_>) -> Result<&[u8], BoxDynError> {
81 value
83 .as_bytes()?
84 .strip_prefix(b"\\x")
85 .ok_or("text does not start with \\x")
86 .map_err(Into::into)
87}
88
89impl Decode<'_, Postgres> for Box<[u8]> {
90 fn decode(value: PgValueRef<'_>) -> Result<Self, BoxDynError> {
91 Ok(match value.format() {
92 PgValueFormat::Binary => Box::from(value.as_bytes()?),
93 PgValueFormat::Text => Box::from(hex::decode(text_hex_decode_input(value)?)?),
94 })
95 }
96}
97
98impl Decode<'_, Postgres> for Vec<u8> {
99 fn decode(value: PgValueRef<'_>) -> Result<Self, BoxDynError> {
100 Ok(match value.format() {
101 PgValueFormat::Binary => value.as_bytes()?.to_owned(),
102 PgValueFormat::Text => hex::decode(text_hex_decode_input(value)?)?,
103 })
104 }
105}
106
107impl<const N: usize> Decode<'_, Postgres> for [u8; N] {
108 fn decode(value: PgValueRef<'_>) -> Result<Self, BoxDynError> {
109 let mut bytes = [0u8; N];
110 match value.format() {
111 PgValueFormat::Binary => {
112 bytes = value.as_bytes()?.try_into()?;
113 }
114 PgValueFormat::Text => hex::decode_to_slice(text_hex_decode_input(value)?, &mut bytes)?,
115 };
116 Ok(bytes)
117 }
118}