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