Skip to content

Commit 60f67db

Browse files
authored
feat: implement Encode, Decode, Type for Arc<str> and Arc<[u8]> (and Rc equivalents) (#3675)
* implement Encode, Decode, Type for Arc<str> and Arc<[u8]> (and Rc equivalents) * sqlx-sqlite: Remove clone in Encode impl * sqlx-sqlite: Remove unnecessary impls
1 parent 0f891a3 commit 60f67db

File tree

10 files changed

+93
-63
lines changed

10 files changed

+93
-63
lines changed

sqlx-core/src/encode.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,3 +200,17 @@ where
200200
<&T as Encode<DB>>::size_hint(&self.as_ref())
201201
}
202202
}
203+
204+
#[macro_export]
205+
macro_rules! forward_encode_impl {
206+
($for_type:ty, $forward_to:ty, $db:ident) => {
207+
impl<'q> Encode<'q, $db> for $for_type {
208+
fn encode_by_ref(
209+
&self,
210+
buf: &mut <$db as sqlx_core::database::Database>::ArgumentBuffer<'q>,
211+
) -> Result<IsNull, BoxDynError> {
212+
<$forward_to as Encode<$db>>::encode(self.as_ref(), buf)
213+
}
214+
}
215+
};
216+
}

sqlx-mysql/src/types/bytes.rs

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
use std::borrow::Cow;
2+
use std::rc::Rc;
3+
use std::sync::Arc;
24

35
use crate::decode::Decode;
46
use crate::encode::{Encode, IsNull};
@@ -42,12 +44,6 @@ impl<'r> Decode<'r, MySql> for &'r [u8] {
4244
}
4345
}
4446

45-
impl Encode<'_, MySql> for Box<[u8]> {
46-
fn encode_by_ref(&self, buf: &mut Vec<u8>) -> Result<IsNull, BoxDynError> {
47-
<&[u8] as Encode<MySql>>::encode(self.as_ref(), buf)
48-
}
49-
}
50-
5147
impl Type<MySql> for Vec<u8> {
5248
fn type_info() -> MySqlTypeInfo {
5349
<[u8] as Type<MySql>>::type_info()
@@ -70,8 +66,7 @@ impl Decode<'_, MySql> for Vec<u8> {
7066
}
7167
}
7268

73-
impl Encode<'_, MySql> for Cow<'_, [u8]> {
74-
fn encode_by_ref(&self, buf: &mut Vec<u8>) -> Result<IsNull, BoxDynError> {
75-
<&[u8] as Encode<MySql>>::encode(self.as_ref(), buf)
76-
}
77-
}
69+
forward_encode_impl!(Arc<[u8]>, &[u8], MySql);
70+
forward_encode_impl!(Rc<[u8]>, &[u8], MySql);
71+
forward_encode_impl!(Box<[u8]>, &[u8], MySql);
72+
forward_encode_impl!(Cow<'_, [u8]>, &[u8], MySql);

sqlx-mysql/src/types/str.rs

Lines changed: 7 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
use std::borrow::Cow;
2+
use std::rc::Rc;
3+
use std::sync::Arc;
24

35
use crate::decode::Decode;
46
use crate::encode::{Encode, IsNull};
@@ -47,12 +49,6 @@ impl<'r> Decode<'r, MySql> for &'r str {
4749
}
4850
}
4951

50-
impl Encode<'_, MySql> for Box<str> {
51-
fn encode_by_ref(&self, buf: &mut Vec<u8>) -> Result<IsNull, BoxDynError> {
52-
<&str as Encode<MySql>>::encode(&**self, buf)
53-
}
54-
}
55-
5652
impl Type<MySql> for String {
5753
fn type_info() -> MySqlTypeInfo {
5854
<str as Type<MySql>>::type_info()
@@ -63,23 +59,14 @@ impl Type<MySql> for String {
6359
}
6460
}
6561

66-
impl Encode<'_, MySql> for String {
67-
fn encode_by_ref(&self, buf: &mut Vec<u8>) -> Result<IsNull, BoxDynError> {
68-
<&str as Encode<MySql>>::encode(&**self, buf)
69-
}
70-
}
71-
7262
impl Decode<'_, MySql> for String {
7363
fn decode(value: MySqlValueRef<'_>) -> Result<Self, BoxDynError> {
7464
<&str as Decode<MySql>>::decode(value).map(ToOwned::to_owned)
7565
}
7666
}
7767

