1#![cfg_attr(not(feature = "std"), no_std)]
6
7#[macro_use]
8extern crate serde_derive;
9#[macro_use]
10extern crate static_assertions;
11
12use crate::error::*;
13#[cfg(feature = "std")]
14mod util;
15pub mod error;
16
17#[cfg(feature = "std")]
18use crate::util::hex_serde::{hex_from_bytes, vec_from_hex};
19use arrayvec::ArrayVec;
20pub use blake3::{hash as blake3, Hash as Blake3Hash, OUT_LEN as BLAKE3_OUT_LEN};
21use core::borrow::Borrow;
22use core::iter::FromIterator;
23
24#[cfg(feature = "std")]
25use std::io::Write;
26
27use varu64::{decode as varu64_decode, encode as varu64_encode, encoding_length};
28
29pub const BLAKE3_HASH_SIZE: usize = 32;
30const_assert_eq!(blake3_hash_size; BLAKE3_HASH_SIZE, BLAKE3_OUT_LEN);
33
34pub const BLAKE3_NUMERIC_ID: u64 = 0;
35
36pub const MAX_YAMF_HASH_SIZE: usize = BLAKE3_HASH_SIZE + 2;
42
43#[derive(Deserialize, Serialize, Debug, Eq, Clone)]
45pub enum YasmfHash<T: Borrow<[u8]> + Clone> {
46 #[cfg_attr(
47 feature = "std",
48 serde(serialize_with = "hex_from_bytes", deserialize_with = "vec_from_hex")
49 )]
50 #[cfg_attr(feature = "std", serde(bound(deserialize = "T: From<Vec<u8>>")))]
51 Blake3(T),
52}
53
54impl<B1: Borrow<[u8]> + Clone, B2: Borrow<[u8]> + Clone> PartialEq<YasmfHash<B1>> for YasmfHash<B2> {
55 fn eq(&self, other: &YasmfHash<B1>) -> bool {
56 match (self, other) {
57 (YasmfHash::Blake3(vec), YasmfHash::Blake3(vec2)) => vec.borrow() == vec2.borrow(),
58 }
59 }
60}
61
62pub fn new_blake3(bytes: &[u8]) -> YasmfHash<ArrayVec<[u8; BLAKE3_HASH_SIZE]>> {
63 let hash_bytes = blake3(bytes);
64
65 let vec_bytes: ArrayVec<[u8; BLAKE3_HASH_SIZE]> =
66 ArrayVec::from_iter(hash_bytes.as_bytes().iter().map(|b| *b));
67
68 YasmfHash::Blake3(vec_bytes)
69}
70
71impl<'a> From<&'a YasmfHash<ArrayVec<[u8; BLAKE3_HASH_SIZE]>>> for YasmfHash<&'a [u8]> {
72 fn from(hash: &YasmfHash<ArrayVec<[u8; BLAKE3_HASH_SIZE]>>) -> YasmfHash<&[u8]> {
73 match hash {
74 YasmfHash::Blake3(bytes) => YasmfHash::Blake3(&bytes[..]),
75 }
76 }
77}
78
79
80impl<'a> From<Blake3Hash> for YasmfHash<ArrayVec<[u8; BLAKE3_HASH_SIZE]>> {
81 fn from(hash: Blake3Hash) -> Self {
82 let vec_bytes: ArrayVec<[u8; BLAKE3_HASH_SIZE]> =
83 ArrayVec::from_iter(hash.as_bytes().iter().map(|b| *b));
84
85 YasmfHash::Blake3(vec_bytes)
86 }
87}
88impl<T: Borrow<[u8]> + Clone> YasmfHash<T> {
89 pub fn encode(&self, out: &mut [u8]) -> Result<usize, Error> {
91 let encoded_size = self.encoding_length();
92
93 match (self, out.len()) {
94 (YasmfHash::Blake3(vec), len) if len >= encoded_size => {
95 varu64_encode(BLAKE3_NUMERIC_ID, &mut out[0..1]);
96 varu64_encode(BLAKE3_HASH_SIZE as u64, &mut out[1..2]);
97 out[2..encoded_size].copy_from_slice(vec.borrow());
98 Ok(encoded_size)
99 }
100 _ => Err(Error::EncodeError),
101 }
102 }
103
104 pub fn encoding_length(&self) -> usize {
105 match self {
106 YasmfHash::Blake3(_) => {
107 encoding_length(BLAKE3_NUMERIC_ID)
108 + encoding_length(BLAKE3_HASH_SIZE as u64)
109 + BLAKE3_HASH_SIZE
110 }
111 }
112 }
113
114 pub fn decode<'a>(bytes: &'a [u8]) -> Result<(YasmfHash<&'a [u8]>, &'a [u8]), Error> {
116 match varu64_decode(&bytes) {
117 Ok((BLAKE3_NUMERIC_ID, remaining_bytes)) if remaining_bytes.len() >= 33 => {
118 let hash = &remaining_bytes[1..33];
119 Ok((YasmfHash::Blake3(hash), &remaining_bytes[33..]))
120 }
121 Err((_, _)) => Err(Error::DecodeVaru64Error),
122 _ => Err(Error::DecodeError {}),
123 }
124 }
125
126 pub fn decode_owned<'a>(
128 bytes: &'a [u8],
129 ) -> Result<(YasmfHash<ArrayVec<[u8; BLAKE3_HASH_SIZE]>>, &'a [u8]), Error> {
130 match varu64_decode(&bytes) {
131 Ok((BLAKE3_NUMERIC_ID, remaining_bytes)) if remaining_bytes.len() >= 33 => {
132 let mut vec = ArrayVec::new();
133 let slice = &remaining_bytes[1..33];
134 vec.try_extend_from_slice(slice).unwrap();
135 Ok((YasmfHash::Blake3(vec), &remaining_bytes[33..]))
136 }
137 Err((_, _)) => Err(Error::DecodeVaru64Error),
138 _ => Err(Error::DecodeError {}),
139 }
140 }
141
142 #[cfg(feature = "std")]
144 pub fn encode_write<W: Write>(&self, mut w: W) -> Result<(), Error> {
145 let mut out = [0; 2];
146 match self {
147 YasmfHash::Blake3(vec) => {
148 varu64_encode(BLAKE3_NUMERIC_ID, &mut out[0..1]);
149 varu64_encode(BLAKE3_HASH_SIZE as u64, &mut out[1..2]);
150 w.write_all(&out).map_err(|_| Error::EncodeWriteError)?;
151 w.write_all(vec.borrow())
152 .map_err(|_| Error::EncodeWriteError)?;
153 Ok(())
154 }
155 }
156 }
157}
158
159#[cfg(test)]
160mod tests {
161 use crate::MAX_YAMF_HASH_SIZE;
162
163 use super::{new_blake3, blake3, Error, YasmfHash, BLAKE3_HASH_SIZE};
164 use arrayvec::ArrayVec;
165 use core::iter::FromIterator;
166
167 #[test]
168 fn encode_yasmf() {
169 let hash_bytes = vec![0xFF; BLAKE3_HASH_SIZE];
170 let yasmf_hash = YasmfHash::Blake3(hash_bytes);
171
172 let mut encoded = vec![0; MAX_YAMF_HASH_SIZE];
173 let length = yasmf_hash.encode(&mut encoded).unwrap();
174 assert_eq!(length, MAX_YAMF_HASH_SIZE);
175 assert_eq!(encoded[0], 0);
176 assert_eq!(encoded[1], 32);
177 }
178 #[test]
179 fn encode_yasmf_write() {
180 let hash_bytes = vec![0xFF; BLAKE3_HASH_SIZE];
181 let yasmf_hash = YasmfHash::Blake3(hash_bytes);
182
183 let mut encoded = Vec::new();
184 yasmf_hash.encode_write(&mut encoded).unwrap();
185 assert_eq!(encoded.len(), 34);
186 assert_eq!(encoded[0], 0);
187 assert_eq!(encoded[1], 32);
188 }
189 #[test]
190 fn encode_yasmf_not_enough_bytes_for_varu() {
191 let hash_bytes = vec![0xFF; 4];
192 let yasmf_hash = YasmfHash::Blake3(hash_bytes);
193
194 let mut encoded = [0; 2];
195 match yasmf_hash.encode_write(&mut encoded[..]) {
196 Err(Error::EncodeWriteError) => {}
197 _ => panic!("Go ok, expected error"),
198 }
199 }
200 #[test]
201 fn encode_yasmf_not_enough_bytes_for_hash() {
202 let hash_bytes = vec![0xFF; 4];
203 let yasmf_hash = YasmfHash::Blake3(hash_bytes);
204
205 let mut encoded = [0; 4];
206 match yasmf_hash.encode_write(&mut encoded[..]) {
207 Err(Error::EncodeWriteError) => {}
208 _ => panic!("Go ok, expected error"),
209 }
210 }
211 #[test]
212 fn decode_yasmf() {
213 let mut hash_bytes = vec![0xFF; 35];
214 hash_bytes[0] = 0;
215 hash_bytes[1] = 32;
216 hash_bytes[34] = 0xAA;
217 let result = YasmfHash::<&[u8]>::decode(&hash_bytes);
218
219 match result {
220 Ok((YasmfHash::Blake3(vec), remaining_bytes)) => {
221 assert_eq!(vec.len(), 32);
222 assert_eq!(vec, &hash_bytes[2..34]);
223 assert_eq!(remaining_bytes, &[0xAA]);
224 }
225 _ => panic!(),
226 }
227 }
228 #[test]
229 fn decode_yasmf_varu_error() {
230 let mut hash_bytes = vec![0xFF; 67];
231 hash_bytes[0] = 248;
232 hash_bytes[1] = 1;
233 hash_bytes[2] = 32;
234 hash_bytes[66] = 0xAA;
235 let result = YasmfHash::<&[u8]>::decode(&hash_bytes);
236
237 match result {
238 Err(Error::DecodeVaru64Error) => {}
239 _ => panic!(),
240 }
241 }
242 #[test]
243 fn decode_yasmf_not_enough_bytes_error() {
244 let mut hash_bytes = vec![0xFF; BLAKE3_HASH_SIZE];
245 hash_bytes[0] = 0;
246 hash_bytes[1] = 32;
247 let result = YasmfHash::<&[u8]>::decode(&hash_bytes);
248
249 match result {
250 Err(Error::DecodeError {}) => {}
251 _ => panic!(),
252 }
253 }
254
255 #[test]
256 fn blake_yasmf_hash() {
257 let lam = || {
258 let hash_bytes = blake3(&[1, 2]);
259 let vec_bytes: ArrayVec<[u8; BLAKE3_HASH_SIZE]> =
260 ArrayVec::from_iter(hash_bytes.as_bytes().iter().map(|b| *b));
261 YasmfHash::Blake3(vec_bytes)
262 };
263 let _ = lam();
264 }
265
266 #[test]
267 fn blake2b_yasmf_hash_eq() {
268 let lam = || {
269 let hash_bytes = blake3(&[1, 2]);
270 let vec_bytes: ArrayVec<[u8; BLAKE3_HASH_SIZE]> =
271 ArrayVec::from_iter(hash_bytes.as_bytes().iter().map(|b| *b));
272 YasmfHash::Blake3(vec_bytes)
273 };
274 let result = lam();
275
276 let hash_bytes = blake3(&[1, 2]);
277 let result2 = YasmfHash::Blake3(&hash_bytes.as_bytes()[..]);
278
279 assert_eq!(result, result2);
280 assert_eq!(result2, result);
281 }
282
283 #[test]
284 fn owned_yasmf_hash() {
285 let lam = || {
286 let mut hash_bytes = ArrayVec::<[u8; BLAKE3_HASH_SIZE]>::new();
287 hash_bytes.push(1);
288 hash_bytes.push(64);
289 YasmfHash::Blake3(hash_bytes)
290 };
291 let _ = lam();
292 }
293 #[test]
294 fn ref_yasmf_hash() {
295 let mut hash_bytes = ArrayVec::<[u8; BLAKE3_HASH_SIZE * 2]>::new();
296 hash_bytes.push(1);
297 hash_bytes.push(64);
298 YasmfHash::Blake3(hash_bytes);
299 }
300 #[test]
301 fn from_owned_to_ref_yasmf_hash() {
302 let lam = || {
303 let mut hash_bytes = ArrayVec::<[u8; BLAKE3_HASH_SIZE]>::new();
304 hash_bytes.push(1);
305 hash_bytes.push(64);
306 YasmfHash::Blake3(hash_bytes)
307 };
308 let result = lam();
309 let _: YasmfHash<&[u8]> = YasmfHash::from(&result);
310 }
311
312 #[test]
313 fn encode_decode_blake2b() {
314 let bytes = vec![1, 2, 3];
315 let yasmf_hash = new_blake3(&bytes);
316
317 let mut encoded = Vec::new();
318 yasmf_hash.encode_write(&mut encoded).unwrap();
319
320 let (decoded, _) = YasmfHash::<ArrayVec<[u8; BLAKE3_HASH_SIZE]>>::decode_owned(&encoded).unwrap();
321
322 assert_eq!(decoded, yasmf_hash);
323 }
324
325 #[test]
326 fn encode_decode_blake3() {
327 let bytes = vec![1, 2, 3];
328 let yasmf_hash = new_blake3(&bytes);
329
330 let mut encoded = Vec::new();
331 yasmf_hash.encode_write(&mut encoded).unwrap();
332
333 let (decoded, _) = YasmfHash::<ArrayVec<[u8; BLAKE3_HASH_SIZE]>>::decode_owned(&encoded).unwrap();
334
335 assert_eq!(decoded, yasmf_hash);
336 }
337}