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::{Digest, Felt, StarkField};
  3use core::ops::Deref;
  4
  5use winterfell::{ByteReader, ByteWriter, Deserializable, DeserializationError, Serializable};
  6
  7// DIGEST TRAIT IMPLEMENTATIONS
  8// ================================================================================================
  9
 10#[derive(Debug, Copy, Clone, Eq, PartialEq)]
 11pub struct RpoDigest256([Felt; DIGEST_SIZE]);
 12
 13impl RpoDigest256 {
 14    pub fn new(value: [Felt; DIGEST_SIZE]) -> Self {
 15        Self(value)
 16    }
 17
 18    pub fn as_elements(&self) -> &[Felt] {
 19        self.as_ref()
 20    }
 21
 22    pub fn digests_as_elements<'a, I>(digests: I) -> impl Iterator<Item = &'a Felt>
 23    where
 24        I: Iterator<Item = &'a Self>,
 25    {
 26        digests.map(|d| d.0.iter()).flatten()
 27    }
 28}
 29
 30impl Digest for RpoDigest256 {
 31    fn as_bytes(&self) -> [u8; 32] {
 32        let mut result = [0; 32];
 33
 34        result[..8].copy_from_slice(&self.0[0].as_int().to_le_bytes());
 35        result[8..16].copy_from_slice(&self.0[1].as_int().to_le_bytes());
 36        result[16..24].copy_from_slice(&self.0[2].as_int().to_le_bytes());
 37        result[24..].copy_from_slice(&self.0[3].as_int().to_le_bytes());
 38
 39        result
 40    }
 41}
 42
 43impl Default for RpoDigest256 {
 44    fn default() -> Self {
 45        RpoDigest256([Felt::default(); DIGEST_SIZE])
 46    }
 47}
 48
 49impl Serializable for RpoDigest256 {
 50    fn write_into<W: ByteWriter>(&self, target: &mut W) {
 51        target.write_u8_slice(&self.as_bytes());
 52    }
 53}
 54
 55impl Deserializable for RpoDigest256 {
 56    fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
 57        let e1 = Felt::new(source.read_u64()?);
 58        let e2 = Felt::new(source.read_u64()?);
 59        let e3 = Felt::new(source.read_u64()?);
 60        let e4 = Felt::new(source.read_u64()?);
 61
 62        Ok(Self([e1, e2, e3, e4]))
 63    }
 64}
 65
 66impl From<[Felt; DIGEST_SIZE]> for RpoDigest256 {
 67    fn from(value: [Felt; DIGEST_SIZE]) -> Self {
 68        Self(value)
 69    }
 70}
 71
 72impl From<RpoDigest256> for [Felt; DIGEST_SIZE] {
 73    fn from(value: RpoDigest256) -> Self {
 74        value.0
 75    }
 76}
 77
 78impl From<RpoDigest256> for [u8; 32] {
 79    fn from(value: RpoDigest256) -> Self {
 80        value.as_bytes()
 81    }
 82}
 83
 84impl Deref for RpoDigest256 {
 85    type Target = [Felt; DIGEST_SIZE];
 86
 87    fn deref(&self) -> &Self::Target {
 88        &self.0
 89    }
 90}
 91
 92impl RpoDigest256 {
 93    fn iter(&self) -> RpoDigest256Iter<'_> {
 94        RpoDigest256Iter {
 95            values: &self.0,
 96            index: 0,
 97        }
 98    }
 99}
100
101pub struct RpoDigest256Iter<'a> {
102    values: &'a [Felt; DIGEST_SIZE],
103    index: usize,
104}
105
106impl<'a> Iterator for RpoDigest256Iter<'a> {
107    type Item = &'a Felt;
108
109    fn next(&mut self) -> Option<Self::Item> {
110        if self.index >= self.values.len() {
111            return None;
112        }
113
114        self.index += 1;
115        Some(&self.values[self.index - 1])
116    }
117}
118
119// TESTS
120// ================================================================================================
121
122#[cfg(test)]
123mod tests {
124
125    use super::RpoDigest256;
126    use crate::Felt;
127    use rand_utils::rand_value;
128    use winterfell::{Deserializable, Serializable, SliceReader};
129
130    #[test]
131    fn digest_serialization() {
132        let e1 = Felt::new(rand_value());
133        let e2 = Felt::new(rand_value());
134        let e3 = Felt::new(rand_value());
135        let e4 = Felt::new(rand_value());
136
137        let d1 = RpoDigest256([e1, e2, e3, e4]);
138
139        let mut bytes = vec![];
140        d1.write_into(&mut bytes);
141        assert_eq!(32, bytes.len());
142
143        let mut reader = SliceReader::new(&bytes);
144        let d2 = RpoDigest256::read_from(&mut reader).unwrap();
145
146        assert_eq!(d1, d2);
147    }
148}