scale-type-resolver integration (#1460)

* start migrating, broken

* first iteration of updating

* fmt and clippy

* add Composite<u32> decoding via scale value patch

* bump scale type gen versions

* fix decoding with new scale decode

* fix js-sys versions

* add nit comments
This commit is contained in:
Tadeo Hepperle
2024-03-13 14:48:11 +01:00
committed by GitHub
parent 952cde3f79
commit 8bdd276d2f
22 changed files with 256 additions and 239 deletions
+21 -21
View File
@@ -245,27 +245,27 @@ where
// Skip over the address, signature and extra fields.
scale_decode::visitor::decode_with_visitor(
cursor,
ids.address,
&ids.address,
metadata.types(),
scale_decode::visitor::IgnoreVisitor,
scale_decode::visitor::IgnoreVisitor::new(),
)
.map_err(scale_decode::Error::from)?;
let address_end_idx = bytes.len() - cursor.len();
scale_decode::visitor::decode_with_visitor(
cursor,
ids.signature,
&ids.signature,
metadata.types(),
scale_decode::visitor::IgnoreVisitor,
scale_decode::visitor::IgnoreVisitor::new(),
)
.map_err(scale_decode::Error::from)?;
let signature_end_idx = bytes.len() - cursor.len();
scale_decode::visitor::decode_with_visitor(
cursor,
ids.extra,
&ids.extra,
metadata.types(),
scale_decode::visitor::IgnoreVisitor,
scale_decode::visitor::IgnoreVisitor::new(),
)
.map_err(scale_decode::Error::from)?;
let extra_end_idx = bytes.len() - cursor.len();
@@ -420,9 +420,7 @@ where
/// Decode and provide the extrinsic fields back in the form of a [`scale_value::Composite`]
/// type which represents the named or unnamed fields that were present in the extrinsic.
pub fn field_values(
&self,
) -> Result<scale_value::Composite<scale_value::scale::TypeId>, Error> {
pub fn field_values(&self) -> Result<scale_value::Composite<u32>, Error> {
let bytes = &mut self.field_bytes();
let extrinsic_metadata = self.extrinsic_metadata()?;
@@ -430,12 +428,9 @@ where
.variant
.fields
.iter()
.map(|f| scale_decode::Field::new(f.ty.id, f.name.as_deref()));
let decoded = <scale_value::Composite<scale_value::scale::TypeId>>::decode_as_fields(
bytes,
&mut fields,
self.metadata.types(),
)?;
.map(|f| scale_decode::Field::new(&f.ty.id, f.name.as_deref()));
let decoded =
scale_value::scale::decode_as_fields(bytes, &mut fields, self.metadata.types())?;
Ok(decoded)
}
@@ -451,7 +446,7 @@ where
.variant
.fields
.iter()
.map(|f| scale_decode::Field::new(f.ty.id, f.name.as_deref()));
.map(|f| scale_decode::Field::new(&f.ty.id, f.name.as_deref()));
let decoded =
E::decode_as_fields(&mut self.field_bytes(), &mut fields, self.metadata.types())?;
Ok(Some(decoded))
@@ -466,7 +461,7 @@ where
pub fn as_root_extrinsic<E: DecodeAsType>(&self) -> Result<E, Error> {
let decoded = E::decode_as_type(
&mut &self.call_bytes()[..],
self.metadata.outer_enums().call_enum_ty(),
&self.metadata.outer_enums().call_enum_ty(),
self.metadata.types(),
)?;
@@ -651,9 +646,9 @@ impl<'a, T: Config> ExtrinsicSignedExtensions<'a, T> {
let cursor = &mut &bytes[byte_start_idx..];
if let Err(err) = scale_decode::visitor::decode_with_visitor(
cursor,
ty_id,
&ty_id,
metadata.types(),
scale_decode::visitor::IgnoreVisitor,
scale_decode::visitor::IgnoreVisitor::new(),
)
.map_err(|e| Error::Decode(e.into()))
{
@@ -748,7 +743,12 @@ impl<'a, T: Config> ExtrinsicSignedExtension<'a, T> {
/// Signed Extension as a [`scale_value::Value`]
pub fn value(&self) -> Result<DecodedValue, Error> {
self.as_type()
let value = scale_value::scale::decode_as_type(
&mut &self.bytes[..],
&self.ty_id,
self.metadata.types(),
)?;
Ok(value)
}
/// Decodes the bytes of this Signed Extension into its associated `Decoded` type.
@@ -762,7 +762,7 @@ impl<'a, T: Config> ExtrinsicSignedExtension<'a, T> {
}
fn as_type<E: DecodeAsType>(&self) -> Result<E, Error> {
let value = E::decode_as_type(&mut &self.bytes[..], self.ty_id, self.metadata.types())?;
let value = E::decode_as_type(&mut &self.bytes[..], &self.ty_id, self.metadata.types())?;
Ok(value)
}
}
+4 -4
View File
@@ -17,7 +17,7 @@ pub use scale_value::{At, Value};
/// regarding what type was used to decode each part of it. This implements
/// [`crate::metadata::DecodeWithMetadata`], and is used as a return type
/// for dynamic requests.
pub type DecodedValue = scale_value::Value<scale_value::scale::TypeId>;
pub type DecodedValue = scale_value::Value<u32>;
// Submit dynamic transactions.
pub use crate::tx::dynamic as tx;
@@ -68,9 +68,9 @@ impl DecodedValueThunk {
}
/// Decode the SCALE encoded storage entry into a dynamic [`DecodedValue`] type.
pub fn to_value(&self) -> Result<DecodedValue, Error> {
let val = DecodedValue::decode_as_type(
let val = scale_value::scale::decode_as_type(
&mut &*self.scale_bytes,
self.type_id,
&self.type_id,
self.metadata.types(),
)?;
Ok(val)
@@ -79,7 +79,7 @@ impl DecodedValueThunk {
pub fn as_type<T: DecodeAsType>(&self) -> Result<T, scale_decode::Error> {
T::decode_as_type(
&mut &self.scale_bytes[..],
self.type_id,
&self.type_id,
self.metadata.types(),
)
}
+14 -10
View File
@@ -7,8 +7,9 @@
use crate::metadata::{DecodeWithMetadata, Metadata};
use core::fmt::Debug;
use scale_decode::{visitor::DecodeAsTypeResult, DecodeAsType};
use std::borrow::Cow;
use scale_decode::{visitor::DecodeAsTypeResult, DecodeAsType, TypeResolver};
use std::{borrow::Cow, marker::PhantomData};
use super::{Error, MetadataError};
@@ -209,7 +210,7 @@ impl ModuleError {
pub fn as_root_error<E: DecodeAsType>(&self) -> Result<E, Error> {
let decoded = E::decode_as_type(
&mut &self.bytes[..],
self.metadata.outer_enums().error_enum_ty(),
&self.metadata.outer_enums().error_enum_ty(),
self.metadata.types(),
)?;
@@ -262,24 +263,27 @@ impl DispatchError {
// a legacy format of 2 bytes, or a newer format of 5 bytes. So, just grab the bytes
// out when decoding to manually work with them.
struct DecodedModuleErrorBytes(Vec<u8>);
struct DecodedModuleErrorBytesVisitor;
impl scale_decode::Visitor for DecodedModuleErrorBytesVisitor {
struct DecodedModuleErrorBytesVisitor<R: TypeResolver>(PhantomData<R>);
impl<R: TypeResolver> scale_decode::Visitor for DecodedModuleErrorBytesVisitor<R> {
type Error = scale_decode::Error;
type Value<'scale, 'info> = DecodedModuleErrorBytes;
type TypeResolver = R;
fn unchecked_decode_as_type<'scale, 'info>(
self,
input: &mut &'scale [u8],
_type_id: scale_decode::visitor::TypeId,
_types: &'info scale_info::PortableRegistry,
_type_id: &R::TypeId,
_types: &'info R,
) -> DecodeAsTypeResult<Self, Result<Self::Value<'scale, 'info>, Self::Error>>
{
DecodeAsTypeResult::Decoded(Ok(DecodedModuleErrorBytes(input.to_vec())))
}
}
impl scale_decode::IntoVisitor for DecodedModuleErrorBytes {
type Visitor = DecodedModuleErrorBytesVisitor;
fn into_visitor() -> Self::Visitor {
DecodedModuleErrorBytesVisitor
type AnyVisitor<R: TypeResolver> = DecodedModuleErrorBytesVisitor<R>;
fn into_visitor<R: TypeResolver>() -> DecodedModuleErrorBytesVisitor<R> {
DecodedModuleErrorBytesVisitor(PhantomData)
}
}
+6
View File
@@ -99,6 +99,12 @@ impl From<std::convert::Infallible> for Error {
}
}
impl From<scale_decode::visitor::DecodeError> for Error {
fn from(value: scale_decode::visitor::DecodeError) -> Self {
Error::Decode(value.into())
}
}
impl Error {
/// Checks whether the error was caused by a RPC re-connection.
pub fn is_disconnected_will_reconnect(&self) -> bool {
+8 -14
View File
@@ -228,9 +228,9 @@ impl<T: Config> EventDetails<T> {
// Skip over the bytes for this field:
scale_decode::visitor::decode_with_visitor(
input,
field_metadata.ty.id,
&field_metadata.ty.id,
metadata.types(),
scale_decode::visitor::IgnoreVisitor,
scale_decode::visitor::IgnoreVisitor::new(),
)
.map_err(scale_decode::Error::from)?;
}
@@ -321,9 +321,7 @@ impl<T: Config> EventDetails<T> {
/// Decode and provide the event fields back in the form of a [`scale_value::Composite`]
/// type which represents the named or unnamed fields that were present in the event.
pub fn field_values(
&self,
) -> Result<scale_value::Composite<scale_value::scale::TypeId>, Error> {
pub fn field_values(&self) -> Result<scale_value::Composite<u32>, Error> {
let bytes = &mut self.field_bytes();
let event_metadata = self.event_metadata();
@@ -331,14 +329,10 @@ impl<T: Config> EventDetails<T> {
.variant
.fields
.iter()
.map(|f| scale_decode::Field::new(f.ty.id, f.name.as_deref()));
.map(|f| scale_decode::Field::new(&f.ty.id, f.name.as_deref()));
use scale_decode::DecodeAsFields;
let decoded = <scale_value::Composite<scale_value::scale::TypeId>>::decode_as_fields(
bytes,
&mut fields,
self.metadata.types(),
)?;
let decoded =
scale_value::scale::decode_as_fields(bytes, &mut fields, self.metadata.types())?;
Ok(decoded)
}
@@ -352,7 +346,7 @@ impl<T: Config> EventDetails<T> {
.variant
.fields
.iter()
.map(|f| scale_decode::Field::new(f.ty.id, f.name.as_deref()));
.map(|f| scale_decode::Field::new(&f.ty.id, f.name.as_deref()));
let decoded =
E::decode_as_fields(&mut self.field_bytes(), &mut fields, self.metadata.types())?;
Ok(Some(decoded))
@@ -369,7 +363,7 @@ impl<T: Config> EventDetails<T> {
let decoded = E::decode_as_type(
&mut &bytes[..],
self.metadata.outer_enums().event_enum_ty(),
&self.metadata.outer_enums().event_enum_ty(),
self.metadata.types(),
)?;
+2 -2
View File
@@ -21,7 +21,7 @@ impl<T: scale_decode::DecodeAsType> DecodeWithMetadata for T {
type_id: u32,
metadata: &Metadata,
) -> Result<T, Error> {
let val = T::decode_as_type(bytes, type_id, metadata.types())?;
let val = T::decode_as_type(bytes, &type_id, metadata.types())?;
Ok(val)
}
}
@@ -45,7 +45,7 @@ impl<T: scale_encode::EncodeAsType> EncodeWithMetadata for T {
metadata: &Metadata,
bytes: &mut Vec<u8>,
) -> Result<(), Error> {
self.encode_as_type_to(type_id, metadata.types(), bytes)?;
self.encode_as_type_to(&type_id, metadata.types(), bytes)?;
Ok(())
}
}
+1 -1
View File
@@ -103,7 +103,7 @@ impl<ArgsData: EncodeAsFields, ReturnTy: DecodeWithMetadata> RuntimeApiPayload
.ok_or_else(|| MetadataError::RuntimeMethodNotFound((*self.method_name).to_owned()))?;
let mut fields = api_method
.inputs()
.map(|input| scale_encode::Field::named(input.ty, &input.name));
.map(|input| scale_encode::Field::named(&input.ty, &input.name));
self.args_data
.encode_as_fields_to(&mut fields, metadata.types(), out)?;
+12 -6
View File
@@ -2,7 +2,7 @@ use crate::{
error::{Error, MetadataError, StorageAddressError},
utils::{Encoded, Static},
};
use scale_decode::{visitor::IgnoreVisitor, DecodeAsType};
use scale_decode::visitor::IgnoreVisitor;
use scale_encode::EncodeAsType;
use scale_info::{PortableRegistry, TypeDef};
use scale_value::Value;
@@ -203,7 +203,7 @@ impl<K: ?Sized> StorageKey for StaticStorageKey<K> {
types: &PortableRegistry,
) -> Result<(), Error> {
let (hasher, ty_id) = hashers.next_or_err()?;
let encoded_value = self.bytes.encode_as_type(ty_id, types)?;
let encoded_value = self.bytes.encode_as_type(&ty_id, types)?;
hash_bytes(&encoded_value, hasher, bytes);
Ok(())
}
@@ -242,7 +242,7 @@ impl StorageKey for Vec<scale_value::Value> {
) -> Result<(), Error> {
for value in self.iter() {
let (hasher, ty_id) = hashers.next_or_err()?;
let encoded_value = value.encode_as_type(ty_id, types)?;
let encoded_value = value.encode_as_type(&ty_id, types)?;
hash_bytes(&encoded_value, hasher, bytes);
}
Ok(())
@@ -260,7 +260,8 @@ impl StorageKey for Vec<scale_value::Value> {
for (hasher, ty_id) in hashers.by_ref() {
match consume_hash_returning_key_bytes(bytes, hasher, ty_id, types)? {
Some(value_bytes) => {
let value = Value::decode_as_type(&mut &*value_bytes, ty_id, types)?;
let value =
scale_value::scale::decode_as_type(&mut &*value_bytes, &ty_id, types)?;
result.push(value.remove_context());
}
None => {
@@ -296,8 +297,13 @@ fn consume_hash_returning_key_bytes<'a>(
// Now, find the bytes representing the key, consuming them.
let before_key = *bytes;
if hasher.ends_with_key() {
scale_decode::visitor::decode_with_visitor(bytes, ty_id, types, IgnoreVisitor)
.map_err(|err| Error::Decode(err.into()))?;
scale_decode::visitor::decode_with_visitor(
bytes,
&ty_id,
types,
IgnoreVisitor::<PortableRegistry>::new(),
)
.map_err(|err| Error::Decode(err.into()))?;
// Return the key bytes, having advanced the input cursor past them.
let key_bytes = &before_key[..before_key.len() - bytes.len()];
+1 -1
View File
@@ -28,6 +28,6 @@ pub use self::{
PartialExtrinsic, SubmittableExtrinsic, TransactionInvalid, TransactionUnknown, TxClient,
ValidationResult,
},
tx_payload::{dynamic, BoxedPayload, DynamicPayload, Payload, TxPayload},
tx_payload::{dynamic, DynamicPayload, Payload, TxPayload},
tx_progress::{TxInBlock, TxProgress, TxStatus},
};
+2 -19
View File
@@ -14,7 +14,7 @@ use codec::Encode;
use derivative::Derivative;
use scale_encode::EncodeAsFields;
use scale_value::{Composite, ValueDef, Variant};
use std::{borrow::Cow, sync::Arc};
use std::borrow::Cow;
/// This represents a transaction payload that can be submitted
/// to a node.
@@ -65,10 +65,6 @@ pub struct Payload<CallData> {
validation_hash: Option<[u8; 32]>,
}
/// A boxed transaction payload.
// Dev Note: Arc used to enable easy cloning (given that we can't have dyn Clone).
pub type BoxedPayload = Payload<Arc<dyn EncodeAsFields + Send + Sync + 'static>>;
/// The type of a payload typically used for dynamic transaction payloads.
pub type DynamicPayload = Payload<Composite<()>>;
@@ -104,19 +100,6 @@ impl<CallData> Payload<CallData> {
}
}
/// Box the payload.
pub fn boxed(self) -> BoxedPayload
where
CallData: EncodeAsFields + Send + Sync + 'static,
{
BoxedPayload {
pallet_name: self.pallet_name,
call_name: self.call_name,
call_data: Arc::new(self.call_data),
validation_hash: self.validation_hash,
}
}
/// Do not validate this call prior to submitting it.
pub fn unvalidated(self) -> Self {
Self {
@@ -174,7 +157,7 @@ impl<CallData: EncodeAsFields> TxPayload for Payload<CallData> {
let mut fields = call
.fields
.iter()
.map(|f| scale_encode::Field::new(f.ty.id, f.name.as_deref()));
.map(|f| scale_encode::Field::new(&f.ty.id, f.name.as_deref()));
self.call_data
.encode_as_fields_to(&mut fields, metadata.types(), out)?;
+19 -20
View File
@@ -9,7 +9,8 @@ use scale_bits::{
scale::format::{Format, OrderFormat, StoreFormat},
Bits,
};
use scale_decode::IntoVisitor;
use scale_decode::{IntoVisitor, TypeResolver};
use std::marker::PhantomData;
/// Associates `bitvec::store::BitStore` trait with corresponding, type-erased `scale_bits::StoreFormat` enum.
@@ -144,45 +145,43 @@ impl<Store: BitStore, Order: BitOrder> codec::Encode for DecodedBits<Store, Orde
}
#[doc(hidden)]
pub struct DecodedBitsVisitor<S, O>(std::marker::PhantomData<(S, O)>);
impl<Store, Order> scale_decode::Visitor for DecodedBitsVisitor<Store, Order> {
pub struct DecodedBitsVisitor<S, O, R: TypeResolver>(std::marker::PhantomData<(S, O, R)>);
impl<Store, Order, R: TypeResolver> scale_decode::Visitor for DecodedBitsVisitor<Store, Order, R> {
type Value<'scale, 'info> = DecodedBits<Store, Order>;
type Error = scale_decode::Error;
type TypeResolver = R;
fn unchecked_decode_as_type<'scale, 'info>(
self,
input: &mut &'scale [u8],
type_id: scale_decode::visitor::TypeId,
types: &'info scale_info::PortableRegistry,
type_id: &R::TypeId,
types: &'info R,
) -> scale_decode::visitor::DecodeAsTypeResult<
Self,
Result<Self::Value<'scale, 'info>, Self::Error>,
> {
let res = scale_decode::visitor::decode_with_visitor(
input,
type_id.0,
types,
Bits::into_visitor(),
)
.map(|bits| DecodedBits {
bits,
_marker: PhantomData,
});
let res =
scale_decode::visitor::decode_with_visitor(input, type_id, types, Bits::into_visitor())
.map(|bits| DecodedBits {
bits,
_marker: PhantomData,
});
scale_decode::visitor::DecodeAsTypeResult::Decoded(res)
}
}
impl<Store, Order> scale_decode::IntoVisitor for DecodedBits<Store, Order> {
type Visitor = DecodedBitsVisitor<Store, Order>;
fn into_visitor() -> Self::Visitor {
type AnyVisitor<R: scale_decode::TypeResolver> = DecodedBitsVisitor<Store, Order, R>;
fn into_visitor<R: TypeResolver>() -> DecodedBitsVisitor<Store, Order, R> {
DecodedBitsVisitor(PhantomData)
}
}
impl<Store, Order> scale_encode::EncodeAsType for DecodedBits<Store, Order> {
fn encode_as_type_to(
fn encode_as_type_to<R: TypeResolver>(
&self,
type_id: u32,
types: &scale_info::PortableRegistry,
type_id: &R::TypeId,
types: &R,
out: &mut Vec<u8>,
) -> Result<(), scale_encode::Error> {
self.bits.encode_as_type_to(type_id, types, out)
+11 -10
View File
@@ -3,7 +3,7 @@
// see LICENSE for license details.
use codec::{Decode, Encode};
use scale_decode::{visitor::DecodeAsTypeResult, IntoVisitor, Visitor};
use scale_decode::{visitor::DecodeAsTypeResult, IntoVisitor, TypeResolver, Visitor};
use scale_encode::EncodeAsType;
/// If the type inside this implements [`Encode`], this will implement [`scale_encode::EncodeAsType`].
@@ -18,10 +18,10 @@ use scale_encode::EncodeAsType;
pub struct Static<T>(pub T);
impl<T: Encode> EncodeAsType for Static<T> {
fn encode_as_type_to(
fn encode_as_type_to<R: TypeResolver>(
&self,
_type_id: u32,
_types: &scale_decode::PortableRegistry,
_type_id: &R::TypeId,
_types: &R,
out: &mut Vec<u8>,
) -> Result<(), scale_encode::Error> {
self.0.encode_to(out);
@@ -29,17 +29,18 @@ impl<T: Encode> EncodeAsType for Static<T> {
}
}
pub struct StaticDecodeAsTypeVisitor<T>(std::marker::PhantomData<T>);
pub struct StaticDecodeAsTypeVisitor<T, R>(std::marker::PhantomData<(T, R)>);
impl<T: Decode> Visitor for StaticDecodeAsTypeVisitor<T> {
impl<T: Decode, R: TypeResolver> Visitor for StaticDecodeAsTypeVisitor<T, R> {
type Value<'scale, 'info> = Static<T>;
type Error = scale_decode::Error;
type TypeResolver = R;
fn unchecked_decode_as_type<'scale, 'info>(
self,
input: &mut &'scale [u8],
_type_id: scale_decode::visitor::TypeId,
_types: &'info scale_info::PortableRegistry,
_type_id: &R::TypeId,
_types: &'info R,
) -> DecodeAsTypeResult<Self, Result<Self::Value<'scale, 'info>, Self::Error>> {
use scale_decode::{visitor::DecodeError, Error};
let decoded = T::decode(input)
@@ -50,8 +51,8 @@ impl<T: Decode> Visitor for StaticDecodeAsTypeVisitor<T> {
}
impl<T: Decode> IntoVisitor for Static<T> {
type Visitor = StaticDecodeAsTypeVisitor<T>;
fn into_visitor() -> Self::Visitor {
type AnyVisitor<R: TypeResolver> = StaticDecodeAsTypeVisitor<T, R>;
fn into_visitor<R: TypeResolver>() -> StaticDecodeAsTypeVisitor<T, R> {
StaticDecodeAsTypeVisitor(std::marker::PhantomData)
}
}
+16 -13
View File
@@ -12,7 +12,7 @@
use std::marker::PhantomData;
use codec::{Decode, Encode};
use scale_decode::{visitor::DecodeAsTypeResult, DecodeAsType, IntoVisitor, Visitor};
use scale_decode::{visitor::DecodeAsTypeResult, DecodeAsType, IntoVisitor, TypeResolver, Visitor};
use super::{Encoded, Static};
@@ -52,10 +52,10 @@ impl<Address, Call, Signature, Extra> Decode
impl<Address, Call, Signature, Extra> scale_encode::EncodeAsType
for UncheckedExtrinsic<Address, Call, Signature, Extra>
{
fn encode_as_type_to(
fn encode_as_type_to<R: TypeResolver>(
&self,
type_id: u32,
types: &scale_info::PortableRegistry,
type_id: &R::TypeId,
types: &R,
out: &mut Vec<u8>,
) -> Result<(), scale_encode::Error> {
self.0.encode_as_type_to(type_id, types, out)
@@ -78,32 +78,35 @@ impl<Address, Call, Signature, Extra> From<UncheckedExtrinsic<Address, Call, Sig
}
}
pub struct UncheckedExtrinsicDecodeAsTypeVisitor<Address, Call, Signature, Extra>(
PhantomData<(Address, Call, Signature, Extra)>,
pub struct UncheckedExtrinsicDecodeAsTypeVisitor<Address, Call, Signature, Extra, R: TypeResolver>(
PhantomData<(Address, Call, Signature, Extra, R)>,
);
impl<Address, Call, Signature, Extra> Visitor
for UncheckedExtrinsicDecodeAsTypeVisitor<Address, Call, Signature, Extra>
impl<Address, Call, Signature, Extra, R: TypeResolver> Visitor
for UncheckedExtrinsicDecodeAsTypeVisitor<Address, Call, Signature, Extra, R>
{
type Value<'scale, 'info> = UncheckedExtrinsic<Address, Call, Signature, Extra>;
type Error = scale_decode::Error;
type TypeResolver = R;
fn unchecked_decode_as_type<'scale, 'info>(
self,
input: &mut &'scale [u8],
type_id: scale_decode::visitor::TypeId,
types: &'info scale_info::PortableRegistry,
type_id: &R::TypeId,
types: &'info R,
) -> DecodeAsTypeResult<Self, Result<Self::Value<'scale, 'info>, Self::Error>> {
DecodeAsTypeResult::Decoded(Self::Value::decode_as_type(input, type_id.0, types))
DecodeAsTypeResult::Decoded(Self::Value::decode_as_type(input, type_id, types))
}
}
impl<Address, Call, Signature, Extra> IntoVisitor
for UncheckedExtrinsic<Address, Call, Signature, Extra>
{
type Visitor = UncheckedExtrinsicDecodeAsTypeVisitor<Address, Call, Signature, Extra>;
type AnyVisitor<R: TypeResolver> =
UncheckedExtrinsicDecodeAsTypeVisitor<Address, Call, Signature, Extra, R>;
fn into_visitor() -> Self::Visitor {
fn into_visitor<R: TypeResolver>(
) -> UncheckedExtrinsicDecodeAsTypeVisitor<Address, Call, Signature, Extra, R> {
UncheckedExtrinsicDecodeAsTypeVisitor(PhantomData)
}
}
+28 -38
View File
@@ -5,7 +5,7 @@
use super::PhantomDataSendSync;
use codec::{Compact, Decode, DecodeAll, Encode};
use derivative::Derivative;
use scale_decode::{IntoVisitor, Visitor};
use scale_decode::{ext::scale_type_resolver::visitor, IntoVisitor, TypeResolver, Visitor};
use scale_encode::EncodeAsType;
/// A wrapper for any type `T` which implement encode/decode in a way compatible with `Vec<u8>`.
@@ -74,57 +74,47 @@ impl<T> WrapperKeepOpaque<T> {
}
impl<T> EncodeAsType for WrapperKeepOpaque<T> {
fn encode_as_type_to(
fn encode_as_type_to<R: TypeResolver>(
&self,
type_id: u32,
types: &scale_info::PortableRegistry,
type_id: &R::TypeId,
types: &R,
out: &mut Vec<u8>,
) -> Result<(), scale_encode::Error> {
use scale_encode::error::{Error, ErrorKind, Kind};
let Some(ty) = types.resolve(type_id) else {
return Err(Error::new(ErrorKind::TypeNotFound(type_id)));
};
// Do a basic check that the target shape lines up.
let scale_info::TypeDef::Composite(_) = &ty.type_def else {
return Err(Error::new(ErrorKind::WrongShape {
let visitor = visitor::new(out, |_, _| {
// Check that the target shape lines up: any other shape but the composite is wrong.
Err(Error::new(ErrorKind::WrongShape {
actual: Kind::Struct,
expected: type_id,
}));
};
expected_id: format!("{:?}", type_id),
}))
})
.visit_composite(|out, _fields| {
self.data.encode_to(out);
Ok(())
});
// Check that the name also lines up.
if ty.path.ident().as_deref() != Some("WrapperKeepOpaque") {
return Err(Error::new(ErrorKind::WrongShape {
actual: Kind::Struct,
expected: type_id,
}));
}
// Just blat the bytes out.
self.data.encode_to(out);
Ok(())
types
.resolve_type(type_id, visitor)
.map_err(|_| Error::new(ErrorKind::TypeNotFound(format!("{:?}", type_id))))?
}
}
pub struct WrapperKeepOpaqueVisitor<T>(std::marker::PhantomData<T>);
impl<T> Visitor for WrapperKeepOpaqueVisitor<T> {
pub struct WrapperKeepOpaqueVisitor<T, R>(std::marker::PhantomData<(T, R)>);
impl<T, R: TypeResolver> Visitor for WrapperKeepOpaqueVisitor<T, R> {
type Value<'scale, 'info> = WrapperKeepOpaque<T>;
type Error = scale_decode::Error;
type TypeResolver = R;
fn visit_composite<'scale, 'info>(
self,
value: &mut scale_decode::visitor::types::Composite<'scale, 'info>,
_type_id: scale_decode::visitor::TypeId,
value: &mut scale_decode::visitor::types::Composite<'scale, 'info, R>,
_type_id: &R::TypeId,
) -> Result<Self::Value<'scale, 'info>, Self::Error> {
use scale_decode::error::{Error, ErrorKind};
if value.path().ident().as_deref() != Some("WrapperKeepOpaque") {
return Err(Error::custom_str(
"Type to decode is not 'WrapperTypeKeepOpaque'",
));
}
// TODO: When `scale-type-resolver` [provides struct names](https://github.com/paritytech/scale-type-resolver/issues/4), check that this struct name is `WrapperKeepOpaque`
if value.remaining() != 2 {
return Err(Error::new(ErrorKind::WrongLength {
actual_len: value.remaining(),
@@ -151,8 +141,8 @@ impl<T> Visitor for WrapperKeepOpaqueVisitor<T> {
}
impl<T> IntoVisitor for WrapperKeepOpaque<T> {
type Visitor = WrapperKeepOpaqueVisitor<T>;
fn into_visitor() -> Self::Visitor {
type AnyVisitor<R: TypeResolver> = WrapperKeepOpaqueVisitor<T, R>;
fn into_visitor<R: TypeResolver>() -> WrapperKeepOpaqueVisitor<T, R> {
WrapperKeepOpaqueVisitor(std::marker::PhantomData)
}
}
@@ -205,7 +195,7 @@ mod test {
let (type_id, types) = make_type::<T>();
let scale_codec_encoded = t.encode();
let encode_as_type_encoded = t.encode_as_type(type_id, &types).unwrap();
let encode_as_type_encoded = t.encode_as_type(&type_id, &types).unwrap();
assert_eq!(
scale_codec_encoded, encode_as_type_encoded,
@@ -213,7 +203,7 @@ mod test {
);
let decode_as_type_bytes = &mut &*scale_codec_encoded;
let decoded_as_type = T::decode_as_type(decode_as_type_bytes, type_id, &types)
let decoded_as_type = T::decode_as_type(decode_as_type_bytes, &type_id, &types)
.expect("decode-as-type decodes");
let decode_scale_codec_bytes = &mut &*scale_codec_encoded;