Skip to content

Commit 1e3f80c

Browse files
pgherveoubkchr
andauthored
Update MaxEncodedLen derive macro (#512)
Fix the generated code for MaxEncoded derive trait --------- Co-authored-by: Bastian Köcher <info@kchr.de>
1 parent 3f933df commit 1e3f80c

4 files changed

Lines changed: 46 additions & 5 deletions

File tree

derive/src/max_encoded_len.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,9 @@ fn fields_length_expr(fields: &Fields, crate_path: &syn::Path) -> proc_macro2::T
9696
let ty = &field.ty;
9797
if utils::is_compact(&field) {
9898
quote_spanned! {
99-
ty.span() => .saturating_add(<#crate_path::Compact::<#ty> as #crate_path::MaxEncodedLen>::max_encoded_len())
99+
ty.span() => .saturating_add(
100+
<<#ty as #crate_path::HasCompact>::Type as #crate_path::MaxEncodedLen>::max_encoded_len()
101+
)
100102
}
101103
} else {
102104
quote_spanned! {

src/compact.rs

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ use crate::alloc::vec::Vec;
2020
use crate::codec::{Encode, Decode, Input, Output, EncodeAsRef};
2121
use crate::encode_like::EncodeLike;
2222
use crate::Error;
23+
#[cfg(feature = "max-encoded-len")]
24+
use crate::MaxEncodedLen;
2325
#[cfg(feature = "fuzz")]
2426
use arbitrary::Arbitrary;
2527

@@ -206,18 +208,39 @@ impl<'de, T> serde::Deserialize<'de> for Compact<T> where T: serde::Deserialize<
206208
}
207209
}
208210

211+
/// Requires the presence of `MaxEncodedLen` when the `max-encoded-len` feature is active.
212+
// Remove this trait when the feature is removed.
213+
#[cfg(feature = "max-encoded-len")]
214+
pub trait MaybeMaxEncodedLen: MaxEncodedLen {}
215+
#[cfg(feature = "max-encoded-len")]
216+
impl<T: MaxEncodedLen> MaybeMaxEncodedLen for T {}
217+
218+
/// Requires the presence of `MaxEncodedLen` when the `max-encoded-len` feature is active.
219+
// Remove this trait when the feature is removed.
220+
#[cfg(not(feature = "max-encoded-len"))]
221+
pub trait MaybeMaxEncodedLen {}
222+
#[cfg(not(feature = "max-encoded-len"))]
223+
impl<T> MaybeMaxEncodedLen for T {}
224+
209225
/// Trait that tells you if a given type can be encoded/decoded in a compact way.
210226
pub trait HasCompact: Sized {
211227
/// The compact type; this can be
212-
type Type: for<'a> EncodeAsRef<'a, Self> + Decode + From<Self> + Into<Self>;
228+
type Type: for<'a> EncodeAsRef<'a, Self> + Decode + From<Self> + Into<Self> + MaybeMaxEncodedLen;
213229
}
214230

215231
impl<'a, T: 'a> EncodeAsRef<'a, T> for Compact<T> where CompactRef<'a, T>: Encode + From<&'a T> {
216232
type RefType = CompactRef<'a, T>;
217233
}
218234

235+
#[cfg(feature = "max-encoded-len")]
236+
impl<T> MaxEncodedLen for Compact<T> where T: CompactAs, Compact<T::As>: MaxEncodedLen, Compact<T>: Encode {
237+
fn max_encoded_len() -> usize {
238+
Compact::<T::As>::max_encoded_len()
239+
}
240+
}
241+
219242
impl<T: 'static> HasCompact for T where
220-
Compact<T>: for<'a> EncodeAsRef<'a, T> + Decode + From<Self> + Into<Self>
243+
Compact<T>: for<'a> EncodeAsRef<'a, T> + Decode + From<Self> + Into<Self> + MaybeMaxEncodedLen
221244
{
222245
type Type = Compact<T>;
223246
}

src/max_encoded_len.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,9 +46,8 @@ macro_rules! impl_primitives {
4646
};
4747
}
4848

49-
impl_primitives!(u8, u16, u32, u64, u128, i8, i16, i32, i64, i128, bool);
50-
5149
impl_primitives!(
50+
u8, i8, u16, i16, u32, i32, u64, i64, u128, i128, bool,
5251
NonZeroU8, NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU128, NonZeroI8, NonZeroI16, NonZeroI32,
5352
NonZeroI64, NonZeroI128
5453
);

tests/max_encoded_len.rs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,12 +73,29 @@ struct CompactField {
7373

7474
#[test]
7575
fn compact_field_max_length() {
76+
assert_eq!(CompactField::max_encoded_len(), 17);
7677
assert_eq!(
7778
CompactField::max_encoded_len(),
7879
Compact::<u64>::max_encoded_len() + u64::max_encoded_len()
7980
);
8081
}
8182

83+
84+
#[derive(Encode, MaxEncodedLen)]
85+
struct CompactFieldGenerics<T: MaxEncodedLen> {
86+
#[codec(compact)]
87+
t: T,
88+
v: u64,
89+
}
90+
91+
#[test]
92+
fn compact_field_generics_max_length() {
93+
assert_eq!(
94+
CompactFieldGenerics::<u64>::max_encoded_len(),
95+
CompactField::max_encoded_len()
96+
);
97+
}
98+
8299
#[derive(Encode, MaxEncodedLen)]
83100
struct CompactStruct(#[codec(compact)] u64);
84101

0 commit comments

Comments
 (0)