nix_compat/nixhash/
serde.rs1use super::NixHash;
2use crate::nixbase32;
3use serde::{Deserialize, Serialize};
4use std::fmt::Formatter;
5
6impl<'de> Deserialize<'de> for NixHash {
7 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
8 where
9 D: serde::Deserializer<'de>,
10 {
11 use serde::de::{Error, Visitor};
12
13 struct NixHashVisitor;
14
15 impl Visitor<'_> for NixHashVisitor {
16 type Value = NixHash;
17
18 fn expecting(&self, formatter: &mut Formatter) -> std::fmt::Result {
19 formatter.write_str("a string representing a Nix hash")
20 }
21
22 fn visit_str<E>(self, s: &str) -> Result<Self::Value, E>
23 where
24 E: Error,
25 {
26 NixHash::from_str(s, None).map_err(|err| Error::custom(format!("{err}: {s:?}")))
27 }
28 }
29
30 deserializer.deserialize_str(NixHashVisitor)
31 }
32}
33
34impl Serialize for NixHash {
35 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
36 where
37 S: serde::Serializer,
38 {
39 let sri = self.to_sri_string();
40 sri.serialize(serializer)
41 }
42}
43
44const NIXBASE32_SHA256_ENCODE_LEN: usize = nixbase32::encode_len(32);
46
47pub fn from_nix_nixbase32_or_sri<'de, D>(deserializer: D) -> Result<[u8; 32], D::Error>
48where
49 D: serde::Deserializer<'de>,
50{
51 let str: &'de str = Deserialize::deserialize(deserializer)?;
52 if let Some(digest_str) = str.strip_prefix("sha256:") {
53 return from_nix_nixbase32::<D>(digest_str);
54 }
55 if let Some(digest_str) = str.strip_prefix("sha256-") {
56 return from_sri::<D>(digest_str);
57 }
58 Err(serde::de::Error::invalid_value(
59 serde::de::Unexpected::Str(str),
60 &"extected a valid nixbase32 or sri narHash",
61 ))
62}
63
64pub fn from_sri<'de, D>(str: &str) -> Result<[u8; 32], D::Error>
65where
66 D: serde::Deserializer<'de>,
67{
68 let digest: [u8; 32] = data_encoding::BASE64
69 .decode(str.as_bytes())
70 .map_err(|_| {
71 serde::de::Error::invalid_value(
72 serde::de::Unexpected::Str(str),
73 &"valid base64 encoded string",
74 )
75 })?
76 .try_into()
77 .map_err(|_| {
78 serde::de::Error::invalid_value(serde::de::Unexpected::Str(str), &"valid digest len")
79 })?;
80
81 Ok(digest)
82}
83
84pub fn from_nix_nixbase32<'de, D>(str: &str) -> Result<[u8; 32], D::Error>
85where
86 D: serde::Deserializer<'de>,
87{
88 let digest_str: [u8; NIXBASE32_SHA256_ENCODE_LEN] =
89 str.as_bytes().try_into().map_err(|_| {
90 serde::de::Error::invalid_value(serde::de::Unexpected::Str(str), &"valid digest len")
91 })?;
92
93 let digest: [u8; 32] = nixbase32::decode_fixed(digest_str).map_err(|_| {
94 serde::de::Error::invalid_value(serde::de::Unexpected::Str(str), &"valid nixbase32")
95 })?;
96
97 Ok(digest)
98}
99
100pub fn to_nix_nixbase32<S>(v: &[u8; 32], serializer: S) -> Result<S::Ok, S::Error>
101where
102 S: serde::Serializer,
103{
104 let string = NixHash::Sha256(*v).to_nix_nixbase32();
105 string.serialize(serializer)
106}