diff --git a/pgx-macros/src/lib.rs b/pgx-macros/src/lib.rs index b1e96f7da..2a2df7529 100644 --- a/pgx-macros/src/lib.rs +++ b/pgx-macros/src/lib.rs @@ -781,7 +781,8 @@ fn impl_postgres_type(ast: DeriveInput) -> syn::Result de.bounds = bounds; lt_generics.params.insert(0, GenericParam::Lifetime(de)); stream.extend(quote! { - impl #lt_generics ::pgx::datum::Serializer<'de> for #name #generics { } + impl #generics ::pgx::datum::Serializer for #name #generics { } + impl #lt_generics ::pgx::datum::Deserializer<'de> for #name #generics { } }); } diff --git a/pgx-tests/src/tests/postgres_type_tests.rs b/pgx-tests/src/tests/postgres_type_tests.rs index f465e6bb3..43bd8f374 100644 --- a/pgx-tests/src/tests/postgres_type_tests.rs +++ b/pgx-tests/src/tests/postgres_type_tests.rs @@ -8,7 +8,7 @@ Use of this source code is governed by the MIT license that can be found in the */ use core::ffi::CStr; use pgx::prelude::*; -use pgx::{InOutFuncs, PgVarlena, PgVarlenaInOutFuncs, Serializer, StringInfo}; +use pgx::{Deserializer, InOutFuncs, PgVarlena, PgVarlenaInOutFuncs, Serializer, StringInfo}; use serde::{Deserialize, Serialize}; use std::io::Write; use std::str::FromStr; @@ -157,11 +157,13 @@ pub enum JsonEnumType { #[custom_serializer] pub struct CustomSerialized; -impl<'de> Serializer<'de> for CustomSerialized { +impl Serializer for CustomSerialized { fn to_writer(&self, mut writer: W) { writer.write(&[1]).expect("can't write"); } +} +impl<'de> Deserializer<'de> for CustomSerialized { fn from_slice(slice: &'de [u8]) -> Self { if slice != &[1] { panic!("wrong type") @@ -171,24 +173,6 @@ impl<'de> Serializer<'de> for CustomSerialized { } } -#[derive(Serialize, Deserialize, PostgresType)] -#[custom_serializer] -pub struct AnotherCustomSerialized; - -impl<'de> Serializer<'de> for AnotherCustomSerialized { - fn to_writer(&self, mut writer: W) { - writer.write(&[0]).expect("can't write"); - } - - fn from_slice(slice: &'de [u8]) -> Self { - if slice != &[0] { - panic!("wrong type") - } else { - AnotherCustomSerialized - } - } -} - #[cfg(any(test, feature = "pg_test"))] #[pgx::pg_schema] mod tests { @@ -196,8 +180,8 @@ mod tests { use crate as pgx_tests; use crate::tests::postgres_type_tests::{ - AnotherCustomSerialized, CustomSerialized, CustomTextFormatSerializedEnumType, - CustomTextFormatSerializedType, JsonEnumType, JsonType, VarlenaEnumType, VarlenaType, + CustomSerialized, CustomTextFormatSerializedEnumType, CustomTextFormatSerializedType, + JsonEnumType, JsonType, VarlenaEnumType, VarlenaType, }; use pgx::prelude::*; use pgx::PgVarlena; @@ -300,14 +284,4 @@ mod tests { ) .unwrap(); } - - #[pg_test(error = "wrong type")] - fn custom_serializer_wrong_type() { - let s = CustomSerialized; - let _ = Spi::get_one_with_args::( - r#"SELECT $1"#, - vec![(PgOid::Custom(CustomSerialized::type_oid()), s.into_datum())], - ) - .unwrap(); - } } diff --git a/pgx/src/datum/mod.rs b/pgx/src/datum/mod.rs index f875281a0..14654c8a3 100644 --- a/pgx/src/datum/mod.rs +++ b/pgx/src/datum/mod.rs @@ -65,10 +65,10 @@ use pgx_sql_entity_graph::RustSqlMapping; /// Implemented automatically by `#[derive(PostgresType)]` pub trait PostgresType {} -/// Serializing to and from datum +/// Serializing to datum /// /// Default implementation uses CBOR and Varlena -pub trait Serializer<'de>: Serialize + Deserialize<'de> { +pub trait Serializer: Serialize { /// Serializes the value to Datum /// /// Default implementation wraps the output of `Self::to_writer` into a Varlena @@ -93,7 +93,12 @@ pub trait Serializer<'de>: Serialize + Deserialize<'de> { fn to_writer(&self, writer: W) { serde_cbor::to_writer(writer, &self).expect("failed to encode as CBOR"); } +} +/// Deserializing from datum +/// +/// Default implementation uses CBOR and Varlena +pub trait Deserializer<'de>: Deserialize<'de> { /// Deserializes datum into a value /// /// Default implementation assumes datum to be a varlena and uses `Self::from_slice` @@ -121,7 +126,7 @@ pub trait Serializer<'de>: Serialize + Deserialize<'de> { let input = datum.cast_mut_ptr(); // this gets the varlena Datum copied into this memory context let varlena = pg_sys::pg_detoast_datum_copy(input as *mut pg_sys::varlena); - >::deserialize(varlena.into()) + >::deserialize(varlena.into()) }) } } @@ -134,9 +139,9 @@ pub trait Serializer<'de>: Serialize + Deserialize<'de> { } } -impl<'de, T> IntoDatum for T +impl IntoDatum for T where - T: PostgresType + Serializer<'de>, + T: PostgresType + Serializer, { fn into_datum(self) -> Option { Some(Serializer::serialize(&self)) @@ -149,7 +154,7 @@ where impl<'de, T> FromDatum for T where - T: PostgresType + Serializer<'de>, + T: PostgresType + Deserializer<'de>, { unsafe fn from_polymorphic_datum( datum: pg_sys::Datum, @@ -159,7 +164,7 @@ where if is_null { None } else { - Some(::deserialize(datum)) + Some(::deserialize(datum)) } }