1use bytes::Bytes;
2
3#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
7pub struct Bash(blake3::Hash);
8
9impl Bash {
10 pub const LEN: usize = 32;
11 const SEPARATOR: u8 = 0u8;
12
13 pub fn new(components: &[&[u8]]) -> Self {
14 let mut hasher = blake3::Hasher::new();
15 for component in components {
16 hasher.update(component);
17 hasher.update(&[Self::SEPARATOR]);
18 }
19 Self(hasher.finalize())
20 }
21
22 pub fn as_bytes(&self) -> &[u8; Bash::LEN] {
23 self.0.as_bytes()
24 }
25}
26
27impl std::fmt::Display for Bash {
28 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
29 f.write_str(self.0.to_hex().as_str())
30 }
31}
32
33impl AsRef<[u8]> for Bash {
34 fn as_ref(&self) -> &[u8] {
35 self.as_bytes()
36 }
37}
38
39impl From<Bash> for [u8; Bash::LEN] {
40 fn from(bash: Bash) -> Self {
41 bash.0.into()
42 }
43}
44
45impl From<[u8; Bash::LEN]> for Bash {
46 fn from(bytes: [u8; Bash::LEN]) -> Self {
47 Self(blake3::Hash::from_bytes(bytes))
48 }
49}
50
51impl From<Bash> for Bytes {
52 fn from(bash: Bash) -> Self {
53 Bytes::copy_from_slice(bash.as_bytes())
54 }
55}
56
57impl serde::Serialize for Bash {
58 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
59 where
60 S: serde::Serializer,
61 {
62 serializer.serialize_str(&self.0.to_hex())
63 }
64}
65
66impl<'de> serde::Deserialize<'de> for Bash {
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 let hash = blake3::Hash::from_hex(s.as_bytes()).map_err(serde::de::Error::custom)?;
73 Ok(Self(hash))
74 }
75}