use super::{ LENGTH_BYTES, }; #[derive(Debug)] pub enum DecodeError { OutOfBounds, TooShort, TooLong, } pub trait Decodable: Sized { fn ssz_decode(bytes: &[u8]) -> Result; } pub fn decode_ssz_list_element(ssz_bytes: &[u8], n: usize) -> Result where T: Decodable { T::ssz_decode(nth_value(ssz_bytes, n)?) } fn nth_value(ssz_bytes: &[u8], n: usize) -> Result<&[u8], DecodeError> { let mut c: usize = 0; for i in 0..(n + 1) { let length = decode_length(&ssz_bytes[c..], LENGTH_BYTES)?; let next = c + LENGTH_BYTES + length; if i == n { return Ok(&ssz_bytes[c + LENGTH_BYTES..next]); } else { if next >= ssz_bytes.len() { return Err(DecodeError::OutOfBounds); } else { c = next; } } } Err(DecodeError::OutOfBounds) } fn decode_length(bytes: &[u8], length_bytes: usize) -> Result { if bytes.len() < length_bytes { return Err(DecodeError::TooShort); }; let mut len: usize = 0; for i in 0..length_bytes { let offset = (length_bytes - i - 1) * 8; len = ((bytes[i] as usize) << offset) | len; }; Ok(len) } #[cfg(test)] mod tests { use super::*; use super::super::encode_length; #[test] fn test_ssz_decode_length() { let decoded = decode_length( &vec![0, 0, 0, 1], LENGTH_BYTES); assert_eq!(decoded.unwrap(), 1); let decoded = decode_length( &vec![0, 0, 1, 0], LENGTH_BYTES); assert_eq!(decoded.unwrap(), 256); let decoded = decode_length( &vec![0, 0, 1, 255], LENGTH_BYTES); assert_eq!(decoded.unwrap(), 511); let decoded = decode_length( &vec![255, 255, 255, 255], LENGTH_BYTES); assert_eq!(decoded.unwrap(), 4294967295); } #[test] fn test_encode_decode_length() { let params: Vec = vec![ 0, 1, 2, 3, 7, 8, 16, 2^8, 2^8 + 1, 2^16, 2^16 + 1, 2^24, 2^24 + 1, 2^32, ]; for i in params { let decoded = decode_length( &encode_length(i, LENGTH_BYTES), LENGTH_BYTES).unwrap(); assert_eq!(i, decoded); } } #[test] fn test_ssz_nth_value() { let ssz = vec![0, 0, 0, 1, 0]; let result = nth_value(&ssz, 0).unwrap(); assert_eq!(result, vec![0].as_slice()); let ssz = vec![0, 0, 0, 4, 1, 2, 3, 4]; let result = nth_value(&ssz, 0).unwrap(); assert_eq!(result, vec![1, 2, 3, 4].as_slice()); let ssz = vec![0, 0, 0, 1, 0, 0, 0, 0, 1, 1]; let result = nth_value(&ssz, 1).unwrap(); assert_eq!(result, vec![1].as_slice()); let mut ssz = vec![0, 0, 1, 255]; ssz.append(&mut vec![42; 511]); let result = nth_value(&ssz, 0).unwrap(); assert_eq!(result, vec![42; 511].as_slice()); } /* #[test] fn test_ssz_decode_u16() { let x: u16 = 100; let mut s = SszStream::new(); s.append(&x); let y: u16 = u16::ssz_decode(s.nth_value(0).unwrap()) .unwrap(); assert_eq!(x, y); } */ }