From e0b13b191ce7b8425d270a12dde60bf33b9949cf Mon Sep 17 00:00:00 2001 From: Romain Ruetschi Date: Wed, 31 Jul 2024 17:55:37 +0200 Subject: [PATCH] Add `borsh` and `parity-scale-codec` features with corresponding derivations --- proto/Cargo.toml | 13 +++++ proto/src/google/protobuf/any.rs | 88 ++++++++++++++++++++++++++++++++ 2 files changed, 101 insertions(+) diff --git a/proto/Cargo.toml b/proto/Cargo.toml index b393415f1..107e32d54 100644 --- a/proto/Cargo.toml +++ b/proto/Cargo.toml @@ -15,9 +15,12 @@ description = """ [features] default = [] +std = [] grpc = ["grpc-server"] grpc-server = ["dep:tonic"] json-schema = ["dep:schemars"] +borsh = ["dep:borsh"] +parity-scale-codec = ["dep:parity-scale-codec", "dep:scale-info"] [package.metadata.docs.rs] all-features = true @@ -32,7 +35,17 @@ subtle-encoding = { version = "0.5", default-features = false, features = ["hex" time = { version = "0.3", default-features = false, features = ["macros", "parsing"] } flex-error = { version = "0.4.4", default-features = false } tonic = { version = "0.12", optional = true } + +## Optional: enabled by the `json-schema` feature schemars = { version = "0.8", optional = true } +## Optional: enabled by the `borsh` feature +## For borsh encode or decode, needs to track `anchor-lang` and `near-sdk-rs` borsh version +borsh = { version = "1", default-features = false, features = ["derive"], optional = true } + +## Optional: enabled by the `parity-scale-codec` feature +parity-scale-codec = { version = "3.0.0", default-features = false, features = ["full"], optional = true } +scale-info = { version = "2.1.2", default-features = false, features = ["derive"], optional = true } + [dev-dependencies] serde_json = { version = "1.0", default-features = false, features = ["alloc"] } diff --git a/proto/src/google/protobuf/any.rs b/proto/src/google/protobuf/any.rs index 5c8842d74..a901edcdd 100644 --- a/proto/src/google/protobuf/any.rs +++ b/proto/src/google/protobuf/any.rs @@ -246,3 +246,91 @@ impl<'de> serde::Deserialize<'de> for Any { deserializer.deserialize_struct("google.protobuf.Any", FIELDS, GeneratedVisitor) } } + +#[cfg(any(feature = "borsh", feature = "parity-scale-codec"))] +mod sealed { + use super::Any; + + use alloc::string::String; + use alloc::vec::Vec; + + #[cfg_attr( + feature = "parity-scale-codec", + derive( + parity_scale_codec::Encode, + parity_scale_codec::Decode, + scale_info::TypeInfo + ) + )] + #[cfg_attr( + feature = "borsh", + derive(borsh::BorshSerialize, borsh::BorshDeserialize) + )] + struct InnerAny { + pub type_url: String, + pub value: Vec, + } + + #[cfg(feature = "borsh")] + impl borsh::BorshSerialize for Any { + fn serialize(&self, writer: &mut W) -> borsh::io::Result<()> { + let inner_any = InnerAny { + type_url: self.type_url.clone(), + value: self.value.clone(), + }; + + borsh::BorshSerialize::serialize(&inner_any, writer) + } + } + + #[cfg(feature = "borsh")] + impl borsh::BorshDeserialize for Any { + fn deserialize_reader(reader: &mut R) -> borsh::io::Result { + let inner_any = InnerAny::deserialize_reader(reader)?; + + Ok(Any { + type_url: inner_any.type_url, + value: inner_any.value, + }) + } + } + + #[cfg(feature = "parity-scale-codec")] + impl parity_scale_codec::Encode for Any { + fn encode_to(&self, writer: &mut T) { + let inner_any = InnerAny { + type_url: self.type_url.clone(), + value: self.value.clone(), + }; + inner_any.encode_to(writer); + } + } + #[cfg(feature = "parity-scale-codec")] + impl parity_scale_codec::Decode for Any { + fn decode( + input: &mut I, + ) -> Result { + let inner_any = InnerAny::decode(input)?; + Ok(Any { + type_url: inner_any.type_url.clone(), + value: inner_any.value, + }) + } + } + + #[cfg(feature = "parity-scale-codec")] + impl scale_info::TypeInfo for Any { + type Identity = Self; + + fn type_info() -> scale_info::Type { + scale_info::Type::builder() + .path(scale_info::Path::new("Any", "ibc_proto::google::protobuf")) + // i128 is chosen before we represent the timestamp is nanoseconds, which is represented as a i128 by Time + .composite( + scale_info::build::Fields::named() + .field(|f| f.ty::().name("type_url").type_name("String")) + .field(|f| f.ty::>().name("value").type_name("Vec")), + ) + } + } +}