1use serde::{Deserialize, Deserializer, Serialize, Serializer, de};
4use std::{collections::BTreeMap, marker::PhantomData};
5
6#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Default)]
12pub struct Hash<K: HashKind>([u8; 32], PhantomData<K>);
13
14impl<K: HashKind> Serialize for Hash<K> {
15 fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
16 if serializer.is_human_readable() {
17 serializer.collect_str(self)
18 } else {
19 self.0.serialize(serializer)
20 }
21 }
22}
23
24impl<'de, K: HashKind> Deserialize<'de> for Hash<K> {
25 fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
26 if deserializer.is_human_readable() {
27 let hex = String::deserialize(deserializer)?;
28 blake3::Hash::from_hex(&hex)
29 .map(|hash| Self(*hash.as_bytes(), PhantomData))
30 .map_err(de::Error::custom)
31 } else {
32 <[u8; 32]>::deserialize(deserializer).map(|bytes| Self(bytes, PhantomData))
33 }
34 }
35}
36
37impl<K: HashKind> std::fmt::Debug for Hash<K> {
38 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
39 write!(f, "{:x?}", self.0)
40 }
41}
42
43impl<K: HashKind> std::fmt::Display for Hash<K> {
44 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
45 for byte in self.0 {
46 write!(f, "{byte:02x}")?;
47 }
48 Ok(())
49 }
50}
51
52impl<K: HashKind> Hash<K> {
53 pub fn of(bytes: &[u8]) -> Self {
56 let mut hasher = Hasher::<K>::new();
57 hasher.update(bytes);
58 hasher.finalize()
59 }
60
61 pub const fn bytes(&self) -> [u8; 32] {
65 self.0
66 }
67
68 pub fn from_hex(text: &str) -> Option<Self> {
71 blake3::Hash::from_hex(text)
72 .ok()
73 .map(|hash| Self(*hash.as_bytes(), PhantomData))
74 }
75}
76
77pub trait HashKind {}
78
79pub struct Hasher<K: HashKind>(blake3::Hasher, PhantomData<K>);
80
81impl<K: HashKind> Default for Hasher<K> {
82 fn default() -> Self {
83 Self::new()
84 }
85}
86
87impl<K: HashKind> Hasher<K> {
88 pub fn new() -> Self {
89 Self(blake3::Hasher::new(), PhantomData)
90 }
91 pub fn update(&mut self, input: &[u8]) -> &mut Self {
92 self.0.update(input);
93 self
94 }
95 pub fn finalize(&self) -> Hash<K> {
96 Hash(self.0.finalize().into(), PhantomData)
97 }
98}
99
100impl<K: HashKind> std::io::Write for Hasher<K> {
102 fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
103 self.0.update(buf);
104 Ok(buf.len())
105 }
106 fn flush(&mut self) -> std::io::Result<()> {
107 Ok(())
108 }
109}
110
111pub type HashedMap<K, T> = BTreeMap<Hash<K>, T>;
112
113#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Default)]
114pub struct AssetKind;
115
116impl HashKind for AssetKind {}
117
118pub type AssetHash = Hash<AssetKind>;
119
120#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Default)]
121pub struct DocKind;
122
123impl HashKind for DocKind {}
124
125pub type DocHash = Hash<DocKind>;