wasm_hash_verifier/
xand_hash.rs1use crate::xand_hash::v1::V1XandHash;
2use alloc::vec::Vec;
3use postcard::{from_bytes, to_allocvec};
4use serde::{Deserialize, Deserializer, Serialize, Serializer};
5
6pub mod v1;
7
8#[non_exhaustive]
11#[derive(Clone, Debug, Eq, Hash, PartialEq)]
12pub enum XandHash {
13 V1(V1XandHash),
14}
15
16#[derive(Serialize, Deserialize)]
19struct SerdeXandHash {
20 variant: u8,
21 inner: Vec<u8>,
22}
23
24#[allow(clippy::fallible_impl_from)]
25impl From<SerdeXandHash> for XandHash {
26 fn from(serde_xand_hash: SerdeXandHash) -> Self {
27 match serde_xand_hash.variant {
28 1 => {
29 let contents = from_bytes(&serde_xand_hash.inner).expect("Should never fail: see prop tests");
30 Self::V1(contents)
31 }
32 _ => unimplemented!("Invalid SerdeXandHash: no variant {:?}", serde_xand_hash.variant),
33 }
34 }
35}
36
37#[allow(unreachable_patterns, clippy::fallible_impl_from)]
38impl From<&XandHash> for SerdeXandHash {
39 fn from(xand_hash: &XandHash) -> Self {
40 match xand_hash {
41 XandHash::V1(contents) => {
42 let variant = 1;
43 let inner = to_allocvec(&contents).expect("Should never fail: see prop tests");
44 Self { variant, inner }
45 }
46 _ => unreachable!("Add new variants here as needed"),
47 }
48 }
49}
50
51impl Serialize for XandHash {
52 fn serialize<S>(&self, serializer: S) -> Result<<S as Serializer>::Ok, <S as Serializer>::Error>
53 where
54 S: Serializer,
55 {
56 let serde_xand_hash: SerdeXandHash = self.into();
57 serde_xand_hash.serialize(serializer)
58 }
59}
60
61impl<'de> Deserialize<'de> for XandHash {
62 fn deserialize<D>(deserializer: D) -> Result<Self, <D as Deserializer<'de>>::Error>
63 where
64 D: Deserializer<'de>,
65 {
66 let serde_hash: SerdeXandHash = Deserialize::deserialize(deserializer)?;
67 Ok(serde_hash.into())
68 }
69}
70
71#[cfg(test)]
72impl XandHash {
73 #[must_use]
74 pub const fn new(inner: blake3::Hash) -> Self {
75 Self::V1(V1XandHash::new(inner))
76 }
77}
78
79#[cfg(test)]
80mod tests {
81 use super::*;
82 use proptest::prelude::*;
83
84 prop_compose! {
85 fn arbitrary_xand_hash()(
86 bytes: [u8;32]
87 ) -> XandHash {
88 let blake3_hash = bytes.into();
89 XandHash::new(blake3_hash)
90 }
91 }
92
93 proptest! {
94 #[test]
95 fn v1__round_trip_serialization_deserialization(
96 expected in arbitrary_xand_hash()
97 ) {
98 let serialized = bincode::serialize(&expected).unwrap();
99 let actual: XandHash = bincode::deserialize(&serialized).unwrap();
100 assert_eq!(expected, actual);
101 }
102 }
103}