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
97impl RpoDigest256 {
98 fn iter(&self) -> RpoDigest256Iter<'_> {
99 RpoDigest256Iter {
100 values: &self.0,
101 index: 0,
102 }
103 }
104}
105
106pub struct RpoDigest256Iter<'a> {
107 values: &'a [Felt; DIGEST_SIZE],
108 index: usize,
109}
110
111impl<'a> Iterator for RpoDigest256Iter<'a> {
112 type Item = &'a Felt;
113
114 fn next(&mut self) -> Option<Self::Item> {
115 if self.index >= self.values.len() {
116 return None;
117 }
118
119 self.index += 1;
120 Some(&self.values[self.index - 1])
121 }
122}
123
124// TESTS
125// ================================================================================================
126
127#[cfg(test)]
128mod tests {
129
130 use super::RpoDigest256;
131 use crate::{Deserializable, Felt, Serializable, SliceReader};
132 use rand_utils::rand_value;
133
134 #[test]
135 fn digest_serialization() {
136 let e1 = Felt::new(rand_value());
137 let e2 = Felt::new(rand_value());
138 let e3 = Felt::new(rand_value());
139 let e4 = Felt::new(rand_value());
140
141 let d1 = RpoDigest256([e1, e2, e3, e4]);
142
143 let mut bytes = vec![];
144 d1.write_into(&mut bytes);
145 assert_eq!(32, bytes.len());
146
147 let mut reader = SliceReader::new(&bytes);
148 let d2 = RpoDigest256::read_from(&mut reader).unwrap();
149
150 assert_eq!(d1, d2);
151 }
152}