diff --git a/eth2/utils/fixed_len_vec/src/impls.rs b/eth2/utils/fixed_len_vec/src/impls.rs index 98c70e3eb..e9e206e87 100644 --- a/eth2/utils/fixed_len_vec/src/impls.rs +++ b/eth2/utils/fixed_len_vec/src/impls.rs @@ -55,8 +55,26 @@ impl ssz::Encodable for FixedLenVec where T: ssz::Encodable, { - fn ssz_append(&self, s: &mut ssz::SszStream) { - s.append_vec(&self.vec) + fn is_ssz_fixed_len() -> bool { + true + } + + 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(); + } } } @@ -64,7 +82,29 @@ impl ssz::Decodable for FixedLenVec where T: ssz::Decodable + Default, { - fn ssz_decode(bytes: &[u8], index: usize) -> Result<(Self, usize), ssz::DecodeError> { - ssz::decode_ssz_list(bytes, index).and_then(|(vec, i)| Ok((vec.into(), i))) + 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.len() == 0 { + 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())) + } } } diff --git a/eth2/utils/fixed_len_vec/src/lib.rs b/eth2/utils/fixed_len_vec/src/lib.rs index 085b1835b..2976ee4e4 100644 --- a/eth2/utils/fixed_len_vec/src/lib.rs +++ b/eth2/utils/fixed_len_vec/src/lib.rs @@ -9,10 +9,7 @@ pub use typenum; mod impls; #[derive(Debug, PartialEq, Clone, Serialize, Deserialize)] -pub struct FixedLenVec -where - N: Unsigned, -{ +pub struct FixedLenVec { vec: Vec, _phantom: PhantomData, }