78-
impl Encode<'_, MySql> for Cow<'_, str> {
79-
fn encode_by_ref(&self, buf: &mut Vec<u8>) -> Result<IsNull, BoxDynError> {
80-
match self {
81-
Cow::Borrowed(str) => <&str as Encode<MySql>>::encode(*str, buf),
82-
Cow::Owned(str) => <&str as Encode<MySql>>::encode(&**str, buf),
83-
}
84-
}
85-
}
68+
forward_encode_impl!(Arc<str>, &str, MySql);
69+
forward_encode_impl!(Rc<str>, &str, MySql);
70+
forward_encode_impl!(Cow<'_, str>, &str, MySql);
71+
forward_encode_impl!(Box<str>, &str, MySql);
72+
forward_encode_impl!(String, &str, MySql);

sqlx-postgres/src/types/bytes.rs

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
use std::borrow::Cow;
2+
use std::rc::Rc;
3+
use std::sync::Arc;
24

35
use crate::decode::Decode;
46
use crate::encode::{Encode, IsNull};
@@ -44,12 +46,6 @@ impl Encode<'_, Postgres> for &'_ [u8] {
4446
}
4547
}
4648

47-
impl Encode<'_, Postgres> for Box<[u8]> {
48-
fn encode_by_ref(&self, buf: &mut PgArgumentBuffer) -> Result<IsNull, BoxDynError> {
49-
<&[u8] as Encode<Postgres>>::encode(self.as_ref(), buf)
50-
}
51-
}
52-
5349
impl Encode<'_, Postgres> for Vec<u8> {
5450
fn encode_by_ref(&self, buf: &mut PgArgumentBuffer) -> Result<IsNull, BoxDynError> {
5551
<&[u8] as Encode<Postgres>>::encode(self, buf)
@@ -104,8 +100,7 @@ impl<const N: usize> Decode<'_, Postgres> for [u8; N] {
104100
}
105101
}
106102

107-
impl Encode<'_, Postgres> for Cow<'_, [u8]> {
108-
fn encode_by_ref(&self, buf: &mut PgArgumentBuffer) -> Result<IsNull, BoxDynError> {
109-
<&[u8] as Encode<Postgres>>::encode(self.as_ref(), buf)
110-
}
111-
}
103+
forward_encode_impl!(Arc<[u8]>, &[u8], Postgres);
104+
forward_encode_impl!(Rc<[u8]>, &[u8], Postgres);
105+
forward_encode_impl!(Box<[u8]>, &[u8], Postgres);
106+
forward_encode_impl!(Cow<'_, [u8]>, &[u8], Postgres);

sqlx-postgres/src/types/str.rs

Lines changed: 8 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ use crate::types::array_compatible;
55
use crate::types::Type;
66
use crate::{PgArgumentBuffer, PgHasArrayType, PgTypeInfo, PgValueRef, Postgres};
77
use std::borrow::Cow;
8+
use std::rc::Rc;
9+
use std::sync::Arc;
810

911
impl Type<Postgres> for str {
1012
fn type_info() -> PgTypeInfo {
@@ -82,27 +84,6 @@ impl Encode<'_, Postgres> for &'_ str {
8284
}
8385
}
8486

85-
impl Encode<'_, Postgres> for Cow<'_, str> {
86-
fn encode_by_ref(&self, buf: &mut PgArgumentBuffer) -> Result<IsNull, BoxDynError> {
87-
match self {
88-
Cow::Borrowed(str) => <&str as Encode<Postgres>>::encode(*str, buf),
89-
Cow::Owned(str) => <&str as Encode<Postgres>>::encode(&**str, buf),
90-
}
91-
}
92-
}
93-
94-
impl Encode<'_, Postgres> for Box<str> {
95-
fn encode_by_ref(&self, buf: &mut PgArgumentBuffer) -> Result<IsNull, BoxDynError> {
96-
<&str as Encode<Postgres>>::encode(&**self, buf)
97-
}
98-
}
99-
100-
impl Encode<'_, Postgres> for String {
101-
fn encode_by_ref(&self, buf: &mut PgArgumentBuffer) -> Result<IsNull, BoxDynError> {
102-
<&str as Encode<Postgres>>::encode(&**self, buf)
103-
}
104-
}
105-
10687
impl<'r> Decode<'r, Postgres> for &'r str {
10788
fn decode(value: PgValueRef<'r>) -> Result<Self, BoxDynError> {
10889
value.as_str()
@@ -114,3 +95,9 @@ impl Decode<'_, Postgres> for String {
11495
Ok(value.as_str()?.to_owned())
11596
}
11697
}
98+
99+
forward_encode_impl!(Arc<str>, &str, Postgres);
100+
forward_encode_impl!(Rc<str>, &str, Postgres);
101+
forward_encode_impl!(Cow<'_, str>, &str, Postgres);
102+
forward_encode_impl!(Box<str>, &str, Postgres);
103+
forward_encode_impl!(String, &str, Postgres);

sqlx-sqlite/src/types/bytes.rs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
use std::borrow::Cow;
2+
use std::rc::Rc;
3+
use std::sync::Arc;
24

35
use crate::decode::Decode;
46
use crate::encode::{Encode, IsNull};
@@ -102,3 +104,21 @@ impl<'q> Encode<'q, Sqlite> for Cow<'q, [u8]> {
102104
Ok(IsNull::No)
103105
}
104106
}
107+
108+
impl<'q> Encode<'q, Sqlite> for Arc<[u8]> {
109+
fn encode_by_ref(
110+
&self,
111+
args: &mut Vec<SqliteArgumentValue<'q>>,
112+
) -> Result<IsNull, BoxDynError> {
113+
<Vec<u8> as Encode<'_, Sqlite>>::encode(self.to_vec(), args)
114+
}
115+
}
116+
117+
impl<'q> Encode<'q, Sqlite> for Rc<[u8]> {
118+
fn encode_by_ref(
119+
&self,
120+
args: &mut Vec<SqliteArgumentValue<'q>>,
121+
) -> Result<IsNull, BoxDynError> {
122+
<Vec<u8> as Encode<'_, Sqlite>>::encode(self.to_vec(), args)
123+
}
124+
}

sqlx-sqlite/src/types/str.rs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
use std::borrow::Cow;
2+
use std::rc::Rc;
3+
use std::sync::Arc;
24

35
use crate::decode::Decode;
46
use crate::encode::{Encode, IsNull};
@@ -94,3 +96,21 @@ impl<'q> Encode<'q, Sqlite> for Cow<'q, str> {
9496
Ok(IsNull::No)
9597
}
9698
}
99+
100+
impl<'q> Encode<'q, Sqlite> for Arc<str> {
101+
fn encode_by_ref(
102+
&self,
103+
args: &mut Vec<SqliteArgumentValue<'q>>,
104+
) -> Result<IsNull, BoxDynError> {
105+
<String as Encode<'_, Sqlite>>::encode(self.to_string(), args)
106+
}
107+
}
108+
109+
impl<'q> Encode<'q, Sqlite> for Rc<str> {
110+
fn encode_by_ref(
111+
&self,
112+
args: &mut Vec<SqliteArgumentValue<'q>>,
113+
) -> Result<IsNull, BoxDynError> {
114+
<String as Encode<'_, Sqlite>>::encode(self.to_string(), args)
115+
}
116+
}

tests/mysql/types.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -310,9 +310,13 @@ test_type!(test_rc<Rc<i32>>(MySql, "1" == Rc::new(1i32)));
310310

311311
test_type!(test_box_str<Box<str>>(MySql, "'John'" == Box::<str>::from("John")));
312312
test_type!(test_cow_str<Cow<'_, str>>(MySql, "'Phil'" == Cow::<'static, str>::from("Phil")));
313+
test_type!(test_arc_str<Arc<str>>(MySql, "'1234'" == Arc::<str>::from("1234")));
314+
test_type!(test_rc_str<Rc<str>>(MySql, "'5678'" == Rc::<str>::from("5678")));
313315

