wasmer_config/
hash.rs

1/// Sha256 hash, represented as bytes.
2#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
3pub struct Sha256Hash(pub [u8; 32]);
4
5impl Sha256Hash {
6    pub fn as_bytes(&self) -> &[u8; 32] {
7        &self.0
8    }
9
10    pub fn from_bytes(bytes: [u8; 32]) -> Self {
11        Self(bytes)
12    }
13}
14
15impl std::str::FromStr for Sha256Hash {
16    type Err = Sha256HashParseError;
17
18    fn from_str(s: &str) -> Result<Self, Self::Err> {
19        if s.len() != 64 {
20            return Err(Sha256HashParseError {
21                value: s.to_string(),
22                message: "invalid hash length - hash must have 64 hex-encoded characters "
23                    .to_string(),
24            });
25        }
26
27        let bytes = hex::decode(s).map_err(|e| Sha256HashParseError {
28            value: s.to_string(),
29            message: e.to_string(),
30        })?;
31
32        Ok(Sha256Hash(bytes.try_into().unwrap()))
33    }
34}
35
36impl std::fmt::Debug for Sha256Hash {
37    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
38        write!(f, "Sha256({})", hex::encode(self.0))
39    }
40}
41
42impl std::fmt::Display for Sha256Hash {
43    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
44        write!(f, "{}", hex::encode(self.0))
45    }
46}
47
48impl schemars::JsonSchema for Sha256Hash {
49    fn schema_name() -> String {
50        "Sha256Hash".to_string()
51    }
52
53    fn json_schema(gen: &mut schemars::gen::SchemaGenerator) -> schemars::schema::Schema {
54        String::json_schema(gen)
55    }
56}
57
58#[derive(Clone, Debug)]
59pub struct Sha256HashParseError {
60    value: String,
61    message: String,
62}
63
64impl std::fmt::Display for Sha256HashParseError {
65    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
66        write!(
67            f,
68            "could not parse value as sha256 hash: {} (value: '{}')",
69            self.message, self.value
70        )
71    }
72}
73
74impl std::error::Error for Sha256HashParseError {}
75
76#[cfg(test)]
77mod tests {
78    use super::*;
79
80    #[test]
81    fn hash_sha256_parse_roundtrip() {
82        let input = "c355cd53795b9b481f7eb2b5f4f6c8cf73631bdc343723a579d671e32db70b3c";
83        let h1 = input
84            .parse::<Sha256Hash>()
85            .expect("string should parse to hash");
86
87        assert_eq!(
88            h1.0,
89            [
90                195, 85, 205, 83, 121, 91, 155, 72, 31, 126, 178, 181, 244, 246, 200, 207, 115, 99,
91                27, 220, 52, 55, 35, 165, 121, 214, 113, 227, 45, 183, 11, 60
92            ],
93        );
94
95        assert_eq!(h1.to_string(), input);
96    }
97
98    #[test]
99    fn hash_sha256_parse_fails() {
100        let res1 =
101            "c355cd53795b9b481f7eb2b5f4f6c8cf73631bdc343723a579d671e32db70b3".parse::<Sha256Hash>();
102        assert!(res1.is_err());
103
104        let res2 = "".parse::<Sha256Hash>();
105        assert!(res2.is_err());
106
107        let res3 = "öööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööööö"
108            .parse::<Sha256Hash>();
109        assert!(res3.is_err());
110    }
111}