fixed_hash/
hash.rs
1#[macro_export(local_inner_macros)]
42macro_rules! construct_fixed_hash {
43 ( $(#[$attr:meta])* $visibility:vis struct $name:ident ( $n_bytes:expr ); ) => {
44 #[repr(C)]
45 $(#[$attr])*
46 $visibility struct $name (pub [u8; $n_bytes]);
47
48 impl From<[u8; $n_bytes]> for $name {
49 #[inline]
55 fn from(bytes: [u8; $n_bytes]) -> Self {
56 $name(bytes)
57 }
58 }
59
60 impl<'a> From<&'a [u8; $n_bytes]> for $name {
61 #[inline]
68 fn from(bytes: &'a [u8; $n_bytes]) -> Self {
69 $name(*bytes)
70 }
71 }
72
73 impl<'a> From<&'a mut [u8; $n_bytes]> for $name {
74 #[inline]
81 fn from(bytes: &'a mut [u8; $n_bytes]) -> Self {
82 $name(*bytes)
83 }
84 }
85
86 impl From<$name> for [u8; $n_bytes] {
87 #[inline]
88 fn from(s: $name) -> Self {
89 s.0
90 }
91 }
92
93 impl AsRef<[u8]> for $name {
94 #[inline]
95 fn as_ref(&self) -> &[u8] {
96 self.as_bytes()
97 }
98 }
99
100 impl AsMut<[u8]> for $name {
101 #[inline]
102 fn as_mut(&mut self) -> &mut [u8] {
103 self.as_bytes_mut()
104 }
105 }
106
107 impl $name {
108 #[inline]
110 pub const fn repeat_byte(byte: u8) -> $name {
111 $name([byte; $n_bytes])
112 }
113
114 #[inline]
116 pub const fn zero() -> $name {
117 $name::repeat_byte(0u8)
118 }
119
120 #[inline]
122 pub const fn len_bytes() -> usize {
123 $n_bytes
124 }
125
126 #[inline]
128 pub fn as_bytes(&self) -> &[u8] {
129 &self.0
130 }
131
132 #[inline]
134 pub fn as_bytes_mut(&mut self) -> &mut [u8] {
135 &mut self.0
136 }
137
138 #[inline]
140 pub const fn as_fixed_bytes(&self) -> &[u8; $n_bytes] {
141 &self.0
142 }
143
144 #[inline]
146 pub fn as_fixed_bytes_mut(&mut self) -> &mut [u8; $n_bytes] {
147 &mut self.0
148 }
149
150 #[inline]
152 pub const fn to_fixed_bytes(self) -> [u8; $n_bytes] {
153 self.0
154 }
155
156 #[inline]
158 pub fn as_ptr(&self) -> *const u8 {
159 self.as_bytes().as_ptr()
160 }
161
162 #[inline]
164 pub fn as_mut_ptr(&mut self) -> *mut u8 {
165 self.as_bytes_mut().as_mut_ptr()
166 }
167
168 pub fn assign_from_slice(&mut self, src: &[u8]) {
178 $crate::core_::assert_eq!(src.len(), $n_bytes);
179 self.as_bytes_mut().copy_from_slice(src);
180 }
181
182 pub fn from_slice(src: &[u8]) -> Self {
192 $crate::core_::assert_eq!(src.len(), $n_bytes);
193 let mut ret = Self::zero();
194 ret.assign_from_slice(src);
195 ret
196 }
197
198 #[inline]
200 pub fn covers(&self, b: &Self) -> bool {
201 &(b & self) == b
202 }
203
204 #[inline]
206 pub fn is_zero(&self) -> bool {
207 self.as_bytes().iter().all(|&byte| byte == 0u8)
208 }
209 }
210
211 impl $crate::core_::fmt::Debug for $name {
212 fn fmt(&self, f: &mut $crate::core_::fmt::Formatter) -> $crate::core_::fmt::Result {
213 $crate::core_::write!(f, "{:#x}", self)
214 }
215 }
216
217 impl $crate::core_::fmt::Display for $name {
218 fn fmt(&self, f: &mut $crate::core_::fmt::Formatter) -> $crate::core_::fmt::Result {
219 $crate::core_::write!(f, "0x")?;
220 for i in &self.0[0..2] {
221 $crate::core_::write!(f, "{:02x}", i)?;
222 }
223 $crate::core_::write!(f, "…")?;
224 for i in &self.0[$n_bytes - 2..$n_bytes] {
225 $crate::core_::write!(f, "{:02x}", i)?;
226 }
227 Ok(())
228 }
229 }
230
231 impl $crate::core_::fmt::LowerHex for $name {
232 fn fmt(&self, f: &mut $crate::core_::fmt::Formatter) -> $crate::core_::fmt::Result {
233 if f.alternate() {
234 $crate::core_::write!(f, "0x")?;
235 }
236 for i in &self.0[..] {
237 $crate::core_::write!(f, "{:02x}", i)?;
238 }
239 Ok(())
240 }
241 }
242
243 impl $crate::core_::fmt::UpperHex for $name {
244 fn fmt(&self, f: &mut $crate::core_::fmt::Formatter) -> $crate::core_::fmt::Result {
245 if f.alternate() {
246 $crate::core_::write!(f, "0X")?;
247 }
248 for i in &self.0[..] {
249 $crate::core_::write!(f, "{:02X}", i)?;
250 }
251 Ok(())
252 }
253 }
254
255 impl $crate::core_::marker::Copy for $name {}
256
257 #[cfg_attr(feature = "dev", allow(expl_impl_clone_on_copy))]
258 impl $crate::core_::clone::Clone for $name {
259 fn clone(&self) -> $name {
260 let mut ret = $name::zero();
261 ret.0.copy_from_slice(&self.0);
262 ret
263 }
264 }
265
266 impl $crate::core_::cmp::Eq for $name {}
267
268 impl $crate::core_::cmp::PartialOrd for $name {
269 fn partial_cmp(&self, other: &Self) -> Option<$crate::core_::cmp::Ordering> {
270 Some(self.cmp(other))
271 }
272 }
273
274 impl $crate::core_::hash::Hash for $name {
275 fn hash<H>(&self, state: &mut H) where H: $crate::core_::hash::Hasher {
276 state.write(&self.0);
277 }
278 }
279
280 impl<I> $crate::core_::ops::Index<I> for $name
281 where
282 I: $crate::core_::slice::SliceIndex<[u8]>
283 {
284 type Output = I::Output;
285
286 #[inline]
287 fn index(&self, index: I) -> &I::Output {
288 &self.as_bytes()[index]
289 }
290 }
291
292 impl<I> $crate::core_::ops::IndexMut<I> for $name
293 where
294 I: $crate::core_::slice::SliceIndex<[u8], Output = [u8]>
295 {
296 #[inline]
297 fn index_mut(&mut self, index: I) -> &mut I::Output {
298 &mut self.as_bytes_mut()[index]
299 }
300 }
301
302 impl $crate::core_::default::Default for $name {
303 #[inline]
304 fn default() -> Self {
305 Self::zero()
306 }
307 }
308
309 impl_ops_for_hash!($name, BitOr, bitor, BitOrAssign, bitor_assign, |, |=);
310 impl_ops_for_hash!($name, BitAnd, bitand, BitAndAssign, bitand_assign, &, &=);
311 impl_ops_for_hash!($name, BitXor, bitxor, BitXorAssign, bitxor_assign, ^, ^=);
312
313 impl_byteorder_for_fixed_hash!($name);
314 impl_rand_for_fixed_hash!($name);
315 impl_cmp_for_fixed_hash!($name);
316 impl_rustc_hex_for_fixed_hash!($name);
317 impl_quickcheck_for_fixed_hash!($name);
318 impl_arbitrary_for_fixed_hash!($name);
319 }
320}
321
322#[cfg(not(feature = "byteorder"))]
330#[macro_export]
331#[doc(hidden)]
332macro_rules! impl_byteorder_for_fixed_hash {
333 ( $name:ident ) => {};
334}
335
336#[cfg(feature = "byteorder")]
344#[macro_export]
345#[doc(hidden)]
346macro_rules! impl_byteorder_for_fixed_hash {
347 ( $name:ident ) => {
348 impl $name {
350 #[inline]
356 fn least_significant_bytes(&self, n: usize) -> &[u8] {
357 $crate::core_::assert_eq!(true, n <= Self::len_bytes());
358 &self[(Self::len_bytes() - n)..]
359 }
360
361 fn to_low_u64_with_byteorder<B>(&self) -> u64
362 where
363 B: $crate::byteorder::ByteOrder,
364 {
365 let mut buf = [0x0; 8];
366 let capped = $crate::core_::cmp::min(Self::len_bytes(), 8);
367 buf[(8 - capped)..].copy_from_slice(self.least_significant_bytes(capped));
368 B::read_u64(&buf)
369 }
370
371 #[inline]
378 pub fn to_low_u64_be(&self) -> u64 {
379 self.to_low_u64_with_byteorder::<$crate::byteorder::BigEndian>()
380 }
381
382 #[inline]
389 pub fn to_low_u64_le(&self) -> u64 {
390 self.to_low_u64_with_byteorder::<$crate::byteorder::LittleEndian>()
391 }
392
393 #[inline]
400 pub fn to_low_u64_ne(&self) -> u64 {
401 self.to_low_u64_with_byteorder::<$crate::byteorder::NativeEndian>()
402 }
403
404 fn from_low_u64_with_byteorder<B>(val: u64) -> Self
405 where
406 B: $crate::byteorder::ByteOrder,
407 {
408 let mut buf = [0x0; 8];
409 B::write_u64(&mut buf, val);
410 let capped = $crate::core_::cmp::min(Self::len_bytes(), 8);
411 let mut bytes = [0x0; $crate::core_::mem::size_of::<Self>()];
412 bytes[(Self::len_bytes() - capped)..].copy_from_slice(&buf[..capped]);
413 Self::from_slice(&bytes)
414 }
415
416 #[inline]
424 pub fn from_low_u64_be(val: u64) -> Self {
425 Self::from_low_u64_with_byteorder::<$crate::byteorder::BigEndian>(val)
426 }
427
428 #[inline]
436 pub fn from_low_u64_le(val: u64) -> Self {
437 Self::from_low_u64_with_byteorder::<$crate::byteorder::LittleEndian>(val)
438 }
439
440 #[inline]
448 pub fn from_low_u64_ne(val: u64) -> Self {
449 Self::from_low_u64_with_byteorder::<$crate::byteorder::NativeEndian>(val)
450 }
451 }
452 };
453}
454
455#[cfg(not(feature = "rand"))]
463#[macro_export]
464#[doc(hidden)]
465macro_rules! impl_rand_for_fixed_hash {
466 ( $name:ident ) => {};
467}
468
469#[cfg(feature = "rand")]
477#[macro_export]
478#[doc(hidden)]
479macro_rules! impl_rand_for_fixed_hash {
480 ( $name:ident ) => {
481 impl $crate::rand::distributions::Distribution<$name> for $crate::rand::distributions::Standard {
482 fn sample<R: $crate::rand::Rng + ?Sized>(&self, rng: &mut R) -> $name {
483 let mut ret = $name::zero();
484 for byte in ret.as_bytes_mut().iter_mut() {
485 *byte = rng.gen();
486 }
487 ret
488 }
489 }
490
491 impl $name {
493 pub fn randomize_using<R>(&mut self, rng: &mut R)
496 where
497 R: $crate::rand::Rng + ?Sized,
498 {
499 use $crate::rand::distributions::Distribution;
500 *self = $crate::rand::distributions::Standard.sample(rng);
501 }
502
503 pub fn randomize(&mut self) {
505 let mut rng = $crate::rand::rngs::OsRng;
506 self.randomize_using(&mut rng);
507 }
508
509 pub fn random_using<R>(rng: &mut R) -> Self
512 where
513 R: $crate::rand::Rng + ?Sized,
514 {
515 let mut ret = Self::zero();
516 ret.randomize_using(rng);
517 ret
518 }
519
520 pub fn random() -> Self {
522 let mut hash = Self::zero();
523 hash.randomize();
524 hash
525 }
526 }
527 };
528}
529
530#[macro_export]
531#[doc(hidden)]
532macro_rules! impl_cmp_for_fixed_hash {
533 ( $name:ident ) => {
534 impl $crate::core_::cmp::PartialEq for $name {
535 #[inline]
536 fn eq(&self, other: &Self) -> bool {
537 self.as_bytes() == other.as_bytes()
538 }
539 }
540
541 impl $crate::core_::cmp::Ord for $name {
542 #[inline]
543 fn cmp(&self, other: &Self) -> $crate::core_::cmp::Ordering {
544 self.as_bytes().cmp(other.as_bytes())
545 }
546 }
547 };
548}
549
550#[cfg(not(feature = "rustc-hex"))]
558#[macro_export]
559#[doc(hidden)]
560macro_rules! impl_rustc_hex_for_fixed_hash {
561 ( $name:ident ) => {};
562}
563
564#[cfg(feature = "rustc-hex")]
572#[macro_export]
573#[doc(hidden)]
574macro_rules! impl_rustc_hex_for_fixed_hash {
575 ( $name:ident ) => {
576 impl $crate::core_::str::FromStr for $name {
577 type Err = $crate::rustc_hex::FromHexError;
578
579 fn from_str(input: &str) -> $crate::core_::result::Result<$name, $crate::rustc_hex::FromHexError> {
590 let input = input.strip_prefix("0x").unwrap_or(input);
591 let mut iter = $crate::rustc_hex::FromHexIter::new(input);
592 let mut result = Self::zero();
593 for byte in result.as_mut() {
594 *byte = iter.next().ok_or(Self::Err::InvalidHexLength)??;
595 }
596 if iter.next().is_some() {
597 return Err(Self::Err::InvalidHexLength)
598 }
599 Ok(result)
600 }
601 }
602 };
603}
604
605#[cfg(not(feature = "quickcheck"))]
613#[macro_export]
614#[doc(hidden)]
615macro_rules! impl_quickcheck_for_fixed_hash {
616 ( $name:ident ) => {};
617}
618
619#[cfg(feature = "quickcheck")]
627#[macro_export]
628#[doc(hidden)]
629macro_rules! impl_quickcheck_for_fixed_hash {
630 ( $name:ident ) => {
631 impl $crate::quickcheck::Arbitrary for $name {
632 fn arbitrary(g: &mut $crate::quickcheck::Gen) -> Self {
633 let res: [u8; Self::len_bytes()] = $crate::core_::array::from_fn(|_| u8::arbitrary(g));
634 Self::from(res)
635 }
636 }
637 };
638}
639
640#[cfg(not(feature = "arbitrary"))]
648#[macro_export]
649#[doc(hidden)]
650macro_rules! impl_arbitrary_for_fixed_hash {
651 ( $name:ident ) => {};
652}
653
654#[cfg(feature = "arbitrary")]
662#[macro_export]
663#[doc(hidden)]
664macro_rules! impl_arbitrary_for_fixed_hash {
665 ( $name:ident ) => {
666 impl $crate::arbitrary::Arbitrary<'_> for $name {
667 fn arbitrary(u: &mut $crate::arbitrary::Unstructured<'_>) -> $crate::arbitrary::Result<Self> {
668 let mut res = Self::zero();
669 u.fill_buffer(&mut res.0)?;
670 Ok(Self::from(res))
671 }
672 }
673 };
674}
675
676#[macro_export]
677#[doc(hidden)]
678macro_rules! impl_ops_for_hash {
679 (
680 $impl_for:ident,
681 $ops_trait_name:ident,
682 $ops_fn_name:ident,
683 $ops_assign_trait_name:ident,
684 $ops_assign_fn_name:ident,
685 $ops_tok:tt,
686 $ops_assign_tok:tt
687 ) => {
688 impl<'r> $crate::core_::ops::$ops_assign_trait_name<&'r $impl_for> for $impl_for {
689 fn $ops_assign_fn_name(&mut self, rhs: &'r $impl_for) {
690 for (lhs, rhs) in self.as_bytes_mut().iter_mut().zip(rhs.as_bytes()) {
691 *lhs $ops_assign_tok rhs;
692 }
693 }
694 }
695
696 impl $crate::core_::ops::$ops_assign_trait_name<$impl_for> for $impl_for {
697 #[inline]
698 fn $ops_assign_fn_name(&mut self, rhs: $impl_for) {
699 *self $ops_assign_tok &rhs;
700 }
701 }
702
703 impl<'l, 'r> $crate::core_::ops::$ops_trait_name<&'r $impl_for> for &'l $impl_for {
704 type Output = $impl_for;
705
706 fn $ops_fn_name(self, rhs: &'r $impl_for) -> Self::Output {
707 let mut ret = self.clone();
708 ret $ops_assign_tok rhs;
709 ret
710 }
711 }
712
713 impl $crate::core_::ops::$ops_trait_name<$impl_for> for $impl_for {
714 type Output = $impl_for;
715
716 #[inline]
717 fn $ops_fn_name(self, rhs: Self) -> Self::Output {
718 &self $ops_tok &rhs
719 }
720 }
721 };
722}
723
724#[macro_export(local_inner_macros)]
748macro_rules! impl_fixed_hash_conversions {
749 ($large_ty:ident, $small_ty:ident) => {
750 $crate::static_assertions::const_assert!(
751 $crate::core_::mem::size_of::<$small_ty>() < $crate::core_::mem::size_of::<$large_ty>()
752 );
753
754 impl From<$small_ty> for $large_ty {
755 fn from(value: $small_ty) -> $large_ty {
756 let large_ty_size = $large_ty::len_bytes();
757 let small_ty_size = $small_ty::len_bytes();
758
759 $crate::core_::debug_assert!(
760 large_ty_size > small_ty_size && large_ty_size % 2 == 0 && small_ty_size % 2 == 0
761 );
762
763 let mut ret = $large_ty::zero();
764 ret.as_bytes_mut()[(large_ty_size - small_ty_size)..large_ty_size].copy_from_slice(value.as_bytes());
765 ret
766 }
767 }
768
769 impl From<$large_ty> for $small_ty {
770 fn from(value: $large_ty) -> $small_ty {
771 let large_ty_size = $large_ty::len_bytes();
772 let small_ty_size = $small_ty::len_bytes();
773
774 $crate::core_::debug_assert!(
775 large_ty_size > small_ty_size && large_ty_size % 2 == 0 && small_ty_size % 2 == 0
776 );
777
778 let mut ret = $small_ty::zero();
779 ret.as_bytes_mut()
780 .copy_from_slice(&value[(large_ty_size - small_ty_size)..large_ty_size]);
781 ret
782 }
783 }
784 };
785}