| use crate::{CVWords, IncrementCounter, BLOCK_LEN, OUT_LEN}; |
| |
| // Unsafe because this may only be called on platforms supporting NEON. |
| pub unsafe fn hash_many<A: arrayvec::Array<Item = u8>>( |
| inputs: &[&A], |
| key: &CVWords, |
| counter: u64, |
| increment_counter: IncrementCounter, |
| flags: u8, |
| flags_start: u8, |
| flags_end: u8, |
| out: &mut [u8], |
| ) { |
| // The Rust hash_many implementations do bounds checking on the `out` |
| // array, but the C implementations don't. Even though this is an unsafe |
| // function, assert the bounds here. |
| assert!(out.len() >= inputs.len() * OUT_LEN); |
| ffi::blake3_hash_many_neon( |
| inputs.as_ptr() as *const *const u8, |
| inputs.len(), |
| A::CAPACITY / BLOCK_LEN, |
| key.as_ptr(), |
| counter, |
| increment_counter.yes(), |
| flags, |
| flags_start, |
| flags_end, |
| out.as_mut_ptr(), |
| ) |
| } |
| |
| // blake3_neon.c normally depends on blake3_portable.c, because the NEON |
| // implementation only provides 4x compression, and it relies on the portable |
| // implementation for 1x compression. However, we expose the portable Rust |
| // implementation here instead, to avoid linking in unnecessary code. |
| #[no_mangle] |
| pub extern "C" fn blake3_compress_in_place_portable( |
| cv: *mut u32, |
| block: *const u8, |
| block_len: u8, |
| counter: u64, |
| flags: u8, |
| ) { |
| unsafe { |
| crate::portable::compress_in_place( |
| &mut *(cv as *mut [u32; 8]), |
| &*(block as *const [u8; 64]), |
| block_len, |
| counter, |
| flags, |
| ) |
| } |
| } |
| |
| pub mod ffi { |
| extern "C" { |
| pub fn 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, |
| ); |
| } |
| } |
| |
| #[cfg(test)] |
| mod test { |
| use super::*; |
| |
| #[test] |
| fn test_hash_many() { |
| // This entire file is gated on feature="neon", so NEON support is |
| // assumed here. |
| crate::test::test_hash_many_fn(hash_many, hash_many); |
| } |
| } |