Commit 7a972929 authored by Kian Peymani's avatar Kian Peymani Committed by Bastian Köcher
Browse files

`len` method for some collections. (#101)

* Basic len for vec and mappings.

* Fix link

* Slicify.

* Support collection types.

* Usize.

* Better usize.

* Update src/codec.rs
parent a73b14e5
Pipeline #40689 passed with stages
in 24 minutes and 12 seconds
......@@ -34,6 +34,8 @@ use arrayvec::ArrayVec;
#[cfg(feature = "std")]
use std::fmt;
use core::convert::TryFrom;
#[cfg_attr(feature = "std", derive(Debug))]
#[derive(PartialEq)]
#[cfg(feature = "std")]
......@@ -223,6 +225,13 @@ pub trait EncodeAppend {
fn append(self_encoded: Vec<u8>, to_append: &[Self::Item]) -> Result<Vec<u8>, Error>;
}
/// Trait that allows the length of a collection to be read, without having
/// to read and decode the entire elements.
pub trait DecodeLength {
/// Return the number of elements in `self_encoded`.
fn len(self_encoded: &mut &[u8]) -> Result<usize, Error>;
}
/// Trait that allows zero-copy read of value-references from slices in LE format.
pub trait Decode: Sized {
#[doc(hidden)]
......@@ -677,6 +686,20 @@ impl Decode for () {
}
}
macro_rules! impl_len {
( $( $type:ident< $($g:ident),* > ),* ) => { $(
impl<$($g),*> DecodeLength for $type<$($g),*> {
fn len(self_encoded: &mut &[u8]) -> Result<usize, Error> {
usize::try_from(u32::from(Compact::<u32>::decode(self_encoded)?))
.map_err(|_| "Failed convert decded size into usize.".into())
}
}
)*}
}
// Collection types that support compact decode length.
impl_len!(Vec<T>, BTreeSet<T>, BTreeMap<K, V>, VecDeque<T>, BinaryHeap<T>, LinkedList<T>);
macro_rules! tuple_impl {
($one:ident,) => {
impl<$one: Encode> Encode for ($one,) {
......@@ -992,6 +1015,37 @@ mod tests {
assert_eq!(decoded, expected);
}
fn test_encode_length<T: Encode + Decode + DecodeLength>(thing: &T, len: usize) {
assert_eq!(<T as DecodeLength>::len(&mut &thing.encode()[..]).unwrap(), len);
}
#[test]
fn len_works_for_decode_collection_types() {
let vector = vec![10; 10];
let mut btree_map: BTreeMap<u32, u32> = BTreeMap::new();
btree_map.insert(1, 1);
btree_map.insert(2, 2);
let mut btree_set: BTreeSet<u32> = BTreeSet::new();
btree_set.insert(1);
btree_set.insert(2);
let mut vd = VecDeque::new();
vd.push_front(1);
vd.push_front(2);
let mut bh = BinaryHeap::new();
bh.push(1);
bh.push(2);
let mut ll = LinkedList::new();
ll.push_back(1);
ll.push_back(2);
test_encode_length(&vector, 10);
test_encode_length(&btree_map, 2);
test_encode_length(&btree_set, 2);
test_encode_length(&vd, 2);
test_encode_length(&bh, 2);
test_encode_length(&ll, 2);
}
#[test]
fn vec_of_string_encoded_as_expected() {
let value = vec![
......
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