bee_crypto/ternary/
hash.rs1use bee_ternary::{raw::RawEncoding, Btrit, Trits, T1B1};
5
6use std::{
7 cmp::PartialEq,
8 fmt, hash,
9 ops::{Deref, DerefMut},
10};
11
12#[derive(Debug)]
13pub enum Error {
14 WrongLength,
15}
16
17pub const HASH_LENGTH: usize = 243;
19
20#[derive(Copy, Clone)]
22pub struct Hash([Btrit; HASH_LENGTH]);
23
24impl Hash {
25 pub fn zeros() -> Self {
27 Self([Btrit::Zero; HASH_LENGTH])
28 }
29
30 pub fn as_trits(&self) -> &Trits<T1B1> {
32 &*self
33 }
34
35 pub fn as_trits_mut(&mut self) -> &mut Trits<T1B1> {
37 &mut *self
38 }
39
40 #[allow(clippy::cast_possible_truncation)] pub fn weight(&self) -> u8 {
43 self.iter().rev().take_while(|t| *t == Btrit::Zero).count() as u8
44 }
45}
46
47impl<'a, T: RawEncoding<Trit = Btrit>> TryFrom<&'a Trits<T>> for Hash {
48 type Error = Error;
49
50 fn try_from(trits: &'a Trits<T>) -> Result<Self, Self::Error> {
51 if trits.len() == HASH_LENGTH {
52 let mut hash = Self([Btrit::Zero; HASH_LENGTH]);
53 hash.copy_from(trits);
54 Ok(hash)
55 } else {
56 Err(Error::WrongLength)
57 }
58 }
59}
60
61impl Deref for Hash {
62 type Target = Trits<T1B1>;
63
64 fn deref(&self) -> &Trits<T1B1> {
65 <&Trits>::from(&self.0 as &[_])
66 }
67}
68
69impl DerefMut for Hash {
70 fn deref_mut(&mut self) -> &mut Trits<T1B1> {
71 <&mut Trits>::from(&mut self.0 as &mut [_])
72 }
73}
74
75impl PartialEq for Hash {
76 fn eq(&self, other: &Self) -> bool {
77 self.as_trits() == other.as_trits()
78 }
79}
80
81impl Eq for Hash {}
82
83impl fmt::Display for Hash {
84 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
85 fmt::Debug::fmt(self, f)
86 }
87}
88
89impl fmt::Debug for Hash {
90 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
91 write!(f, "{:?}", self.as_trits())
92 }
93}
94
95impl hash::Hash for Hash {
96 fn hash<H: hash::Hasher>(&self, hasher: &mut H) {
97 self.0.hash(hasher)
98 }
99}