crypto/hashes/ternary/
mod.rs1#[cfg(feature = "curl-p")]
7#[cfg_attr(docsrs, doc(cfg(feature = "curl-p")))]
8pub mod curl_p;
9
10#[cfg(feature = "kerl_deprecated_do_not_use")]
11#[cfg_attr(docsrs, doc(cfg(feature = "kerl_deprecated_do_not_use")))]
12#[cfg_attr(not(test), deprecated)]
13pub mod kerl;
14
15pub const HASH_LENGTH: usize = 243;
17pub const HASH_LENGTH_TRYTES: usize = 243 / 3;
19
20use core::ops::DerefMut;
21
22use crate::encoding::ternary::{raw::RawEncoding, Btrit, TritBuf, Trits, T1B1};
23
24pub trait Sponge {
26 type Error;
28
29 fn reset(&mut self);
31
32 fn absorb(&mut self, input: &Trits) -> Result<(), Self::Error>;
34
35 fn squeeze_into(&mut self, buf: &mut Trits) -> Result<(), Self::Error>;
37
38 fn squeeze(&mut self) -> Result<TritBuf, Self::Error> {
40 let mut output = TritBuf::zeros(HASH_LENGTH);
41 self.squeeze_into(&mut output)?;
42 Ok(output)
43 }
44
45 fn digest_into(&mut self, input: &Trits, buf: &mut Trits) -> Result<(), Self::Error> {
47 self.absorb(input)?;
48 self.squeeze_into(buf)?;
49 self.reset();
50 Ok(())
51 }
52
53 fn digest(&mut self, input: &Trits) -> Result<TritBuf, Self::Error> {
55 self.absorb(input)?;
56 let output = self.squeeze()?;
57 self.reset();
58 Ok(output)
59 }
60}
61
62impl<T: Sponge, U: DerefMut<Target = T>> Sponge for U {
63 type Error = T::Error;
64
65 fn reset(&mut self) {
66 T::reset(self)
67 }
68
69 fn absorb(&mut self, input: &Trits) -> Result<(), Self::Error> {
70 T::absorb(self, input)
71 }
72
73 fn squeeze_into(&mut self, buf: &mut Trits) -> Result<(), Self::Error> {
74 T::squeeze_into(self, buf)
75 }
76}
77
78#[derive(Debug)]
79pub enum HashError {
80 WrongLength,
81}
82
83#[derive(Copy, Clone)]
85pub struct Hash([Btrit; HASH_LENGTH]);
86
87impl Hash {
88 pub fn zeros() -> Self {
90 Self([Btrit::Zero; HASH_LENGTH])
91 }
92
93 pub fn as_trits(&self) -> &Trits<T1B1> {
95 self
96 }
97
98 pub fn as_trits_mut(&mut self) -> &mut Trits<T1B1> {
100 &mut *self
101 }
102
103 #[allow(clippy::cast_possible_truncation)] pub fn weight(&self) -> u8 {
106 self.iter().rev().take_while(|t| *t == Btrit::Zero).count() as u8
107 }
108}
109
110impl<'a, T: RawEncoding<Trit = Btrit>> core::convert::TryFrom<&'a Trits<T>> for Hash {
111 type Error = HashError;
112
113 fn try_from(trits: &'a Trits<T>) -> Result<Self, Self::Error> {
114 if trits.len() == HASH_LENGTH {
115 let mut hash = Self([Btrit::Zero; HASH_LENGTH]);
116 hash.copy_from(trits);
117 Ok(hash)
118 } else {
119 Err(HashError::WrongLength)
120 }
121 }
122}
123
124impl core::ops::Deref for Hash {
125 type Target = Trits<T1B1>;
126
127 fn deref(&self) -> &Trits<T1B1> {
128 <&Trits>::from(&self.0 as &[_])
129 }
130}
131
132impl DerefMut for Hash {
133 fn deref_mut(&mut self) -> &mut Trits<T1B1> {
134 <&mut Trits>::from(&mut self.0 as &mut [_])
135 }
136}
137
138impl PartialEq for Hash {
139 fn eq(&self, other: &Self) -> bool {
140 self.as_trits() == other.as_trits()
141 }
142}
143
144impl Eq for Hash {}
145
146impl core::fmt::Display for Hash {
147 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
148 core::fmt::Debug::fmt(self, f)
149 }
150}
151
152impl core::fmt::Debug for Hash {
153 fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
154 write!(f, "{:?}", self.as_trits())
155 }
156}
157
158impl core::hash::Hash for Hash {
159 fn hash<H: core::hash::Hasher>(&self, hasher: &mut H) {
160 self.0.hash(hasher)
161 }
162}