Skip to content
This repository was archived by the owner on Nov 15, 2023. It is now read-only.
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
fix wrapper opaque
  • Loading branch information
gui1117 committed Sep 28, 2021
commit f4adbcd21ad637ed941c8264daa7e433e477caaf
31 changes: 27 additions & 4 deletions frame/support/src/traits/misc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,9 @@

//! Smaller traits used in FRAME which don't need their own file.

use crate::{dispatch::Parameter, TypeInfo};
use crate::dispatch::Parameter;
use codec::{Decode, Encode, EncodeLike, Input, MaxEncodedLen};
use scale_info::{build::Fields, meta_type, Path, Type, TypeInfo, TypeParameter};
use sp_runtime::{traits::Block as BlockT, DispatchError};
use sp_std::vec::Vec;

Expand Down Expand Up @@ -384,16 +385,15 @@ impl<Call, Balance: From<u32>, const T: u32> EstimateCallFee<Call, Balance> for
///
/// The encoding is the encoding of `T` prepended with the compact encoding of its size in bytes.
/// Thus the encoded value can be decoded as a `Vec<u8>`.
#[derive(Debug, Eq, PartialEq, Default, Clone, MaxEncodedLen, TypeInfo)]
#[derive(Debug, Eq, PartialEq, Default, Clone)]
#[cfg_attr(feature = "std", derive(serde::Serialize, serde::Deserialize))]
pub struct WrapperOpaque<T>(pub T);

impl<T: Encode> EncodeLike for WrapperOpaque<T> {}

impl<T: Encode> Encode for WrapperOpaque<T> {
fn size_hint(&self) -> usize {
// Compact<u32> usually takes at most 4 bytes
self.0.size_hint().saturating_add(4)
self.0.size_hint().saturating_add(<codec::Compact<u32>>::max_encoded_len())
}

fn encode_to<O: codec::Output + ?Sized>(&self, dest: &mut O) {
Expand Down Expand Up @@ -425,6 +425,28 @@ impl<T> From<T> for WrapperOpaque<T> {
}
}

impl<T: MaxEncodedLen> MaxEncodedLen for WrapperOpaque<T> {
fn max_encoded_len() -> usize {
// Note: this can be improved if `T::max_encoded_len` is small.
// E.g. if T max encoded len is 4, then the compact encoding of its encoded length is 1.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why this comment here?

The point of this is to return the max encoded length?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes but I think we can be more precise in certain situation, I finally did the more precise implementation 5f07186

<codec::Compact<u32>>::max_encoded_len().saturating_add(T::max_encoded_len())
}
}

impl<T: TypeInfo + 'static> TypeInfo for WrapperOpaque<T> {
type Identity = Self;
fn type_info() -> Type {
Type::builder()
.path(Path::new("WrapperOpaque", module_path!()))
.type_params(vec![TypeParameter::new("T", Some(meta_type::<T>()))])
.composite(
Fields::unnamed()
.field(|f| f.compact::<u32>().type_name("EncodedLengthOfT"))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't need type_name here. It is optional and is used for the name of the type of the field as it appears in the code, in order to identify alias usage. E.g. where the concrete type is u128 the type_name would be Balance for example.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see, I'll do another PR with this removed

.field(|f| f.ty::<T>().type_name("T")),
)
}
}

#[cfg(test)]
mod test {
use super::*;
Expand All @@ -438,5 +460,6 @@ mod test {
assert_eq!(decoded_from_vec_u8, 3u32);
let decoded = <WrapperOpaque<u32>>::decode(&mut &encoded[..]).unwrap();
assert_eq!(decoded.0, 3u32);
assert_eq!(<WrapperOpaque<u32>>::max_encoded_len(), 5 + 4);
}
}