use super::DIGEST_SIZE; use crate::{Digest, Felt, StarkField}; use core::slice; use winterfell::{ByteReader, ByteWriter, Deserializable, DeserializationError, Serializable}; // DIGEST TRAIT IMPLEMENTATIONS // ================================================================================================ #[derive(Debug, Copy, Clone, Eq, PartialEq)] pub struct RpoDigest256([Felt; DIGEST_SIZE]); impl RpoDigest256 { pub fn new(value: [Felt; DIGEST_SIZE]) -> Self { Self(value) } pub fn as_elements(&self) -> &[Felt] { &self.0 } pub fn digests_as_elements(digests: &[Self]) -> &[Felt] { let p = digests.as_ptr(); let len = digests.len() * DIGEST_SIZE; unsafe { slice::from_raw_parts(p as *const Felt, len) } } } impl Digest for RpoDigest256 { fn as_bytes(&self) -> [u8; 32] { let mut result = [0; 32]; result[..8].copy_from_slice(&self.0[0].as_int().to_le_bytes()); result[8..16].copy_from_slice(&self.0[1].as_int().to_le_bytes()); result[16..24].copy_from_slice(&self.0[2].as_int().to_le_bytes()); result[24..].copy_from_slice(&self.0[3].as_int().to_le_bytes()); result } } impl Default for RpoDigest256 { fn default() -> Self { RpoDigest256([Felt::default(); DIGEST_SIZE]) } } impl Serializable for RpoDigest256 { fn write_into(&self, target: &mut W) { target.write_u8_slice(&self.as_bytes()); } } impl Deserializable for RpoDigest256 { fn read_from(source: &mut R) -> Result { // TODO: check if the field elements are valid? let e1 = Felt::new(source.read_u64()?); let e2 = Felt::new(source.read_u64()?); let e3 = Felt::new(source.read_u64()?); let e4 = Felt::new(source.read_u64()?); Ok(Self([e1, e2, e3, e4])) } } impl From<[Felt; DIGEST_SIZE]> for RpoDigest256 { fn from(value: [Felt; DIGEST_SIZE]) -> Self { Self(value) } } impl From for [Felt; DIGEST_SIZE] { fn from(value: RpoDigest256) -> Self { value.0 } } impl From for [u8; 32] { fn from(value: RpoDigest256) -> Self { value.as_bytes() } } // TESTS // ================================================================================================ #[cfg(test)] mod tests { use super::RpoDigest256; use crate::Felt; use rand_utils::rand_value; use winterfell::{Deserializable, Serializable, SliceReader}; #[test] fn digest_serialization() { let e1 = Felt::new(rand_value()); let e2 = Felt::new(rand_value()); let e3 = Felt::new(rand_value()); let e4 = Felt::new(rand_value()); let d1 = RpoDigest256([e1, e2, e3, e4]); let mut bytes = vec![]; d1.write_into(&mut bytes); assert_eq!(32, bytes.len()); let mut reader = SliceReader::new(&bytes); let d2 = RpoDigest256::read_from(&mut reader).unwrap(); assert_eq!(d1, d2); } }