Skip to content

Commit

Permalink
Make possible to have multiple encoders blanket impls
Browse files Browse the repository at this point in the history
  • Loading branch information
iduartgomez committed Oct 6, 2023
1 parent 6c44ebf commit 2ef4d95
Show file tree
Hide file tree
Showing 4 changed files with 119 additions and 103 deletions.
28 changes: 11 additions & 17 deletions rust-macros/src/contract_impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -201,13 +201,11 @@ pub(crate) fn contract_ffi_impl(
} else {
let contract_iface = impl_trait.gen_contract_iface(encoder);
let ffi = impl_trait.gen_extern_functions();
let encoder_impl = impl_trait.encoder_impl(encoder, &asoc_types);
let serialization_adapter = impl_trait.gen_serialization_adapter(&asoc_types);
let serialization_adapter = impl_trait.gen_serialization_adapter(&asoc_types, encoder);
quote! {
#input
#contract_iface
#ffi
#encoder_impl
#serialization_adapter
}
.into()
Expand All @@ -224,7 +222,11 @@ impl ImplTrait {
quote!(i64)
}

fn gen_serialization_adapter(&self, asoc_types: &AsocTypes) -> TokenStream {
fn gen_serialization_adapter(
&self,
asoc_types: &AsocTypes,
encoder: &syn::Path,
) -> TokenStream {
let type_name = &self.type_name;
let params = &asoc_types.params;
let delta = &asoc_types.delta;
Expand All @@ -234,20 +236,12 @@ impl ImplTrait {
type Parameters = #params;
type Delta = #delta;
type Summary = #summary;
}
}
}

fn encoder_impl(&self, encoder: &syn::Path, asoc_types: &AsocTypes) -> TokenStream {
let type_name = &self.type_name;
let params = &asoc_types.params;
let delta = &asoc_types.delta;
let summary = &asoc_types.summary;
quote! {
impl #encoder for #type_name {}
impl #encoder for #params {}
impl #encoder for #delta {}
impl #encoder for #summary {}
type SelfEncoder = #encoder<Self>;
type ParametersEncoder = #encoder<Self::Parameters>;
type DeltaEncoder = #encoder<Self::Delta>;
type SummaryEncoder = #encoder<Self::Summary>;
}
}
}

Expand Down
107 changes: 66 additions & 41 deletions rust/src/composers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,8 @@ impl RelatedContractsContainer {
}

