1 use crate::{CVWords, IncrementCounter, BLOCK_LEN, OUT_LEN};
2 
3 // Unsafe because this may only be called on platforms supporting AVX-512.
compress_in_place( cv: &mut CVWords, block: &[u8; BLOCK_LEN], block_len: u8, counter: u64, flags: u8, )4 pub unsafe fn compress_in_place(
5     cv: &mut CVWords,
6     block: &[u8; BLOCK_LEN],
7     block_len: u8,
8     counter: u64,
9     flags: u8,
10 ) {
11     ffi::blake3_compress_in_place_avx512(cv.as_mut_ptr(), block.as_ptr(), block_len, counter, flags)
12 }
13 
14 // Unsafe because this may only be called on platforms supporting AVX-512.
compress_xof( cv: &CVWords, block: &[u8; BLOCK_LEN], block_len: u8, counter: u64, flags: u8, ) -> [u8; 64]15 pub unsafe fn compress_xof(
16     cv: &CVWords,
17     block: &[u8; BLOCK_LEN],
18     block_len: u8,
19     counter: u64,
20     flags: u8,
21 ) -> [u8; 64] {
22     let mut out = [0u8; 64];
23     ffi::blake3_compress_xof_avx512(
24         cv.as_ptr(),
25         block.as_ptr(),
26         block_len,
27         counter,
28         flags,
29         out.as_mut_ptr(),
30     );
31     out
32 }
33 
34 // Unsafe because this may only be called on platforms supporting AVX-512.
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], )35 pub unsafe fn hash_many<const N: usize>(
36     inputs: &[&[u8; N]],
37     key: &CVWords,
38     counter: u64,
39     increment_counter: IncrementCounter,
40     flags: u8,
41     flags_start: u8,
42     flags_end: u8,
43     out: &mut [u8],
44 ) {
45     // The Rust hash_many implementations do bounds checking on the `out`
46     // array, but the C implementations don't. Even though this is an unsafe
47     // function, assert the bounds here.
48     assert!(out.len() >= inputs.len() * OUT_LEN);
49     ffi::blake3_hash_many_avx512(
50         inputs.as_ptr() as *const *const u8,
51         inputs.len(),
52         N / BLOCK_LEN,
53         key.as_ptr(),
54         counter,
55         increment_counter.yes(),
56         flags,
57         flags_start,
58         flags_end,
59         out.as_mut_ptr(),
60     )
61 }
62 
63 pub mod ffi {
64     extern "C" {
blake3_compress_in_place_avx512( cv: *mut u32, block: *const u8, block_len: u8, counter: u64, flags: u8, )65         pub fn blake3_compress_in_place_avx512(
66             cv: *mut u32,
67             block: *const u8,
68             block_len: u8,
69             counter: u64,
70             flags: u8,
71         );
blake3_compress_xof_avx512( cv: *const u32, block: *const u8, block_len: u8, counter: u64, flags: u8, out: *mut u8, )72         pub fn blake3_compress_xof_avx512(
73             cv: *const u32,
74             block: *const u8,
75             block_len: u8,
76             counter: u64,
77             flags: u8,
78             out: *mut u8,
79         );
blake3_hash_many_avx512( 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, )80         pub fn blake3_hash_many_avx512(
81             inputs: *const *const u8,
82             num_inputs: usize,
83             blocks: usize,
84             key: *const u32,
85             counter: u64,
86             increment_counter: bool,
87             flags: u8,
88             flags_start: u8,
89             flags_end: u8,
90             out: *mut u8,
91         );
92     }
93 }
94 
95 #[cfg(test)]
96 mod test {
97     use super::*;
98 
99     #[test]
test_compress()100     fn test_compress() {
101         if !crate::platform::avx512_detected() {
102             return;
103         }
104         crate::test::test_compress_fn(compress_in_place, compress_xof);
105     }
106 
107     #[test]
test_hash_many()108     fn test_hash_many() {
109         if !crate::platform::avx512_detected() {
110             return;
111         }
112         crate::test::test_hash_many_fn(hash_many, hash_many);
113     }
114 }
115