solana_nostd_blake3/
lib.rs1use core::mem::MaybeUninit;
2
3#[cfg(not(target_os = "solana"))]
4use blake3::Hasher;
5
6pub const HASH_LENGTH: usize = 32;
7
8#[cfg(target_os = "solana")]
9extern "C" {
10 fn sol_blake3(vals: *const u8, val_len: u64, hash_result: *mut u8) -> u64;
11}
12
13#[cfg_attr(target_os = "solana", inline(always))]
14pub fn hash(data: &[u8]) -> [u8;HASH_LENGTH] {
15 hashv(&[data])
16}
17
18#[inline(always)]
19pub fn hash_ref<T: AsRef<[u8]>>(data: T) -> [u8;HASH_LENGTH] {
20 hashv(&[data.as_ref()])
21}
22
23#[cfg(not(target_os = "solana"))]
24pub fn hashv(data: &[&[u8]]) -> [u8; HASH_LENGTH] {
25 let mut out = MaybeUninit::<[u8; HASH_LENGTH]>::uninit();
26 unsafe {
27 hash_into(data, out.assume_init_mut());
28 out.assume_init()
29 }
30}
31
32#[cfg(target_os = "solana")]
33#[inline(always)]
34pub fn hashv(data: &[&[u8]]) -> [u8; HASH_LENGTH] {
35 let mut out = MaybeUninit::<[u8; HASH_LENGTH]>::uninit();
36 unsafe {
37 hash_into(data, out.as_mut_ptr());
38 out.assume_init()
39 }
40}
41
42#[cfg(not(target_os = "solana"))]
43pub fn hash_into(data: &[&[u8]], out: &mut [u8; HASH_LENGTH]) {
44 let mut hasher = Hasher::new();
45 for item in data {
46 hasher.update(item);
47 }
48 hasher.finalize_xof().fill(out);
49}
50
51#[cfg(target_os = "solana")]
52#[inline(always)]
53pub fn hash_into(data: &[&[u8]], out: *mut [u8; 32]) {
54 unsafe {
55 sol_blake3(
56 data as *const _ as *const u8,
57 data.len() as u64,
58 out as *mut u8,
59 );
60 }
61}
62
63#[cfg(test)]
64mod tests {
65 use crate::*;
66
67 #[test]
68 fn test_hash() {
69 let h = hash_ref("test");
70 let h2 = hashv(&[b"test".as_ref()]);
71 assert_eq!(h, h2);
72 assert_eq!(h2, [0x48, 0x78, 0xca, 0x04, 0x25, 0xc7, 0x39, 0xfa, 0x42, 0x7f, 0x7e, 0xda, 0x20, 0xfe, 0x84, 0x5f, 0x6b, 0x2e, 0x46, 0xba, 0x5f, 0xe2, 0xa1, 0x4d, 0xf5, 0xb1, 0xe3, 0x2f, 0x50, 0x60, 0x32, 0x15]);
73 }
74}