1 use crate::{CVWords, IncrementCounter, BLOCK_LEN, OUT_LEN};
2 
3 // Unsafe because this may only be called on platforms supporting NEON.
hash_many<const N: usize>( inputs: &[&[u8; N]], key: &CVWords, counter: u64, increment_counter: IncrementCounter, flags: u8, flags_start: u8, flags_end: u8, out: &mut [u8], )4 pub unsafe fn hash_many<const N: usize>(
5     inputs: &[&[u8; N]],
6     key: &CVWords,
7     counter: u64,
8     increment_counter: IncrementCounter,
9     flags: u8,
10     flags_start: u8,
11     flags_end: u8,
12     out: &mut [u8],
13 ) {
14     // The Rust hash_many implementations do bounds checking on the `out`
15     // array, but the C implementations don't. Even though this is an unsafe
16     // function, assert the bounds here.
17     assert!(out.len() >= inputs.len() * OUT_LEN);
18     ffi::blake3_hash_many_neon(
19         inputs.as_ptr() as *const *const u8,
20         inputs.len(),
21         N / BLOCK_LEN,
22         key.as_ptr(),
23         counter,
24         increment_counter.yes(),
25         flags,
26         flags_start,
27         flags_end,
28         out.as_mut_ptr(),
29     )
30 }
31 
32 // blake3_neon.c normally depends on blake3_portable.c, because the NEON
33 // implementation only provides 4x compression, and it relies on the portable
34 // implementation for 1x compression. However, we expose the portable Rust
35 // implementation here instead, to avoid linking in unnecessary code.
36 #[no_mangle]
blake3_compress_in_place_portable( cv: *mut u32, block: *const u8, block_len: u8, counter: u64, flags: u8, )37 pub extern "C" fn blake3_compress_in_place_portable(
38     cv: *mut u32,
39     block: *const u8,
40     block_len: u8,
41     counter: u64,
42     flags: u8,
43 ) {
44     unsafe {
45         crate::portable::compress_in_place(
46             &mut *(cv as *mut [u32; 8]),
47             &*(block as *const [u8; 64]),
48             block_len,
49             counter,
50             flags,
51         )
52     }
53 }
54 
55 pub mod ffi {
56     extern "C" {
blake3_hash_many_neon( inputs: *const *const u8, num_inputs: usize, blocks: usize, key: *const u32, counter: u64, increment_counter: bool, flags: u8, flags_start: u8, flags_end: u8, out: *mut u8, )57         pub fn blake3_hash_many_neon(
58             inputs: *const *const u8,
59             num_inputs: usize,
60             blocks: usize,
61             key: *const u32,
62             counter: u64,
63             increment_counter: bool,
64             flags: u8,
65             flags_start: u8,
66             flags_end: u8,
67             out: *mut u8,
68         );
69     }
70 }
71 
72 #[cfg(test)]
73 mod test {
74     use super::*;
75 
76     #[test]
test_hash_many()77     fn test_hash_many() {
78         // This entire file is gated on feature="neon", so NEON support is
79         // assumed here.
80         crate::test::test_hash_many_fn(hash_many, hash_many);
81     }
82 }
83