pub mod from_bytes {
use serde::de::DeserializeOwned;

use crate::{
contract_interface::{
serialization::{Encoder, SerializationAdapter},
Expand All @@ -235,28 +237,33 @@ pub mod from_bytes {

use super::*;

// <<T as SerializationAdapter>::SelfEncoder as Encoder<T>>::Error
pub fn inner_validate_state<T, Child, Ctx>(
parameters: Parameters<'static>,
state: State<'static>,
related: RelatedContracts<'static>,
) -> Result<ValidateResult, ContractError>
where
T: ComposableContract + SerializationAdapter,
<T as ComposableContract>::Parameters: Encoder,
T: ComposableContract + SerializationAdapter + DeserializeOwned,
<T as SerializationAdapter>::Parameters: Into<<T as ComposableContract>::Parameters>,
for<'x> <T as ComposableContract>::Context: From<&'x Ctx>,
ContractError: From<<<T as SerializationAdapter>::Parameters as Encoder>::Error>,
ContractError: From<<T as Encoder>::Error>,
ContractError: From<
<<T as SerializationAdapter>::ParametersEncoder as Encoder<
<T as SerializationAdapter>::Parameters,
>>::Error,
>,
ContractError: From<<<T as SerializationAdapter>::SelfEncoder as Encoder<T>>::Error>,
Child: ComposableContract,
<Child as ComposableContract>::Parameters:
for<'x> From<&'x <T as ComposableContract>::Parameters>,
<Child as ComposableContract>::Context: for<'x> From<&'x T>,
Ctx: for<'x> From<&'x T>,
{
let typed_params: <T as ComposableContract>::Parameters =
<<T as SerializationAdapter>::Parameters as Encoder>::deserialize(parameters.as_ref())?
<<T as SerializationAdapter>::ParametersEncoder>::deserialize(parameters.as_ref())?
.into();
let typed_state: T = <T as Encoder>::deserialize(state.as_ref())?;
let typed_state: T =
<<T as SerializationAdapter>::SelfEncoder>::deserialize(state.as_ref())?;
let related_container = RelatedContractsContainer::from(related);
let ctx = Ctx::from(&typed_state);
match typed_state.verify::<Child, Ctx>(&typed_params, &ctx, &related_container)? {
Expand All @@ -275,22 +282,28 @@ pub mod from_bytes {
) -> Result<bool, ContractError>
where
T: ComposableContract + SerializationAdapter,
<T as SerializationAdapter>::Delta: Encoder,
<T as ComposableContract>::Parameters: Encoder,
<T as SerializationAdapter>::Parameters: Into<<T as ComposableContract>::Parameters>,
<T as SerializationAdapter>::Delta: Into<<T as ComposableContract>::Delta>,
ContractError: From<<<T as SerializationAdapter>::Parameters as Encoder>::Error>,
ContractError: From<<<T as SerializationAdapter>::Delta as Encoder>::Error>,
ContractError: From<
<<T as SerializationAdapter>::ParametersEncoder as Encoder<
<T as SerializationAdapter>::Parameters,
>>::Error,
>,
ContractError: From<
<<T as SerializationAdapter>::DeltaEncoder as Encoder<
<T as SerializationAdapter>::Delta,
>>::Error,
>,
Child: ComposableContract,
<Child as ComposableContract>::Parameters:
for<'x> From<&'x <T as ComposableContract>::Parameters>,
<Child as ComposableContract>::Delta: for<'x> From<&'x <T as ComposableContract>::Delta>,
{
let typed_params =
<<T as SerializationAdapter>::Parameters as Encoder>::deserialize(parameters.as_ref())?
<<T as SerializationAdapter>::ParametersEncoder>::deserialize(parameters.as_ref())?
.into();
let typed_delta =
<<T as SerializationAdapter>::Delta as Encoder>::deserialize(delta.as_ref())?.into();
<<T as SerializationAdapter>::DeltaEncoder>::deserialize(delta.as_ref())?.into();
<T as ComposableContract>::verify_delta::<Child>(&typed_params, &typed_delta)
}

Expand All @@ -301,31 +314,38 @@ pub mod from_bytes {
) -> Result<UpdateModification<'static>, ContractError>
where
T: ComposableContract + SerializationAdapter,
<T as SerializationAdapter>::Delta: Encoder,
<T as ComposableContract>::Parameters: Encoder,
<T as SerializationAdapter>::Parameters: Into<<T as ComposableContract>::Parameters>,
<T as SerializationAdapter>::Delta: Into<<T as ComposableContract>::Delta>,
ContractError: From<<<T as SerializationAdapter>::Parameters as Encoder>::Error>,
ContractError: From<<<T as SerializationAdapter>::Delta as Encoder>::Error>,
ContractError: From<<T as Encoder>::Error>,
ContractError: From<
<<T as SerializationAdapter>::ParametersEncoder as Encoder<
<T as SerializationAdapter>::Parameters,
>>::Error,
>,
ContractError: From<
<<T as SerializationAdapter>::DeltaEncoder as Encoder<
<T as SerializationAdapter>::Delta,
>>::Error,
>,
ContractError: From<<<T as SerializationAdapter>::SelfEncoder as Encoder<T>>::Error>,
Child: ComposableContract,
<Child as ComposableContract>::Parameters:
for<'x> From<&'x <T as ComposableContract>::Parameters>,
<Child as ComposableContract>::Delta: for<'x> From<&'x <T as ComposableContract>::Delta>,
{
let typed_params =
<<T as SerializationAdapter>::Parameters as Encoder>::deserialize(parameters.as_ref())?
<<T as SerializationAdapter>::ParametersEncoder>::deserialize(parameters.as_ref())?
.into();
let mut typed_state: T = <T as Encoder>::deserialize(state.as_ref())?;
let mut typed_state: T =
<<T as SerializationAdapter>::SelfEncoder>::deserialize(state.as_ref())?;
let self_updates = UpdateData::get_self_states(&data);
let related_container = RelatedContractsContainer::from(data);
for (state, delta) in self_updates {
let state = state
.map(|s| <T as Encoder>::deserialize(s.as_ref()))
.map(|s| <<T as SerializationAdapter>::SelfEncoder>::deserialize(s.as_ref()))
.transpose()?;
let delta = delta
.map(|d| {
<<T as SerializationAdapter>::Delta as Encoder>::deserialize(d.as_ref())
<<T as SerializationAdapter>::DeltaEncoder>::deserialize(d.as_ref())
.map(Into::into)
})
.transpose()?;
Expand All @@ -338,7 +358,7 @@ pub mod from_bytes {
MergeResult::Error(err) => return Err(err),
}
}
let encoded = typed_state.serialize()?;
let encoded = <<T as SerializationAdapter>::SelfEncoder>::serialize(&typed_state)?;
Ok(UpdateModification::valid(encoded.into()))
}

Expand All @@ -351,16 +371,18 @@ pub mod from_bytes {
<T as SerializationAdapter>::Parameters: Into<<T as ComposableContract>::Parameters>,
<T as ComposableContract>::Summary:
for<'x> From<&'x T> + ComposableSummary<<T as ComposableContract>::Summary>,
ContractError: From<<<T as SerializationAdapter>::Parameters as Encoder>::Error>,
ContractError: From<<T as Encoder>::Error>,
// Child: ComposableContract,
// <Child as ComposableContract>::Parameters:
// for<'x> From<&'x <T as ComposableContract>::Parameters>,
ContractError: From<
<<T as SerializationAdapter>::ParametersEncoder as Encoder<
<T as SerializationAdapter>::Parameters,
>>::Error,
>,
ContractError: From<<<T as SerializationAdapter>::SelfEncoder as Encoder<T>>::Error>,
{
let typed_params =
<<T as SerializationAdapter>::Parameters as Encoder>::deserialize(parameters.as_ref())?
<<T as SerializationAdapter>::ParametersEncoder>::deserialize(parameters.as_ref())?
.into();
let typed_state: T = <T as Encoder>::deserialize(state.as_ref())?;
let typed_state: T =
<<T as SerializationAdapter>::SelfEncoder>::deserialize(state.as_ref())?;
let mut summary = <<T as ComposableContract>::Summary>::from(&typed_state);
typed_state.summarize(&typed_params, &mut summary)?;
Ok(summary)
Expand All @@ -375,22 +397,25 @@ pub mod from_bytes {
T: ComposableContract + SerializationAdapter,
<T as SerializationAdapter>::Parameters: Into<<T as ComposableContract>::Parameters>,
<T as SerializationAdapter>::Summary: Into<<T as ComposableContract>::Summary>,
ContractError: From<<T as Encoder>::Error>,
ContractError: From<<<T as SerializationAdapter>::Parameters as Encoder>::Error>,
ContractError: From<<<T as SerializationAdapter>::Summary as Encoder>::Error>,
// Child: ComposableContract,
// <Child as ComposableContract>::Parameters:
// for<'x> From<&'x <T as ComposableContract>::Parameters>,
// <Child as ComposableContract>::Summary:
// for<'x> From<&'x <T as ComposableContract>::Summary>,
ContractError: From<
<<T as SerializationAdapter>::ParametersEncoder as Encoder<
<T as SerializationAdapter>::Parameters,
>>::Error,
>,
ContractError: From<
<<T as SerializationAdapter>::SummaryEncoder as Encoder<
<T as SerializationAdapter>::Summary,
>>::Error,
>,
ContractError: From<<<T as SerializationAdapter>::SelfEncoder as Encoder<T>>::Error>,
{
let typed_params =
<<T as SerializationAdapter>::Parameters as Encoder>::deserialize(parameters.as_ref())?
<<T as SerializationAdapter>::ParametersEncoder>::deserialize(parameters.as_ref())?
.into();
let typed_state: T = <T as Encoder>::deserialize(state.as_ref())?;
let typed_state: T =
<<T as SerializationAdapter>::SelfEncoder>::deserialize(state.as_ref())?;
let typed_summary =
<<T as SerializationAdapter>::Summary as Encoder>::deserialize(summary.as_ref())?
.into();
<<T as SerializationAdapter>::SummaryEncoder>::deserialize(summary.as_ref())?.into();
typed_state.delta(&typed_params, &typed_summary)
}
}
83 changes: 39 additions & 44 deletions rust/src/contract_interface.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1593,34 +1593,48 @@ mod test {

pub(crate) mod serialization {
//! Helper types to interaction between wasm and host boundaries.
use std::marker::PhantomData;

use serde::de::DeserializeOwned;

use super::*;

/// A contract state and it's associated types which can be encoded and decoded
/// via an specific encoder.
pub trait SerializationAdapter: Encoder {
type Parameters: Encoder;
type Delta: Encoder;
type Summary: Encoder;
}

pub trait Encoder
pub trait SerializationAdapter
where
Self: Sized,
{
type Parameters;
type Delta;
type Summary;

type SelfEncoder: Encoder<Self>;
type ParametersEncoder: Encoder<Self::Parameters>;
type DeltaEncoder: Encoder<Self::Delta>;
type SummaryEncoder: Encoder<Self::Summary>;
}

pub trait Encoder<T> {
type Error: Into<ContractError>;
fn deserialize(bytes: &[u8]) -> Result<Self, Self::Error>;
fn serialize(&self) -> Result<Vec<u8>, Self::Error>;
fn deserialize(bytes: &[u8]) -> Result<T, Self::Error>;
fn serialize(value: &T) -> Result<Vec<u8>, Self::Error>;
}

pub trait JsonEncoder: Serialize + DeserializeOwned {
fn deserialize(_bytes: &[u8]) -> Result<Self, serde_json::Error> {
todo!()
pub struct JsonEncoder<T>(PhantomData<T>);

impl<T> Encoder<T> for JsonEncoder<T>
where
T: DeserializeOwned + Serialize,
{
type Error = serde_json::Error;

fn deserialize(bytes: &[u8]) -> Result<T, Self::Error> {
serde_json::from_slice(bytes)
}

fn serialize(&self) -> Result<Vec<u8>, serde_json::Error> {
todo!()
fn serialize(value: &T) -> Result<Vec<u8>, Self::Error> {
serde_json::to_vec(value)
}
}

Expand All @@ -1630,13 +1644,20 @@ pub(crate) mod serialization {
}
}

pub trait BincodeEncoder: Serialize + DeserializeOwned {
fn deserialize(bytes: &[u8]) -> Result<Self, bincode::Error> {
pub struct BincodeEncoder<T>(PhantomData<T>);

impl<T> Encoder<T> for BincodeEncoder<T>
where
T: DeserializeOwned + Serialize,
{
type Error = bincode::Error;

fn deserialize(bytes: &[u8]) -> Result<T, Self::Error> {
bincode::deserialize(bytes)
}

fn serialize(&self) -> Result<Vec<u8>, bincode::Error> {
bincode::serialize(self)
fn serialize(value: &T) -> Result<Vec<u8>, Self::Error> {
bincode::serialize(value)
}
}

Expand All @@ -1645,30 +1666,4 @@ pub(crate) mod serialization {
ContractError::Deser(format!("{value}"))
}
}

impl<C> Encoder for C
where
C: BincodeEncoder,
{
type Error = bincode::Error;
fn deserialize(bytes: &[u8]) -> Result<C, bincode::Error> {
<C as BincodeEncoder>::deserialize(bytes)
}
fn serialize(&self) -> Result<Vec<u8>, bincode::Error> {
<C as BincodeEncoder>::serialize(self)
}
}

// impl<C> Encoder for C
// where
// C: JsonEncoder,
// {
// type Error = bincode::Error;
// fn deserialize(bytes: &[u8]) -> Result<C, bincode::Error> {
// <C as BincodeEncoder>::deserialize(bytes)
// }
// fn serialize(&self) -> Result<Vec<u8>, bincode::Error> {
// <C as BincodeEncoder>::serialize(self)
// }
// }
}
4 changes: 3 additions & 1 deletion rust/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,9 @@ pub mod time;
/// Locutus stdlib prelude.
pub mod prelude {
pub use crate::code_hash::*;
pub use crate::contract_interface::serialization::{BincodeEncoder, SerializationAdapter};
pub use crate::contract_interface::serialization::{
BincodeEncoder, Encoder, JsonEncoder, SerializationAdapter,
};
pub use crate::contract_interface::wasm_interface::*;
pub use crate::contract_interface::*;
pub use crate::delegate_interface::wasm_interface::*;
Expand Down

0 comments on commit 2ef4d95

Please sign in to comment.