arnaucube
arnaucube/miden-cryptoPublic Self-hosted repository
miden-crypto/src/hash/rpo/digest.rs
src/hash/rpo/digest.rsRaw
  1use super::DIGEST_SIZE;
  2use crate::{
  3    ByteReader, ByteWriter, Deserializable, DeserializationError, Digest, Felt, Serializable,
  4    StarkField, ZERO,
  5};
  6use core::ops::Deref;
  7
  8// DIGEST TRAIT IMPLEMENTATIONS
  9// ================================================================================================
 10
 11#[derive(Debug, Copy, Clone, Eq, PartialEq)]
 12pub struct RpoDigest256([Felt; DIGEST_SIZE]);
 13
 14impl RpoDigest256 {
 15    pub fn new(value: [Felt; DIGEST_SIZE]) -> Self {
 16        Self(value)
 17    }
 18
 19    pub fn as_elements(&self) -> &[Felt] {
 20        self.as_ref()
 21    }
 22
 23    pub fn digests_as_elements<'a, I>(digests: I) -> impl Iterator<Item = &'a Felt>
 24    where
 25        I: Iterator<Item = &'a Self>,
 26    {
 27        digests.flat_map(|d| d.0.iter())
 28    }
 29}
 30
 31impl Digest for RpoDigest256 {
 32    fn as_bytes(&self) -> [u8; 32] {
 33        let mut result = [0; 32];
 34
 35        result[..8].copy_from_slice(&self.0[0].as_int().to_le_bytes());
 36        result[8..16].copy_from_slice(&self.0[1].as_int().to_le_bytes());
 37        result[16..24].copy_from_slice(&self.0[2].as_int().to_le_bytes());
 38        result[24..].copy_from_slice(&self.0[3].as_int().to_le_bytes());
 39
 40        result
 41    }
 42}
 43
 44impl Default for RpoDigest256 {
 45    fn default() -> Self {
 46        RpoDigest256([Felt::default(); DIGEST_SIZE])
 47    }
 48}
 49
 50impl Serializable for RpoDigest256 {
 51    fn write_into<W: ByteWriter>(&self, target: &mut W) {
 52        target.write_u8_slice(&self.as_bytes());
 53    }
 54}
 55
 56impl Deserializable for RpoDigest256 {
 57    fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
 58        let mut inner: [Felt; DIGEST_SIZE] = [ZERO; DIGEST_SIZE];
 59        for inner in inner.iter_mut() {
 60            let e = source.read_u64()?;
 61            if e >= Felt::MODULUS {
 62                return Err(DeserializationError::InvalidValue(
 63                    "Value not in the appropriate range".to_owned(),
 64                ));
 65            }
 66            *inner = Felt::new(e);
 67        }
 68
 69        Ok(Self(inner))
 70    }
 71}
 72
 73impl From<[Felt; DIGEST_SIZE]> for RpoDigest256 {
 74    fn from(value: [Felt; DIGEST_SIZE]) -> Self {
 75        Self(value)
 76    }
 77}
 78
 79impl From<RpoDigest256> for [Felt; DIGEST_SIZE] {
 80    fn from(value: RpoDigest256) -> Self {
 81        value.0
 82    }
 83}
 84
 85impl From<RpoDigest256> for [u8; 32] {
 86    fn from(value: RpoDigest256) -> Self {
 87        value.as_bytes()
 88    }
 89}
 90
 91impl Deref for RpoDigest256 {
 92    type Target = [Felt; DIGEST_SIZE];
 93
 94    fn deref(&self) -> &Self::Target {
 95        &self.0
 96    }
 97}
 98
 99// TESTS
100// ================================================================================================
101
102#[cfg(test)]
103mod tests {
104
105    use super::RpoDigest256;
106    use crate::{Deserializable, Felt, Serializable, SliceReader};
107    use rand_utils::rand_value;
108
109    #[test]
110    fn digest_serialization() {
111        let e1 = Felt::new(rand_value());
112        let e2 = Felt::new(rand_value());
113        let e3 = Felt::new(rand_value());
114        let e4 = Felt::new(rand_value());
115
116        let d1 = RpoDigest256([e1, e2, e3, e4]);
117
118        let mut bytes = vec![];
119        d1.write_into(&mut bytes);
120        assert_eq!(32, bytes.len());
121
122        let mut reader = SliceReader::new(&bytes);
123        let d2 = RpoDigest256::read_from(&mut reader).unwrap();
124
125        assert_eq!(d1, d2);
126    }
127}