wasmer_config/package/
package_hash.rs1use crate::{hash::Sha256Hash, package::PackageParseError};
2
3#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
7#[non_exhaustive]
8pub enum PackageHash {
9 Sha256(Sha256Hash),
10}
11
12impl PackageHash {
13 const SHA256_STR_PREFIX: &'static str = "sha256:";
14
15 pub fn as_sha256(&self) -> Option<&Sha256Hash> {
16 match self {
17 PackageHash::Sha256(hash) => Some(hash),
18 }
19 }
20
21 pub fn from_sha256_bytes(bytes: [u8; 32]) -> Self {
22 Self::Sha256(Sha256Hash(bytes))
23 }
24}
25
26impl From<Sha256Hash> for PackageHash {
27 fn from(value: Sha256Hash) -> Self {
28 Self::Sha256(value)
29 }
30}
31
32impl std::fmt::Display for PackageHash {
33 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
34 match self {
35 Self::Sha256(hash) => write!(f, "sha256:{hash}"),
36 }
37 }
38}
39
40impl std::str::FromStr for PackageHash {
41 type Err = PackageParseError;
42
43 fn from_str(s: &str) -> Result<Self, Self::Err> {
44 if !s.starts_with(Self::SHA256_STR_PREFIX) {
45 return Err(PackageParseError::new(
46 s,
47 "package hashes must start with 'sha256:'",
48 ));
49 }
50 let hash = Sha256Hash::from_str(&s[Self::SHA256_STR_PREFIX.len()..])
51 .map_err(|e| PackageParseError::new(s, e.to_string()))?;
52
53 Ok(Self::Sha256(hash))
54 }
55}
56
57impl serde::Serialize for PackageHash {
58 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
59 where
60 S: serde::Serializer,
61 {
62 serializer.serialize_str(&self.to_string())
63 }
64}
65
66impl<'de> serde::Deserialize<'de> for PackageHash {
67 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
68 where
69 D: serde::Deserializer<'de>,
70 {
71 let s = String::deserialize(deserializer)?;
72 s.parse::<Self>()
73 .map_err(|e| serde::de::Error::custom(e.to_string()))
74 }
75}
76
77impl schemars::JsonSchema for PackageHash {
78 fn schema_name() -> String {
79 "PackageHash".to_string()
80 }
81
82 fn json_schema(gen: &mut schemars::gen::SchemaGenerator) -> schemars::schema::Schema {
83 String::json_schema(gen)
84 }
85}
86
87#[cfg(test)]
88mod tests {
89 use super::*;
90
91 #[test]
92 fn parse_package_hash_roundtrip() {
93 let input = "sha256:c355cd53795b9b481f7eb2b5f4f6c8cf73631bdc343723a579d671e32db70b3c";
94 let h1 = input
95 .parse::<PackageHash>()
96 .expect("string should parse to hash");
97
98 assert_eq!(
99 h1.as_sha256().unwrap().as_bytes(),
100 &[
101 195, 85, 205, 83, 121, 91, 155, 72, 31, 126, 178, 181, 244, 246, 200, 207, 115, 99,
102 27, 220, 52, 55, 35, 165, 121, 214, 113, 227, 45, 183, 11, 60
103 ],
104 );
105
106 assert_eq!(h1.to_string(), input);
107 }
108
109 #[test]
110 fn package_hash_serde_roundtrip() {
111 let input = "sha256:c355cd53795b9b481f7eb2b5f4f6c8cf73631bdc343723a579d671e32db70b3c";
112 let h1 = input
113 .parse::<PackageHash>()
114 .expect("string should parse to hash");
115
116 assert_eq!(
118 serde_json::to_value(&h1).unwrap(),
119 serde_json::Value::String(input.to_owned()),
120 );
121
122 let v = serde_json::to_string(&h1).unwrap();
124 let h2 = serde_json::from_str::<PackageHash>(&v).unwrap();
125
126 assert_eq!(h1, h2);
127 }
128}