314316
test_prepared_type!(test_box_slice<Box<[u8]>>(MySql, "X'01020304'" == Box::<[u8]>::from([1,2,3,4])));
315317
test_prepared_type!(test_cow_slice<Cow<'_, [u8]>>(MySql, "X'01020304'" == Cow::<'static, [u8]>::from(&[1,2,3,4])));
318+
test_prepared_type!(test_arc_slice<Arc<[u8]>>(MySql, "X'01020304'" == Arc::<[u8]>::from([1,2,3,4])));
319+
test_prepared_type!(test_rc_slice<Rc<[u8]>>(MySql, "X'01020304'" == Rc::<[u8]>::from([1,2,3,4])));
316320

317321
#[sqlx_macros::test]
318322
async fn test_bits() -> anyhow::Result<()> {

tests/postgres/types.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -704,9 +704,13 @@ test_type!(test_rc<Rc<i32>>(Postgres, "1::INT4" == Rc::new(1i32)));
704704

705705
test_type!(test_box_str<Box<str>>(Postgres, "'John'::TEXT" == Box::<str>::from("John")));
706706
test_type!(test_cow_str<Cow<'_, str>>(Postgres, "'Phil'::TEXT" == Cow::<'static, str>::from("Phil")));
707+
test_type!(test_arc_str<Arc<str>>(Postgres, "'1234'::TEXT" == Arc::<str>::from("1234")));
708+
test_type!(test_rc_str<Rc<str>>(Postgres, "'5678'::TEXT" == Rc::<str>::from("5678")));
707709

708710
test_prepared_type!(test_box_slice<Box<[u8]>>(Postgres, "'\\x01020304'::BYTEA" == Box::<[u8]>::from([1,2,3,4])));
709711
test_prepared_type!(test_cow_slice<Cow<'_, [u8]>>(Postgres, "'\\x01020304'::BYTEA" == Cow::<'static, [u8]>::from(&[1,2,3,4])));
712+
test_prepared_type!(test_arc_slice<Arc<[u8]>>(Postgres, "'\\x01020304'::BYTEA" == Arc::<[u8]>::from([1,2,3,4])));
713+
test_prepared_type!(test_rc_slice<Rc<[u8]>>(Postgres, "'\\x01020304'::BYTEA" == Rc::<[u8]>::from([1,2,3,4])));
710714

711715
#[sqlx_macros::test]
712716
async fn test_text_adapter() -> anyhow::Result<()> {

tests/sqlite/types.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -219,9 +219,13 @@ test_type!(test_rc<Rc<i32>>(Sqlite, "1" == Rc::new(1i32)));
219219

220220
test_type!(test_box_str<Box<str>>(Sqlite, "'John'" == Box::<str>::from("John")));
221221
test_type!(test_cow_str<Cow<'_, str>>(Sqlite, "'Phil'" == Cow::<'static, str>::from("Phil")));
222+
test_type!(test_arc_str<Arc<str>>(Sqlite, "'1234'" == Arc::<str>::from("1234")));
223+
test_type!(test_rc_str<Rc<str>>(Sqlite, "'5678'" == Rc::<str>::from("5678")));
222224

223225
test_type!(test_box_slice<Box<[u8]>>(Sqlite, "X'01020304'" == Box::<[u8]>::from([1,2,3,4])));
224226
test_type!(test_cow_slice<Cow<'_, [u8]>>(Sqlite, "X'01020304'" == Cow::<'static, [u8]>::from(&[1,2,3,4])));
227+
test_type!(test_arc_slice<Arc<[u8]>>(Sqlite, "X'01020304'" == Arc::<[u8]>::from([1,2,3,4])));
228+
test_type!(test_rc_slice<Rc<[u8]>>(Sqlite, "X'01020304'" == Rc::<[u8]>::from([1,2,3,4])));
225229

226230
#[sqlx_macros::test]
227231
async fn test_text_adapter() -> anyhow::Result<()> {

0 commit comments

Comments
 (0)