@@ -543,6 +543,29 @@ impl<S> RawHasher<S> {
543
543
}
544
544
}
545
545
546
+ fn dispatch_f < R > ( f : impl FnOnce ( & dyn Vector ) -> R ) -> R {
547
+ #[ cfg( all( target_arch = "aarch64" , feature = "std" ) ) ]
548
+ {
549
+ if std:: arch:: is_aarch64_feature_detected!( "neon" ) {
550
+ // Safety: We just ensured we have the NEON feature
551
+ return unsafe { f ( & neon:: Impl ) } ;
552
+ }
553
+ }
554
+
555
+ // #[cfg(all(target_arch = "x86_64", feature = "std"))]
556
+ // {
557
+ // if is_x86_feature_detected!("avx2") {
558
+ // // Safety: We just ensured we have the AVX2 feature
559
+ // return unsafe { do_avx2($($arg_name),*) };
560
+ // } else if is_x86_feature_detected!("sse2") {
561
+ // // Safety: We just ensured we have the SSE2 feature
562
+ // return unsafe { do_sse2($($arg_name),*) };
563
+ // }
564
+ // }
565
+
566
+ f ( & scalar:: Impl )
567
+ }
568
+
546
569
macro_rules! dispatch {
547
570
(
548
571
fn $fn_name: ident<$( $gen: ident) ,* >( $( $arg_name: ident : $arg_ty: ty) ,* ) $( -> $ret_ty: ty) ?
@@ -634,178 +657,158 @@ where
634
657
S : FixedBuffer ,
635
658
{
636
659
#[ inline]
637
- fn write ( & mut self , input : & [ u8 ] ) {
638
- let this = self ;
639
- dispatch ! {
640
- fn write_impl<S >( this: & mut RawHasher <S >, input: & [ u8 ] )
641
- [ S : FixedBuffer ]
642
- }
643
- }
644
-
645
- #[ inline]
646
- fn finish ( & self ) -> u64 {
647
- let this = self ;
648
- dispatch ! {
649
- fn finish_impl<S >( this: & RawHasher <S >) -> u64
650
- [ S : FixedBuffer ]
651
- }
652
- }
653
- }
660
+ fn write ( & mut self , mut input : & [ u8 ] ) {
661
+ dispatch_f ( |vector| {
662
+ if input. is_empty ( ) {
663
+ return ;
664
+ }
654
665
655
- #[ inline( always) ]
656
- fn write_impl < S > ( vector : impl Vector , this : & mut RawHasher < S > , mut input : & [ u8 ] )
657
- where
658
- S : FixedBuffer ,
659
- {
660
- if input. is_empty ( ) {
661
- return ;
662
- }
666
+ let RawHasher {
667
+ secret_buffer,
668
+ buffer_usage,
669
+ stripe_accumulator,
670
+ total_bytes,
671
+ ..
672
+ } = self ;
663
673
664
- let RawHasher {
665
- secret_buffer,
666
- buffer_usage,
667
- stripe_accumulator,
668
- total_bytes,
669
- ..
670
- } = this;
674
+ let n_stripes = secret_buffer. n_stripes ( ) ;
675
+ let ( _, secret, buffer) = secret_buffer. parts_mut ( ) ;
671
676
672
- let n_stripes = secret_buffer. n_stripes ( ) ;
673
- let ( _, secret, buffer) = secret_buffer. parts_mut ( ) ;
677
+ * total_bytes += input. len ( ) ;
674
678
675
- * total_bytes += input. len ( ) ;
679
+ // Safety: This is an invariant of the buffer.
680
+ unsafe {
681
+ debug_assert ! ( * buffer_usage <= buffer. len( ) ) ;
682
+ assert_unchecked ( * buffer_usage <= buffer. len ( ) )
683
+ } ;
676
684
677
- // Safety: This is an invariant of the buffer.
678
- unsafe {
679
- debug_assert ! ( * buffer_usage <= buffer. len( ) ) ;
680
- assert_unchecked ( * buffer_usage <= buffer. len ( ) )
681
- } ;
685
+ // We have some previous data saved; try to fill it up and process it first
686
+ if !buffer. is_empty ( ) {
687
+ let remaining = & mut buffer[ * buffer_usage..] ;
688
+ let n_to_copy = usize:: min ( remaining. len ( ) , input. len ( ) ) ;
682
689
683
- // We have some previous data saved; try to fill it up and process it first
684
- if !buffer. is_empty ( ) {
685
- let remaining = & mut buffer[ * buffer_usage..] ;
686
- let n_to_copy = usize:: min ( remaining. len ( ) , input. len ( ) ) ;
690
+ let ( remaining_head, remaining_tail) = remaining. split_at_mut ( n_to_copy) ;
691
+ let ( input_head, input_tail) = input. split_at ( n_to_copy) ;
687
692
688
- let ( remaining_head , remaining_tail ) = remaining . split_at_mut ( n_to_copy ) ;
689
- let ( input_head , input_tail ) = input . split_at ( n_to_copy) ;
693
+ remaining_head . copy_from_slice ( input_head ) ;
694
+ * buffer_usage += n_to_copy;
690
695
691
- remaining_head. copy_from_slice ( input_head) ;
692
- * buffer_usage += n_to_copy;
696
+ input = input_tail;
693
697
694
- input = input_tail;
698
+ // We did not fill up the buffer
699
+ if !remaining_tail. is_empty ( ) {
700
+ return ;
701
+ }
695
702
696
- // We did not fill up the buffer
697
- if !remaining_tail . is_empty ( ) {
698
- return ;
699
- }
703
+ // We don't know this isn't the last of the data
704
+ if input . is_empty ( ) {
705
+ return ;
706
+ }
700
707
701
- // We don't know this isn't the last of the data
702
- if input. is_empty ( ) {
703
- return ;
704
- }
708
+ let ( stripes, _) = buffer. bp_as_chunks ( ) ;
709
+ for stripe in stripes {
710
+ stripe_accumulator. process_stripe ( vector, stripe, n_stripes, secret) ;
711
+ }
712
+ * buffer_usage = 0 ;
713
+ }
705
714
706
- let ( stripes, _) = buffer. bp_as_chunks ( ) ;
707
- for stripe in stripes {
708
- stripe_accumulator. process_stripe ( vector, stripe, n_stripes, secret) ;
709
- }
710
- * buffer_usage = 0 ;
711
- }
712
-
713
- debug_assert ! ( * buffer_usage == 0 ) ;
714
-
715
- // Process as much of the input data in-place as possible,
716
- // while leaving at least one full stripe for the
717
- // finalization.
718
- if let Some ( len) = input. len ( ) . checked_sub ( STRIPE_BYTES ) {
719
- let full_block_point = ( len / STRIPE_BYTES ) * STRIPE_BYTES ;
720
- // Safety: We know that `full_block_point` must be less than
721
- // `input.len()` as we subtracted and then integer-divided
722
- // (which rounds down) and then multiplied back. That's not
723
- // evident to the compiler and `split_at` results in a
724
- // potential panic.
725
- //
726
- // https://github.com/llvm/llvm-project/issues/104827
727
- let ( stripes, remainder) = unsafe { input. split_at_unchecked ( full_block_point) } ;
728
- let ( stripes, _) = stripes. bp_as_chunks ( ) ;
729
-
730
- for stripe in stripes {
731
- stripe_accumulator. process_stripe ( vector, stripe, n_stripes, secret)
732
- }
733
- input = remainder;
734
- }
715
+ debug_assert ! ( * buffer_usage == 0 ) ;
716
+
717
+ // Process as much of the input data in-place as possible,
718
+ // while leaving at least one full stripe for the
719
+ // finalization.
720
+ if let Some ( len) = input. len ( ) . checked_sub ( STRIPE_BYTES ) {
721
+ let full_block_point = ( len / STRIPE_BYTES ) * STRIPE_BYTES ;
722
+ // Safety: We know that `full_block_point` must be less than
723
+ // `input.len()` as we subtracted and then integer-divided
724
+ // (which rounds down) and then multiplied back. That's not
725
+ // evident to the compiler and `split_at` results in a
726
+ // potential panic.
727
+ //
728
+ // https://github.com/llvm/llvm-project/issues/104827
729
+ let ( stripes, remainder) = unsafe { input. split_at_unchecked ( full_block_point) } ;
730
+ let ( stripes, _) = stripes. bp_as_chunks ( ) ;
731
+
732
+ for stripe in stripes {
733
+ stripe_accumulator. process_stripe ( & vector, stripe, n_stripes, secret)
734
+ }
735
+ input = remainder;
736
+ }
735
737
736
- // Any remaining data has to be less than the buffer, and the
737
- // buffer is empty so just fill up the buffer.
738
- debug_assert ! ( * buffer_usage == 0 ) ;
739
- debug_assert ! ( !input. is_empty( ) ) ;
738
+ // Any remaining data has to be less than the buffer, and the
739
+ // buffer is empty so just fill up the buffer.
740
+ debug_assert ! ( * buffer_usage == 0 ) ;
741
+ debug_assert ! ( !input. is_empty( ) ) ;
742
+
743
+ // Safety: We have parsed all the full blocks of input except one
744
+ // and potentially a full block minus one byte. That amount of
745
+ // data must be less than the buffer.
746
+ let buffer_head = unsafe {
747
+ debug_assert ! ( input. len( ) < 2 * STRIPE_BYTES ) ;
748
+ debug_assert ! ( 2 * STRIPE_BYTES < buffer. len( ) ) ;
749
+ buffer. get_unchecked_mut ( ..input. len ( ) )
750
+ } ;
740
751
741
- // Safety: We have parsed all the full blocks of input except one
742
- // and potentially a full block minus one byte. That amount of
743
- // data must be less than the buffer.
744
- let buffer_head = unsafe {
745
- debug_assert ! ( input. len( ) < 2 * STRIPE_BYTES ) ;
746
- debug_assert ! ( 2 * STRIPE_BYTES < buffer. len( ) ) ;
747
- buffer. get_unchecked_mut ( ..input. len ( ) )
748
- } ;
752
+ buffer_head. copy_from_slice ( input) ;
753
+ * buffer_usage = input. len ( ) ;
754
+ } ) ;
755
+ }
749
756
750
- buffer_head. copy_from_slice ( input) ;
751
- * buffer_usage = input. len ( ) ;
752
- }
757
+ #[ inline]
758
+ fn finish ( & self ) -> u64 {
759
+ dispatch_f ( |vector| {
760
+ let RawHasher {
761
+ ref secret_buffer,
762
+ buffer_usage,
763
+ mut stripe_accumulator,
764
+ total_bytes,
765
+ } = * self ;
766
+
767
+ let n_stripes = secret_buffer. n_stripes ( ) ;
768
+ let ( seed, secret, buffer) = secret_buffer. parts ( ) ;
769
+
770
+ // Safety: This is an invariant of the buffer.
771
+ unsafe {
772
+ debug_assert ! ( buffer_usage <= buffer. len( ) ) ;
773
+ assert_unchecked ( buffer_usage <= buffer. len ( ) )
774
+ } ;
753
775
754
- #[ inline( always) ]
755
- fn finish_impl < S > ( vector : impl Vector , this : & RawHasher < S > ) -> u64
756
- where
757
- S : FixedBuffer ,
758
- {
759
- let RawHasher {
760
- ref secret_buffer,
761
- buffer_usage,
762
- mut stripe_accumulator,
763
- total_bytes,
764
- } = * this;
765
-
766
- let n_stripes = secret_buffer. n_stripes ( ) ;
767
- let ( seed, secret, buffer) = secret_buffer. parts ( ) ;
768
-
769
- // Safety: This is an invariant of the buffer.
770
- unsafe {
771
- debug_assert ! ( buffer_usage <= buffer. len( ) ) ;
772
- assert_unchecked ( buffer_usage <= buffer. len ( ) )
773
- } ;
776
+ if total_bytes > CUTOFF {
777
+ let input = & buffer[ ..buffer_usage] ;
774
778
775
- if total_bytes > CUTOFF {
776
- let input = & buffer[ ..buffer_usage] ;
779
+ // Ingest final stripes
780
+ let ( stripes, remainder) = stripes_with_tail ( input) ;
781
+ for stripe in stripes {
782
+ stripe_accumulator. process_stripe ( & vector, stripe, n_stripes, secret) ;
783
+ }
777
784
778
- // Ingest final stripes
779
- let ( stripes, remainder) = stripes_with_tail ( input) ;
780
- for stripe in stripes {
781
- stripe_accumulator. process_stripe ( vector, stripe, n_stripes, secret) ;
782
- }
785
+ let mut temp = [ 0 ; 64 ] ;
783
786
784
- let mut temp = [ 0 ; 64 ] ;
787
+ let last_stripe = match input. last_chunk ( ) {
788
+ Some ( chunk) => chunk,
789
+ None => {
790
+ let n_to_reuse = 64 - input. len ( ) ;
791
+ let to_reuse = buffer. len ( ) - n_to_reuse;
785
792
786
- let last_stripe = match input. last_chunk ( ) {
787
- Some ( chunk) => chunk,
788
- None => {
789
- let n_to_reuse = 64 - input. len ( ) ;
790
- let to_reuse = buffer. len ( ) - n_to_reuse;
793
+ let ( temp_head, temp_tail) = temp. split_at_mut ( n_to_reuse) ;
794
+ temp_head. copy_from_slice ( & buffer[ to_reuse..] ) ;
795
+ temp_tail. copy_from_slice ( input) ;
791
796
792
- let ( temp_head , temp_tail ) = temp. split_at_mut ( n_to_reuse ) ;
793
- temp_head . copy_from_slice ( & buffer [ to_reuse.. ] ) ;
794
- temp_tail . copy_from_slice ( input ) ;
797
+ & temp
798
+ }
799
+ } ;
795
800
796
- & temp
801
+ Algorithm ( vector) . finalize (
802
+ stripe_accumulator. accumulator ,
803
+ remainder,
804
+ last_stripe,
805
+ secret,
806
+ total_bytes,
807
+ )
808
+ } else {
809
+ impl_oneshot ( DEFAULT_SECRET , seed, & buffer[ ..total_bytes] )
797
810
}
798
- } ;
799
-
800
- Algorithm ( vector) . finalize (
801
- stripe_accumulator. accumulator ,
802
- remainder,
803
- last_stripe,
804
- secret,
805
- total_bytes,
806
- )
807
- } else {
808
- impl_oneshot ( DEFAULT_SECRET , seed, & buffer[ ..total_bytes] )
811
+ } )
809
812
}
810
813
}
811
814
@@ -1171,12 +1174,22 @@ fn stripes_with_tail(block: &[u8]) -> (&[[u8; 64]], &[u8]) {
1171
1174
}
1172
1175
}
1173
1176
1174
- trait Vector : Copy {
1177
+ trait Vector {
1175
1178
fn round_scramble ( & self , acc : & mut [ u64 ; 8 ] , secret_end : & [ u8 ; 64 ] ) ;
1176
1179
1177
1180
fn accumulate ( & self , acc : & mut [ u64 ; 8 ] , stripe : & [ u8 ; 64 ] , secret : & [ u8 ; 64 ] ) ;
1178
1181
}
1179
1182
1183
+ impl < V : Vector + ?Sized > Vector for & V {
1184
+ fn round_scramble ( & self , acc : & mut [ u64 ; 8 ] , secret_end : & [ u8 ; 64 ] ) {
1185
+ V :: round_scramble ( self , acc, secret_end) ;
1186
+ }
1187
+
1188
+ fn accumulate ( & self , acc : & mut [ u64 ; 8 ] , stripe : & [ u8 ; 64 ] , secret : & [ u8 ; 64 ] ) {
1189
+ V :: accumulate ( self , acc, stripe, secret) ;
1190
+ }
1191
+ }
1192
+
1180
1193
#[ inline]
1181
1194
fn avalanche ( mut x : u64 ) -> u64 {
1182
1195
x ^= x >> 37 ;
0 commit comments