p3_symmetric/
serializing_hasher.rs

1use core::iter;
2
3use p3_field::{PackedValue, PrimeField32, PrimeField64};
4
5use crate::CryptographicHasher;
6
7/// Serializes 32-bit field elements to bytes (i.e. the little-endian encoding of their canonical
8/// values), then hashes those bytes using some inner hasher, and outputs a `[u8; 32]`.
9#[derive(Copy, Clone, Debug)]
10pub struct SerializingHasher32<Inner> {
11    inner: Inner,
12}
13
14/// Serializes 32-bit field elements to u64s (packing two canonical values together), then hashes
15/// those u64s using some inner hasher, and outputs a `[u64; 4]`.
16#[derive(Copy, Clone, Debug)]
17pub struct SerializingHasher32To64<Inner> {
18    inner: Inner,
19}
20
21/// Serializes 64-bit field elements to bytes (i.e. the little-endian encoding of their canonical
22/// values), then hashes those bytes using some inner hasher, and outputs a `[u8; 32]`.
23#[derive(Copy, Clone, Debug)]
24pub struct SerializingHasher64<Inner> {
25    inner: Inner,
26}
27
28impl<Inner> SerializingHasher32<Inner> {
29    pub const fn new(inner: Inner) -> Self {
30        Self { inner }
31    }
32}
33
34impl<Inner> SerializingHasher32To64<Inner> {
35    pub const fn new(inner: Inner) -> Self {
36        Self { inner }
37    }
38}
39
40impl<Inner> SerializingHasher64<Inner> {
41    pub const fn new(inner: Inner) -> Self {
42        Self { inner }
43    }
44}
45
46impl<F, Inner> CryptographicHasher<F, [u8; 32]> for SerializingHasher32<Inner>
47where
48    F: PrimeField32,
49    Inner: CryptographicHasher<u8, [u8; 32]>,
50{
51    fn hash_iter<I>(&self, input: I) -> [u8; 32]
52    where
53        I: IntoIterator<Item = F>,
54    {
55        self.inner.hash_iter(
56            input
57                .into_iter()
58                .flat_map(|x| x.to_unique_u32().to_le_bytes()),
59        )
60    }
61}
62
63impl<P, PW, Inner> CryptographicHasher<P, [PW; 8]> for SerializingHasher32<Inner>
64where
65    P: PackedValue,
66    P::Value: PrimeField32,
67    PW: PackedValue<Value = u32>,
68    Inner: CryptographicHasher<PW, [PW; 8]>,
69{
70    fn hash_iter<I>(&self, input: I) -> [PW; 8]
71    where
72        I: IntoIterator<Item = P>,
73    {
74        self.inner.hash_iter(
75            input
76                .into_iter()
77                .map(|x| PW::from_fn(|i| x.as_slice()[i].to_unique_u32())),
78        )
79    }
80}
81
82impl<P, PW, Inner> CryptographicHasher<P, [PW; 4]> for SerializingHasher32To64<Inner>
83where
84    P: PackedValue,
85    P::Value: PrimeField32,
86    PW: PackedValue<Value = u64>,
87    Inner: CryptographicHasher<PW, [PW; 4]>,
88{
89    fn hash_iter<I>(&self, input: I) -> [PW; 4]
90    where
91        I: IntoIterator<Item = P>,
92    {
93        assert_eq!(P::WIDTH, PW::WIDTH);
94        let mut input = input.into_iter();
95        self.inner.hash_iter(iter::from_fn(
96            #[inline]
97            || {
98                let a = input.next();
99                let b = input.next();
100                if let (Some(a), Some(b)) = (a, b) {
101                    let ab = PW::from_fn(|i| {
102                        let a_i = a.as_slice()[i].to_unique_u64();
103                        let b_i = b.as_slice()[i].to_unique_u64();
104                        a_i | (b_i << 32)
105                    });
106                    Some(ab)
107                } else {
108                    a.map(|a| PW::from_fn(|i| a.as_slice()[i].to_unique_u64()))
109                }
110            },
111        ))
112    }
113}
114
115impl<F, Inner> CryptographicHasher<F, [u8; 32]> for SerializingHasher64<Inner>
116where
117    F: PrimeField64,
118    Inner: CryptographicHasher<u8, [u8; 32]>,
119{
120    fn hash_iter<I>(&self, input: I) -> [u8; 32]
121    where
122        I: IntoIterator<Item = F>,
123    {
124        self.inner.hash_iter(
125            input
126                .into_iter()
127                .flat_map(|x| x.to_unique_u64().to_le_bytes()),
128        )
129    }
130}
131
132impl<P, PW, Inner> CryptographicHasher<P, [PW; 4]> for SerializingHasher64<Inner>
133where
134    P: PackedValue,
135    P::Value: PrimeField64,
136    PW: PackedValue<Value = u64>,
137    Inner: CryptographicHasher<PW, [PW; 4]>,
138{
139    fn hash_iter<I>(&self, input: I) -> [PW; 4]
140    where
141        I: IntoIterator<Item = P>,
142    {
143        self.inner.hash_iter(
144            input
145                .into_iter()
146                .map(|x| PW::from_fn(|i| x.as_slice()[i].to_unique_u64())),
147        )
148    }
149}