1use std::hash::{DefaultHasher, Hasher};
14
15#[cfg(feature = "shake256")]
16use sha3::Shake256;
17#[cfg(feature = "shake256")]
18use sha3::digest::{ExtendableOutput, Update as XofUpdate, XofReader};
19
20pub mod english_word;
21
22pub trait ByteReader {
28 fn read(&mut self, dest: &mut [u8]) -> usize;
30
31 fn remaining(&self) -> Option<usize>;
33}
34
35pub trait ReadableHasher: Default {
37 type Reader: ByteReader;
38
39 fn update(&mut self, data: &[u8]);
40 fn finalize(self) -> Self::Reader;
41}
42
43#[derive(Default)]
48pub struct StdHasher<H: Hasher + Default = DefaultHasher> {
49 hasher: H,
50}
51
52impl<H: Hasher + Default> ReadableHasher for StdHasher<H> {
53 type Reader = StdHasherReader;
54
55 fn update(&mut self, data: &[u8]) {
56 self.hasher.write(data);
57 }
58
59 fn finalize(self) -> Self::Reader {
60 StdHasherReader {
61 bytes: self.hasher.finish().to_le_bytes(),
62 position: 0,
63 }
64 }
65}
66
67pub struct StdHasherReader {
68 bytes: [u8; 8],
69 position: usize,
70}
71
72impl ByteReader for StdHasherReader {
73 fn read(&mut self, dest: &mut [u8]) -> usize {
74 let available = 8 - self.position;
75 let bytes_to_read = dest.len().min(available);
76 dest[..bytes_to_read]
77 .copy_from_slice(&self.bytes[self.position..self.position + bytes_to_read]);
78 self.position += bytes_to_read;
79 bytes_to_read
80 }
81
82 fn remaining(&self) -> Option<usize> {
83 Some(8 - self.position)
84 }
85}
86
87#[cfg(feature = "shake256")]
92#[derive(Default)]
93pub struct Shake256Hasher {
94 hasher: Shake256,
95}
96
97#[cfg(feature = "shake256")]
98impl ReadableHasher for Shake256Hasher {
99 type Reader = Shake256Reader;
100
101 fn update(&mut self, data: &[u8]) {
102 XofUpdate::update(&mut self.hasher, data);
103 }
104
105 fn finalize(self) -> Self::Reader {
106 Shake256Reader {
107 reader: self.hasher.finalize_xof(),
108 }
109 }
110}
111
112#[cfg(feature = "shake256")]
113pub struct Shake256Reader {
114 reader: sha3::Shake256Reader,
115}
116
117#[cfg(feature = "shake256")]
118impl ByteReader for Shake256Reader {
119 fn read(&mut self, dest: &mut [u8]) -> usize {
120 XofReader::read(&mut self.reader, dest);
121 dest.len()
122 }
123
124 fn remaining(&self) -> Option<usize> {
125 None
126 }
127}
128
129pub struct SliceReader<'a> {
135 data: &'a [u8],
136 position: usize,
137}
138
139impl<'a> SliceReader<'a> {
140 pub fn new(data: &'a [u8]) -> Self {
141 Self { data, position: 0 }
142 }
143}
144
145impl<'a> ByteReader for SliceReader<'a> {
146 fn read(&mut self, dest: &mut [u8]) -> usize {
147 let available = self.data.len() - self.position;
148 let bytes_to_read = dest.len().min(available);
149 dest[..bytes_to_read]
150 .copy_from_slice(&self.data[self.position..self.position + bytes_to_read]);
151 self.position += bytes_to_read;
152 bytes_to_read
153 }
154
155 fn remaining(&self) -> Option<usize> {
156 Some(self.data.len() - self.position)
157 }
158}
159
160pub fn english_word_hash<H, T>(input: T) -> String
182where
183 H: ReadableHasher,
184 T: AsRef<[u8]>,
185{
186 let input_bytes = input.as_ref();
187 if input_bytes.is_empty() {
188 return String::new();
189 }
190 let input_len = input_bytes.len();
191
192 let mut hasher = H::default();
193 hasher.update(input_bytes);
194 let reader = hasher.finalize();
195
196 let bytes_limit = match reader.remaining() {
198 Some(_) => None, None => Some(input_len.max(8)), };
201
202 let mut limited_reader = LimitedByteReader::new(reader, bytes_limit);
203 english_word::generate_word_with_target_len(&mut limited_reader, input_len)
204}
205
206struct LimitedByteReader<R: ByteReader> {
208 inner: R,
209 remaining: Option<usize>,
210}
211
212impl<R: ByteReader> LimitedByteReader<R> {
213 fn new(inner: R, limit: Option<usize>) -> Self {
214 Self {
215 inner,
216 remaining: limit,
217 }
218 }
219}
220
221impl<R: ByteReader> ByteReader for LimitedByteReader<R> {
222 fn read(&mut self, dest: &mut [u8]) -> usize {
223 let max_read = match self.remaining {
224 Some(0) => return 0,
225 Some(remaining) => dest.len().min(remaining),
226 None => dest.len(),
227 };
228
229 let bytes_read = self.inner.read(&mut dest[..max_read]);
230 if let Some(ref mut remaining) = self.remaining {
231 *remaining = remaining.saturating_sub(bytes_read);
232 }
233 bytes_read
234 }
235
236 fn remaining(&self) -> Option<usize> {
237 match (self.remaining, self.inner.remaining()) {
238 (Some(limit), Some(inner_remaining)) => Some(limit.min(inner_remaining)),
239 (Some(limit), None) => Some(limit),
240 (None, inner_remaining) => inner_remaining,
241 }
242 }
243}