perf(rlp): improve uint encoding performance (#3197)

This commit is contained in:
DaniPopes
2023-06-16 11:59:22 +02:00
committed by GitHub
parent 5e0508b973
commit bded94ef94

View File

@@ -4,9 +4,11 @@ use auto_impl::auto_impl;
use bytes::{BufMut, Bytes, BytesMut};
use core::borrow::Borrow;
fn zeroless_view(v: &impl AsRef<[u8]>) -> &[u8] {
let v = v.as_ref();
&v[v.iter().take_while(|&&b| b == 0).count()..]
macro_rules! to_be_bytes_trimmed {
($be:ident, $x:expr) => {{
$be = $x.to_be_bytes();
&$be[($x.leading_zeros() / 8) as usize..]
}};
}
impl Header {
@@ -16,8 +18,8 @@ impl Header {
let code = if self.list { EMPTY_LIST_CODE } else { EMPTY_STRING_CODE };
out.put_u8(code + self.payload_length as u8);
} else {
let len_be = self.payload_length.to_be_bytes();
let len_be = zeroless_view(&len_be);
let len_be;
let len_be = to_be_bytes_trimmed!(len_be, self.payload_length);
let code = if self.list { 0xF7 } else { 0xB7 };
out.put_u8(code + len_be.len() as u8);
out.put_slice(len_be);
@@ -132,8 +134,8 @@ macro_rules! encodable_uint {
} else if *self < <$t>::from(EMPTY_STRING_CODE) {
out.put_u8(u8::try_from(*self).unwrap());
} else {
let be = self.to_be_bytes();
let be = zeroless_view(&be);
let be;
let be = to_be_bytes_trimmed!(be, *self);
out.put_u8(EMPTY_STRING_CODE + be.len() as u8);
out.put_slice(be);
}
@@ -278,7 +280,8 @@ mod ethereum_types_support {
}
fn encode(&self, out: &mut dyn bytes::BufMut) {
self.to_be_bytes_trimmed_vec().as_slice().encode(out)
let be = self.to_be_bytes::<$n_bytes>();
(&be[self.leading_zeros() / 8..]).encode(out);
}
}
};
@@ -622,4 +625,43 @@ mod tests {
"abcdefgh".to_string().encode(&mut b);
assert_eq!(&encoded(SmolStr::new("abcdefgh"))[..], b.as_ref());
}
#[test]
fn to_be_bytes_trimmed() {
macro_rules! test_to_be_bytes_trimmed {
($($x:expr => $expected:expr),+ $(,)?) => {$(
let be;
assert_eq!(to_be_bytes_trimmed!(be, $x), $expected);
)+};
}
test_to_be_bytes_trimmed! {
0u8 => [],
0u16 => [],
0u32 => [],
0u64 => [],
0usize => [],
0u128 => [],
1u8 => [1],
1u16 => [1],
1u32 => [1],
1u64 => [1],
1usize => [1],
1u128 => [1],
u8::MAX => [0xff],
u16::MAX => [0xff, 0xff],
u32::MAX => [0xff, 0xff, 0xff, 0xff],
u64::MAX => [0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff],
u128::MAX => [0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff],
1u8 => [1],
255u8 => [255],
256u16 => [1, 0],
65535u16 => [255, 255],
65536u32 => [1, 0, 0],
65536u64 => [1, 0, 0],
}
}
}