wasmer_types/
module_hash.rs

1use std::fmt::{self, Display, Formatter};
2
3use rkyv::{Archive, Deserialize as RkyvDeserialize, Serialize as RkyvSerialize};
4#[cfg(feature = "enable-serde")]
5use serde::{Deserialize, Serialize};
6use sha2::Digest;
7
8/// Hashing algorithm to be used for the module info
9#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
10pub enum HashAlgorithm {
11    /// Sha256
12    Sha256,
13    /// XXHash
14    XXHash,
15}
16
17/// The hash of a WebAssembly module.
18#[derive(
19    Debug,
20    Copy,
21    Clone,
22    PartialEq,
23    Eq,
24    Hash,
25    PartialOrd,
26    Ord,
27    RkyvSerialize,
28    RkyvDeserialize,
29    Archive,
30)]
31#[rkyv(derive(Debug))]
32#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
33pub enum ModuleHash {
34    /// xxhash
35    XXHash([u8; 8]),
36
37    /// sha256
38    Sha256([u8; 32]),
39}
40
41#[cfg(feature = "artifact-size")]
42impl loupe::MemoryUsage for ModuleHash {
43    fn size_of_val(&self, _tracker: &mut dyn loupe::MemoryUsageTracker) -> usize {
44        match self {
45            ModuleHash::XXHash(_) => 8 * 8,
46            ModuleHash::Sha256(_) => 8 * 32,
47        }
48    }
49}
50
51impl ModuleHash {
52    /// Create a new [`ModuleHash`] from the raw xxhash hash.
53    pub fn xxhash_from_bytes(key: [u8; 8]) -> Self {
54        Self::XXHash(key)
55    }
56
57    /// Create a new [`ModuleHash`] from the raw sha256 hash.
58    pub fn sha256_from_bytes(key: [u8; 32]) -> Self {
59        Self::Sha256(key)
60    }
61
62    /// Parse a XXHash hash from a hex-encoded string.
63    pub fn xxhash_parse_hex(hex_str: &str) -> Result<Self, hex::FromHexError> {
64        let mut hash = [0_u8; 8];
65        hex::decode_to_slice(hex_str, &mut hash)?;
66        Ok(Self::xxhash_from_bytes(hash))
67    }
68
69    /// Parse a Sha256 hash from a hex-encoded string.
70    pub fn sha256_parse_hex(hex_str: &str) -> Result<Self, hex::FromHexError> {
71        let mut hash = [0_u8; 32];
72        hex::decode_to_slice(hex_str, &mut hash)?;
73        Ok(Self::sha256_from_bytes(hash))
74    }
75
76    /// Generate a new [`ModuleCache`] based on the XXHash hash of some bytes.
77    pub fn xxhash(wasm: impl AsRef<[u8]>) -> Self {
78        let wasm = wasm.as_ref();
79
80        let hash = xxhash_rust::xxh64::xxh64(wasm, 0);
81
82        Self::XXHash(hash.to_ne_bytes())
83    }
84
85    /// Generate a new [`ModuleCache`] based on the Sha256 hash of some bytes.
86    pub fn sha256(wasm: impl AsRef<[u8]>) -> Self {
87        let wasm = wasm.as_ref();
88
89        let hash: [u8; 32] = sha2::Sha256::digest(wasm).into();
90
91        Self::Sha256(hash)
92    }
93
94    /// Get the raw hash.
95    pub fn as_bytes(&self) -> &[u8] {
96        match self {
97            Self::XXHash(bytes) => bytes.as_slice(),
98            Self::Sha256(bytes) => bytes.as_slice(),
99        }
100    }
101}
102
103impl Display for ModuleHash {
104    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
105        fn format<const N: usize>(f: &mut Formatter<'_>, bytes: &[u8; N]) -> fmt::Result {
106            for byte in bytes {
107                write!(f, "{byte:02X}")?;
108            }
109
110            Ok(())
111        }
112
113        match self {
114            Self::XXHash(bytes) => format(f, bytes)?,
115            Self::Sha256(bytes) => format(f, bytes)?,
116        }
117
118        Ok(())
119    }
120}