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}