use super::*; impl tree_hash::TreeHash for FixedLenVec where T: tree_hash::TreeHash, { fn tree_hash_type() -> tree_hash::TreeHashType { tree_hash::TreeHashType::Vector } fn tree_hash_packed_encoding(&self) -> Vec { unreachable!("Vector should never be packed.") } fn tree_hash_packing_factor() -> usize { unreachable!("Vector should never be packed.") } fn tree_hash_root(&self) -> Vec { tree_hash::impls::vec_tree_hash_root(&self.vec) } } impl cached_tree_hash::CachedTreeHash for FixedLenVec where T: cached_tree_hash::CachedTreeHash + tree_hash::TreeHash, { fn new_tree_hash_cache( &self, depth: usize, ) -> Result { let (cache, _overlay) = cached_tree_hash::vec::new_tree_hash_cache(&self.vec, depth)?; Ok(cache) } fn tree_hash_cache_schema(&self, depth: usize) -> cached_tree_hash::BTreeSchema { cached_tree_hash::vec::produce_schema(&self.vec, depth) } fn update_tree_hash_cache( &self, cache: &mut cached_tree_hash::TreeHashCache, ) -> Result<(), cached_tree_hash::Error> { cached_tree_hash::vec::update_tree_hash_cache(&self.vec, cache)?; Ok(()) } } impl ssz::Encode for FixedLenVec where T: ssz::Encode, { fn is_ssz_fixed_len() -> bool { true } fn ssz_fixed_len() -> usize { if ::is_ssz_fixed_len() { T::ssz_fixed_len() * N::to_usize() } else { ssz::BYTES_PER_LENGTH_OFFSET } } fn ssz_append(&self, buf: &mut Vec) { if T::is_ssz_fixed_len() { buf.reserve(T::ssz_fixed_len() * self.len()); for item in &self.vec { item.ssz_append(buf); } } else { let mut encoder = ssz::SszEncoder::list(buf, self.len() * ssz::BYTES_PER_LENGTH_OFFSET); for item in &self.vec { encoder.append(item); } encoder.finalize(); } } } impl ssz::Decode for FixedLenVec where T: ssz::Decode + Default, { fn is_ssz_fixed_len() -> bool { T::is_ssz_fixed_len() } fn ssz_fixed_len() -> usize { if ::is_ssz_fixed_len() { T::ssz_fixed_len() * N::to_usize() } else { ssz::BYTES_PER_LENGTH_OFFSET } } fn from_ssz_bytes(bytes: &[u8]) -> Result { if bytes.is_empty() { Ok(FixedLenVec::from(vec![])) } else if T::is_ssz_fixed_len() { bytes .chunks(T::ssz_fixed_len()) .map(|chunk| T::from_ssz_bytes(chunk)) .collect::, _>>() .and_then(|vec| Ok(vec.into())) } else { ssz::decode_list_of_variable_length_items(bytes).and_then(|vec| Ok(vec.into())) } } } #[cfg(test)] mod ssz_tests { use super::*; use ssz::*; use typenum::*; #[test] fn encode() { let vec: FixedLenVec = vec![0; 2].into(); assert_eq!(vec.as_ssz_bytes(), vec![0, 0, 0, 0]); assert_eq!( as Encode>::ssz_fixed_len(), 4); } fn round_trip(item: T) { let encoded = &item.as_ssz_bytes(); assert_eq!(T::from_ssz_bytes(&encoded), Ok(item)); } #[test] fn u16_len_8() { round_trip::>(vec![42; 8].into()); round_trip::>(vec![0; 8].into()); } }