1#[macro_export]
4macro_rules! hex_fmt_impl(
6 ($reverse:expr, $len:expr, $ty:ident) => (
7 $crate::hex_fmt_impl!($reverse, $len, $ty, );
8 );
9 ($reverse:expr, $len:expr, $ty:ident, $($gen:ident: $gent:ident),*) => (
10 impl<$($gen: $gent),*> $crate::_export::_core::fmt::LowerHex for $ty<$($gen),*> {
11 #[inline]
12 fn fmt(&self, f: &mut $crate::_export::_core::fmt::Formatter) -> $crate::_export::_core::fmt::Result {
13 if $reverse {
14 $crate::hex::fmt_hex_exact!(f, $len, <Self as $crate::Hash>::as_byte_array(&self).iter().rev(), $crate::hex::Case::Lower)
15 } else {
16 $crate::hex::fmt_hex_exact!(f, $len, <Self as $crate::Hash>::as_byte_array(&self), $crate::hex::Case::Lower)
17 }
18 }
19 }
20
21 impl<$($gen: $gent),*> $crate::_export::_core::fmt::UpperHex for $ty<$($gen),*> {
22 #[inline]
23 fn fmt(&self, f: &mut $crate::_export::_core::fmt::Formatter) -> $crate::_export::_core::fmt::Result {
24 if $reverse {
25 $crate::hex::fmt_hex_exact!(f, $len, <Self as $crate::Hash>::as_byte_array(&self).iter().rev(), $crate::hex::Case::Upper)
26 } else {
27 $crate::hex::fmt_hex_exact!(f, $len, <Self as $crate::Hash>::as_byte_array(&self), $crate::hex::Case::Upper)
28 }
29 }
30 }
31
32 impl<$($gen: $gent),*> $crate::_export::_core::fmt::Display for $ty<$($gen),*> {
33 #[inline]
34 fn fmt(&self, f: &mut $crate::_export::_core::fmt::Formatter) -> $crate::_export::_core::fmt::Result {
35 $crate::_export::_core::fmt::LowerHex::fmt(&self, f)
36 }
37 }
38
39 impl<$($gen: $gent),*> $crate::_export::_core::fmt::Debug for $ty<$($gen),*> {
40 #[inline]
41 fn fmt(&self, f: &mut $crate::_export::_core::fmt::Formatter) -> $crate::_export::_core::fmt::Result {
42 write!(f, "{}", self)
43 }
44 }
45 );
46);
47
48#[macro_export]
50macro_rules! borrow_slice_impl(
51 ($ty:ident) => (
52 $crate::borrow_slice_impl!($ty, );
53 );
54 ($ty:ident, $($gen:ident: $gent:ident),*) => (
55 impl<$($gen: $gent),*> $crate::_export::_core::borrow::Borrow<[u8]> for $ty<$($gen),*> {
56 fn borrow(&self) -> &[u8] {
57 &self[..]
58 }
59 }
60
61 impl<$($gen: $gent),*> $crate::_export::_core::convert::AsRef<[u8]> for $ty<$($gen),*> {
62 fn as_ref(&self) -> &[u8] {
63 &self[..]
64 }
65 }
66 )
67);
68
69macro_rules! engine_input_impl(
70 () => (
71 #[cfg(not(hashes_fuzz))]
72 fn input(&mut self, mut inp: &[u8]) {
73 while !inp.is_empty() {
74 let buf_idx = self.length % <Self as crate::HashEngine>::BLOCK_SIZE;
75 let rem_len = <Self as crate::HashEngine>::BLOCK_SIZE - buf_idx;
76 let write_len = cmp::min(rem_len, inp.len());
77
78 self.buffer[buf_idx..buf_idx + write_len]
79 .copy_from_slice(&inp[..write_len]);
80 self.length += write_len;
81 if self.length % <Self as crate::HashEngine>::BLOCK_SIZE == 0 {
82 self.process_block();
83 }
84 inp = &inp[write_len..];
85 }
86 }
87
88 #[cfg(hashes_fuzz)]
89 fn input(&mut self, inp: &[u8]) {
90 for c in inp {
91 self.buffer[0] ^= *c;
92 }
93 self.length += inp.len();
94 }
95 )
96);
97
98#[macro_export]
180macro_rules! hash_newtype {
181 ($($(#[$($type_attrs:tt)*])* $type_vis:vis struct $newtype:ident($(#[$field_attrs:tt])* $field_vis:vis $hash:path);)+) => {
182 $(
183 $($crate::hash_newtype_known_attrs!(#[ $($type_attrs)* ]);)*
184
185 $crate::hash_newtype_struct! {
186 $type_vis struct $newtype($(#[$field_attrs])* $field_vis $hash);
187
188 $({ $($type_attrs)* })*
189 }
190
191 $crate::hex_fmt_impl!(<$newtype as $crate::Hash>::DISPLAY_BACKWARD, <$newtype as $crate::Hash>::LEN, $newtype);
192 $crate::serde_impl!($newtype, <$newtype as $crate::Hash>::LEN);
193 $crate::borrow_slice_impl!($newtype);
194
195 impl $newtype {
196 #[allow(unused)] pub fn from_raw_hash(inner: $hash) -> $newtype {
199 $newtype(inner)
200 }
201
202 #[allow(unused)] pub fn to_raw_hash(self) -> $hash {
205 self.0
206 }
207
208 #[allow(unused)] pub fn as_raw_hash(&self) -> &$hash {
211 &self.0
212 }
213 }
214
215 impl $crate::_export::_core::convert::From<$hash> for $newtype {
216 fn from(inner: $hash) -> $newtype {
217 Self { 0: inner }
219 }
220 }
221
222 impl $crate::_export::_core::convert::From<$newtype> for $hash {
223 fn from(hashtype: $newtype) -> $hash {
224 hashtype.0
225 }
226 }
227
228 impl $crate::Hash for $newtype {
229 type Engine = <$hash as $crate::Hash>::Engine;
230 type Bytes = <$hash as $crate::Hash>::Bytes;
231
232 const LEN: usize = <$hash as $crate::Hash>::LEN;
233 const DISPLAY_BACKWARD: bool = $crate::hash_newtype_get_direction!($hash, $(#[$($type_attrs)*])*);
234
235 fn engine() -> Self::Engine {
236 <$hash as $crate::Hash>::engine()
237 }
238
239 fn from_engine(e: Self::Engine) -> Self {
240 Self::from(<$hash as $crate::Hash>::from_engine(e))
241 }
242
243 #[inline]
244 fn from_slice(sl: &[u8]) -> $crate::_export::_core::result::Result<$newtype, $crate::FromSliceError> {
245 Ok($newtype(<$hash as $crate::Hash>::from_slice(sl)?))
246 }
247
248 #[inline]
249 fn from_byte_array(bytes: Self::Bytes) -> Self {
250 $newtype(<$hash as $crate::Hash>::from_byte_array(bytes))
251 }
252
253 #[inline]
254 fn to_byte_array(self) -> Self::Bytes {
255 self.0.to_byte_array()
256 }
257
258 #[inline]
259 fn as_byte_array(&self) -> &Self::Bytes {
260 self.0.as_byte_array()
261 }
262
263 #[inline]
264 fn all_zeros() -> Self {
265 let zeros = <$hash>::all_zeros();
266 $newtype(zeros)
267 }
268 }
269
270 impl $crate::_export::_core::str::FromStr for $newtype {
271 type Err = $crate::hex::HexToArrayError;
272 fn from_str(s: &str) -> $crate::_export::_core::result::Result<$newtype, Self::Err> {
273 use $crate::{Hash, hex::FromHex};
274
275 let mut bytes = <[u8; <Self as $crate::Hash>::LEN]>::from_hex(s)?;
276 if <Self as $crate::Hash>::DISPLAY_BACKWARD {
277 bytes.reverse();
278 };
279 Ok($newtype(<$hash>::from_byte_array(bytes)))
280 }
281 }
282
283 impl $crate::_export::_core::convert::AsRef<[u8; <$hash as $crate::Hash>::LEN]> for $newtype {
284 fn as_ref(&self) -> &[u8; <$hash as $crate::Hash>::LEN] {
285 AsRef::<[u8; <$hash as $crate::Hash>::LEN]>::as_ref(&self.0)
286 }
287 }
288
289 impl<I: $crate::_export::_core::slice::SliceIndex<[u8]>> $crate::_export::_core::ops::Index<I> for $newtype {
290 type Output = I::Output;
291
292 #[inline]
293 fn index(&self, index: I) -> &Self::Output {
294 &self.0[index]
295 }
296 }
297 )+
298 };
299}
300
301#[doc(hidden)]
312#[macro_export]
313macro_rules! hash_newtype_struct {
314 ($(#[$other_attrs:meta])* $type_vis:vis struct $newtype:ident($(#[$field_attrs:meta])* $field_vis:vis $hash:path);) => {
315 $(#[$other_attrs])*
316 #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
317 $type_vis struct $newtype($(#[$field_attrs])* $field_vis $hash);
318 };
319 ($(#[$other_attrs:meta])* $type_vis:vis struct $newtype:ident($(#[$field_attrs:meta])* $field_vis:vis $hash:path); { hash_newtype($($ignore:tt)*) } $($type_attrs:tt)*) => {
320 $crate::hash_newtype_struct! {
321 $(#[$other_attrs])*
322 $type_vis struct $newtype($(#[$field_attrs])* $field_vis $hash);
323
324 $($type_attrs)*
325 }
326 };
327 ($(#[$other_attrs:meta])* $type_vis:vis struct $newtype:ident($(#[$field_attrs:meta])* $field_vis:vis $hash:path); { $other_attr:meta } $($type_attrs:tt)*) => {
328 $crate::hash_newtype_struct! {
329 $(#[$other_attrs])*
330 #[$other_attr]
331 $type_vis struct $newtype($(#[$field_attrs])* $field_vis $hash);
332
333 $($type_attrs)*
334 }
335 };
336}
337
338#[doc(hidden)]
347#[macro_export]
348macro_rules! hash_newtype_get_direction {
349 ($hash:ty, ) => { <$hash as $crate::Hash>::DISPLAY_BACKWARD };
350 ($hash:ty, #[hash_newtype(forward)] $($others:tt)*) => { { $crate::hash_newtype_forbid_direction!(forward, $($others)*); false } };
351 ($hash:ty, #[hash_newtype(backward)] $($others:tt)*) => { { $crate::hash_newtype_forbid_direction!(backward, $($others)*); true } };
352 ($hash:ty, #[$($ignore:tt)*] $($others:tt)*) => { $crate::hash_newtype_get_direction!($hash, $($others)*) };
353}
354
355#[doc(hidden)]
359#[macro_export]
360macro_rules! hash_newtype_forbid_direction {
361 ($direction:ident, ) => {};
362 ($direction:ident, #[hash_newtype(forward)] $(others:tt)*) => {
363 compile_error!(concat!("Cannot set display direction to forward: ", stringify!($direction), " was already specified"));
364 };
365 ($direction:ident, #[hash_newtype(backward)] $(others:tt)*) => {
366 compile_error!(concat!("Cannot set display direction to backward: ", stringify!($direction), " was already specified"));
367 };
368 ($direction:ident, #[$($ignore:tt)*] $(#[$others:tt])*) => {
369 $crate::hash_newtype_forbid_direction!($direction, $(#[$others])*)
370 };
371}
372
373#[doc(hidden)]
379#[macro_export]
380macro_rules! hash_newtype_known_attrs {
381 (#[hash_newtype(forward)]) => {};
382 (#[hash_newtype(backward)]) => {};
383 (#[hash_newtype($($unknown:tt)*)]) => { compile_error!(concat!("Unrecognized attribute ", stringify!($($unknown)*))); };
384 ($($ignore:tt)*) => {};
385}
386
387#[cfg(test)]
388mod test {
389 use crate::{sha256, Hash};
390
391 #[test]
392 fn hash_as_ref_array() {
393 let hash = sha256::Hash::hash(&[3, 50]);
394 let r = AsRef::<[u8; 32]>::as_ref(&hash);
395 assert_eq!(r, hash.as_byte_array());
396 }
397
398 #[test]
399 fn hash_as_ref_slice() {
400 let hash = sha256::Hash::hash(&[3, 50]);
401 let r = AsRef::<[u8]>::as_ref(&hash);
402 assert_eq!(r, hash.as_byte_array());
403 }
404
405 #[test]
406 fn hash_borrow() {
407 use core::borrow::Borrow;
408
409 let hash = sha256::Hash::hash(&[3, 50]);
410 let borrowed: &[u8] = hash.borrow();
411 assert_eq!(borrowed, hash.as_byte_array());
412 }
413
414 hash_newtype! {
415 struct TestHash(crate::sha256d::Hash);
417 }
418
419 #[test]
420 fn display() {
421 let want = "0000000000000000000000000000000000000000000000000000000000000000";
422 let got = format!("{}", TestHash::all_zeros());
423 assert_eq!(got, want)
424 }
425
426 #[test]
427 fn display_alternate() {
428 let want = "0x0000000000000000000000000000000000000000000000000000000000000000";
429 let got = format!("{:#}", TestHash::all_zeros());
430 assert_eq!(got, want)
431 }
432
433 #[test]
434 fn lower_hex() {
435 let want = "0000000000000000000000000000000000000000000000000000000000000000";
436 let got = format!("{:x}", TestHash::all_zeros());
437 assert_eq!(got, want)
438 }
439
440 #[test]
441 fn lower_hex_alternate() {
442 let want = "0x0000000000000000000000000000000000000000000000000000000000000000";
443 let got = format!("{:#x}", TestHash::all_zeros());
444 assert_eq!(got, want)
445 }
446
447 #[test]
448 fn inner_hash_as_ref_array() {
449 let hash = TestHash::all_zeros();
450 let r = AsRef::<[u8; 32]>::as_ref(&hash);
451 assert_eq!(r, hash.as_byte_array());
452 }
453
454 #[test]
455 fn inner_hash_as_ref_slice() {
456 let hash = TestHash::all_zeros();
457 let r = AsRef::<[u8]>::as_ref(&hash);
458 assert_eq!(r, hash.as_byte_array());
459 }
460}