Unverified Commit a5c22931 authored by laizy's avatar laizy Committed by GitHub
Browse files

add EncodedSize that calculates the encoded size more efficiently. (#245)



Co-authored-by: thiolliere's avatarGuillaume Thiolliere <gui.thiolliere@gmail.com>
Co-authored-by: default avatarBastian Köcher <bkchr@users.noreply.github.com>
parent e2365be3
Pipeline #121632 passed with stages
in 22 minutes and 18 seconds
......@@ -228,6 +228,35 @@ pub trait Encode {
fn using_encoded<R, F: FnOnce(&[u8]) -> R>(&self, f: F) -> R {
f(&self.encode())
}
/// Calculates the encoded size.
///
/// Should be used when the encoded data isn't required.
///
/// # Note
///
/// This works by using a special [`Output`] that only tracks the size. So, there are no allocations inside the
/// output. However, this can not prevent allocations that some types are doing inside their own encoding.
fn encoded_size(&self) -> usize {
let mut size_tracker = SizeTracker { written: 0 };
self.encode_to(&mut size_tracker);
size_tracker.written
}
}
// Implements `Output` and only keeps track of the number of written bytes
struct SizeTracker {
written: usize,
}
impl Output for SizeTracker {
fn write(&mut self, bytes: &[u8]) {
self.written += bytes.len();
}
fn push_byte(&mut self, _byte: u8) {
self.written += 1;
}
}
/// Trait that allows the length of a collection to be read, without having
......@@ -1587,4 +1616,41 @@ mod tests {
assert!(encoded.is_empty());
<[u32; 0]>::decode(&mut &encoded[..]).unwrap();
}
fn test_encoded_size(val: impl Encode) {
let length = val.using_encoded(|v| v.len());
assert_eq!(length, val.encoded_size());
}
struct TestStruct {
data: Vec<u32>,
other: u8,
compact: Compact<u128>,
}
impl Encode for TestStruct {
fn encode_to<W: Output + ?Sized>(&self, dest: &mut W) {
self.data.encode_to(dest);
self.other.encode_to(dest);
self.compact.encode_to(dest);
}
}
#[test]
fn encoded_size_works() {
test_encoded_size(120u8);
test_encoded_size(30u16);
test_encoded_size(1u32);
test_encoded_size(2343545u64);
test_encoded_size(34358394245459854u128);
test_encoded_size(vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10u32]);
test_encoded_size(Compact(32445u32));
test_encoded_size(Compact(34353454453545u128));
test_encoded_size(TestStruct {
data: vec![1, 2, 4, 5, 6],
other: 45,
compact: Compact(123234545),
});
}
}
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment