diff --git a/sqlx-core/src/encode.rs b/sqlx-core/src/encode.rs index 1a149b6e87..ba9a1d40c9 100644 --- a/sqlx-core/src/encode.rs +++ b/sqlx-core/src/encode.rs @@ -200,3 +200,17 @@ where <&T as Encode>::size_hint(&self.as_ref()) } } + +#[macro_export] +macro_rules! forward_encode_impl { + ($for_type:ty, $forward_to:ty, $db:ident) => { + impl<'q> Encode<'q, $db> for $for_type { + fn encode_by_ref( + &self, + buf: &mut <$db as sqlx_core::database::Database>::ArgumentBuffer<'q>, + ) -> Result { + <$forward_to as Encode<$db>>::encode(self.as_ref(), buf) + } + } + }; +} diff --git a/sqlx-mysql/src/types/bytes.rs b/sqlx-mysql/src/types/bytes.rs index 023a8ee87a..649fb9dc0a 100644 --- a/sqlx-mysql/src/types/bytes.rs +++ b/sqlx-mysql/src/types/bytes.rs @@ -1,4 +1,6 @@ use std::borrow::Cow; +use std::rc::Rc; +use std::sync::Arc; use crate::decode::Decode; use crate::encode::{Encode, IsNull}; @@ -42,12 +44,6 @@ impl<'r> Decode<'r, MySql> for &'r [u8] { } } -impl Encode<'_, MySql> for Box<[u8]> { - fn encode_by_ref(&self, buf: &mut Vec) -> Result { - <&[u8] as Encode>::encode(self.as_ref(), buf) - } -} - impl Type for Vec { fn type_info() -> MySqlTypeInfo { <[u8] as Type>::type_info() @@ -70,8 +66,7 @@ impl Decode<'_, MySql> for Vec { } } -impl Encode<'_, MySql> for Cow<'_, [u8]> { - fn encode_by_ref(&self, buf: &mut Vec) -> Result { - <&[u8] as Encode>::encode(self.as_ref(), buf) - } -} +forward_encode_impl!(Arc<[u8]>, &[u8], MySql); +forward_encode_impl!(Rc<[u8]>, &[u8], MySql); +forward_encode_impl!(Box<[u8]>, &[u8], MySql); +forward_encode_impl!(Cow<'_, [u8]>, &[u8], MySql); diff --git a/sqlx-mysql/src/types/str.rs b/sqlx-mysql/src/types/str.rs index 4e2730577a..3a306fec45 100644 --- a/sqlx-mysql/src/types/str.rs +++ b/sqlx-mysql/src/types/str.rs @@ -1,4 +1,6 @@ use std::borrow::Cow; +use std::rc::Rc; +use std::sync::Arc; use crate::decode::Decode; use crate::encode::{Encode, IsNull}; @@ -47,12 +49,6 @@ impl<'r> Decode<'r, MySql> for &'r str { } } -impl Encode<'_, MySql> for Box { - fn encode_by_ref(&self, buf: &mut Vec) -> Result { - <&str as Encode>::encode(&**self, buf) - } -} - impl Type for String { fn type_info() -> MySqlTypeInfo { >::type_info() @@ -63,23 +59,14 @@ impl Type for String { } } -impl Encode<'_, MySql> for String { - fn encode_by_ref(&self, buf: &mut Vec) -> Result { - <&str as Encode>::encode(&**self, buf) - } -} - impl Decode<'_, MySql> for String { fn decode(value: MySqlValueRef<'_>) -> Result { <&str as Decode>::decode(value).map(ToOwned::to_owned) } } -impl Encode<'_, MySql> for Cow<'_, str> { - fn encode_by_ref(&self, buf: &mut Vec) -> Result { - match self { - Cow::Borrowed(str) => <&str as Encode>::encode(*str, buf), - Cow::Owned(str) => <&str as Encode>::encode(&**str, buf), - } - } -} +forward_encode_impl!(Arc, &str, MySql); +forward_encode_impl!(Rc, &str, MySql); +forward_encode_impl!(Cow<'_, str>, &str, MySql); +forward_encode_impl!(Box, &str, MySql); +forward_encode_impl!(String, &str, MySql); diff --git a/sqlx-postgres/src/types/bytes.rs b/sqlx-postgres/src/types/bytes.rs index 17b7ce9a3f..16cbc14a07 100644 --- a/sqlx-postgres/src/types/bytes.rs +++ b/sqlx-postgres/src/types/bytes.rs @@ -1,4 +1,6 @@ use std::borrow::Cow; +use std::rc::Rc; +use std::sync::Arc; use crate::decode::Decode; use crate::encode::{Encode, IsNull}; @@ -44,12 +46,6 @@ impl Encode<'_, Postgres> for &'_ [u8] { } } -impl Encode<'_, Postgres> for Box<[u8]> { - fn encode_by_ref(&self, buf: &mut PgArgumentBuffer) -> Result { - <&[u8] as Encode>::encode(self.as_ref(), buf) - } -} - impl Encode<'_, Postgres> for Vec { fn encode_by_ref(&self, buf: &mut PgArgumentBuffer) -> Result { <&[u8] as Encode>::encode(self, buf) @@ -104,8 +100,7 @@ impl Decode<'_, Postgres> for [u8; N] { } } -impl Encode<'_, Postgres> for Cow<'_, [u8]> { - fn encode_by_ref(&self, buf: &mut PgArgumentBuffer) -> Result { - <&[u8] as Encode>::encode(self.as_ref(), buf) - } -} +forward_encode_impl!(Arc<[u8]>, &[u8], Postgres); +forward_encode_impl!(Rc<[u8]>, &[u8], Postgres); +forward_encode_impl!(Box<[u8]>, &[u8], Postgres); +forward_encode_impl!(Cow<'_, [u8]>, &[u8], Postgres); diff --git a/sqlx-postgres/src/types/str.rs b/sqlx-postgres/src/types/str.rs index 8b9c33ef47..8ab0a37af9 100644 --- a/sqlx-postgres/src/types/str.rs +++ b/sqlx-postgres/src/types/str.rs @@ -5,6 +5,8 @@ use crate::types::array_compatible; use crate::types::Type; use crate::{PgArgumentBuffer, PgHasArrayType, PgTypeInfo, PgValueRef, Postgres}; use std::borrow::Cow; +use std::rc::Rc; +use std::sync::Arc; impl Type for str { fn type_info() -> PgTypeInfo { @@ -82,27 +84,6 @@ impl Encode<'_, Postgres> for &'_ str { } } -impl Encode<'_, Postgres> for Cow<'_, str> { - fn encode_by_ref(&self, buf: &mut PgArgumentBuffer) -> Result { - match self { - Cow::Borrowed(str) => <&str as Encode>::encode(*str, buf), - Cow::Owned(str) => <&str as Encode>::encode(&**str, buf), - } - } -} - -impl Encode<'_, Postgres> for Box { - fn encode_by_ref(&self, buf: &mut PgArgumentBuffer) -> Result { - <&str as Encode>::encode(&**self, buf) - } -} - -impl Encode<'_, Postgres> for String { - fn encode_by_ref(&self, buf: &mut PgArgumentBuffer) -> Result { - <&str as Encode>::encode(&**self, buf) - } -} - impl<'r> Decode<'r, Postgres> for &'r str { fn decode(value: PgValueRef<'r>) -> Result { value.as_str() @@ -114,3 +95,9 @@ impl Decode<'_, Postgres> for String { Ok(value.as_str()?.to_owned()) } } + +forward_encode_impl!(Arc, &str, Postgres); +forward_encode_impl!(Rc, &str, Postgres); +forward_encode_impl!(Cow<'_, str>, &str, Postgres); +forward_encode_impl!(Box, &str, Postgres); +forward_encode_impl!(String, &str, Postgres); diff --git a/sqlx-sqlite/src/types/bytes.rs b/sqlx-sqlite/src/types/bytes.rs index 48dffe0ae5..af625579e0 100644 --- a/sqlx-sqlite/src/types/bytes.rs +++ b/sqlx-sqlite/src/types/bytes.rs @@ -1,4 +1,6 @@ use std::borrow::Cow; +use std::rc::Rc; +use std::sync::Arc; use crate::decode::Decode; use crate::encode::{Encode, IsNull}; @@ -102,3 +104,21 @@ impl<'q> Encode<'q, Sqlite> for Cow<'q, [u8]> { Ok(IsNull::No) } } + +impl<'q> Encode<'q, Sqlite> for Arc<[u8]> { + fn encode_by_ref( + &self, + args: &mut Vec>, + ) -> Result { + as Encode<'_, Sqlite>>::encode(self.to_vec(), args) + } +} + +impl<'q> Encode<'q, Sqlite> for Rc<[u8]> { + fn encode_by_ref( + &self, + args: &mut Vec>, + ) -> Result { + as Encode<'_, Sqlite>>::encode(self.to_vec(), args) + } +} diff --git a/sqlx-sqlite/src/types/str.rs b/sqlx-sqlite/src/types/str.rs index 6c51fa1aff..8acd0d8798 100644 --- a/sqlx-sqlite/src/types/str.rs +++ b/sqlx-sqlite/src/types/str.rs @@ -1,4 +1,6 @@ use std::borrow::Cow; +use std::rc::Rc; +use std::sync::Arc; use crate::decode::Decode; use crate::encode::{Encode, IsNull}; @@ -94,3 +96,21 @@ impl<'q> Encode<'q, Sqlite> for Cow<'q, str> { Ok(IsNull::No) } } + +impl<'q> Encode<'q, Sqlite> for Arc { + fn encode_by_ref( + &self, + args: &mut Vec>, + ) -> Result { + >::encode(self.to_string(), args) + } +} + +impl<'q> Encode<'q, Sqlite> for Rc { + fn encode_by_ref( + &self, + args: &mut Vec>, + ) -> Result { + >::encode(self.to_string(), args) + } +} diff --git a/tests/mysql/types.rs b/tests/mysql/types.rs index df46cdfd8a..9686d41721 100644 --- a/tests/mysql/types.rs +++ b/tests/mysql/types.rs @@ -310,9 +310,13 @@ test_type!(test_rc>(MySql, "1" == Rc::new(1i32))); test_type!(test_box_str>(MySql, "'John'" == Box::::from("John"))); test_type!(test_cow_str>(MySql, "'Phil'" == Cow::<'static, str>::from("Phil"))); +test_type!(test_arc_str>(MySql, "'1234'" == Arc::::from("1234"))); +test_type!(test_rc_str>(MySql, "'5678'" == Rc::::from("5678"))); test_prepared_type!(test_box_slice>(MySql, "X'01020304'" == Box::<[u8]>::from([1,2,3,4]))); test_prepared_type!(test_cow_slice>(MySql, "X'01020304'" == Cow::<'static, [u8]>::from(&[1,2,3,4]))); +test_prepared_type!(test_arc_slice>(MySql, "X'01020304'" == Arc::<[u8]>::from([1,2,3,4]))); +test_prepared_type!(test_rc_slice>(MySql, "X'01020304'" == Rc::<[u8]>::from([1,2,3,4]))); #[sqlx_macros::test] async fn test_bits() -> anyhow::Result<()> { diff --git a/tests/postgres/types.rs b/tests/postgres/types.rs index 569fe585e1..8a9288ba75 100644 --- a/tests/postgres/types.rs +++ b/tests/postgres/types.rs @@ -704,9 +704,13 @@ test_type!(test_rc>(Postgres, "1::INT4" == Rc::new(1i32))); test_type!(test_box_str>(Postgres, "'John'::TEXT" == Box::::from("John"))); test_type!(test_cow_str>(Postgres, "'Phil'::TEXT" == Cow::<'static, str>::from("Phil"))); +test_type!(test_arc_str>(Postgres, "'1234'::TEXT" == Arc::::from("1234"))); +test_type!(test_rc_str>(Postgres, "'5678'::TEXT" == Rc::::from("5678"))); test_prepared_type!(test_box_slice>(Postgres, "'\\x01020304'::BYTEA" == Box::<[u8]>::from([1,2,3,4]))); test_prepared_type!(test_cow_slice>(Postgres, "'\\x01020304'::BYTEA" == Cow::<'static, [u8]>::from(&[1,2,3,4]))); +test_prepared_type!(test_arc_slice>(Postgres, "'\\x01020304'::BYTEA" == Arc::<[u8]>::from([1,2,3,4]))); +test_prepared_type!(test_rc_slice>(Postgres, "'\\x01020304'::BYTEA" == Rc::<[u8]>::from([1,2,3,4]))); #[sqlx_macros::test] async fn test_text_adapter() -> anyhow::Result<()> { diff --git a/tests/sqlite/types.rs b/tests/sqlite/types.rs index de949d5259..302ad54a61 100644 --- a/tests/sqlite/types.rs +++ b/tests/sqlite/types.rs @@ -219,9 +219,13 @@ test_type!(test_rc>(Sqlite, "1" == Rc::new(1i32))); test_type!(test_box_str>(Sqlite, "'John'" == Box::::from("John"))); test_type!(test_cow_str>(Sqlite, "'Phil'" == Cow::<'static, str>::from("Phil"))); +test_type!(test_arc_str>(Sqlite, "'1234'" == Arc::::from("1234"))); +test_type!(test_rc_str>(Sqlite, "'5678'" == Rc::::from("5678"))); test_type!(test_box_slice>(Sqlite, "X'01020304'" == Box::<[u8]>::from([1,2,3,4]))); test_type!(test_cow_slice>(Sqlite, "X'01020304'" == Cow::<'static, [u8]>::from(&[1,2,3,4]))); +test_type!(test_arc_slice>(Sqlite, "X'01020304'" == Arc::<[u8]>::from([1,2,3,4]))); +test_type!(test_rc_slice>(Sqlite, "X'01020304'" == Rc::<[u8]>::from([1,2,3,4]))); #[sqlx_macros::test] async fn test_text_adapter() -> anyhow::Result<()> {