1#[cfg(any(
2 target_arch = "x86_64",
3 target_arch = "aarch64",
4 all(target_family = "wasm", target_feature = "simd128")
5))]
6pub fn unordered_load3(from: &[u8]) -> u64 {
7 if from.is_empty() {
8 return 0;
9 }
10
11 let size_mod4 = from.len() % 4;
12
13 u64::from(from[0])
14 + (u64::from(from[size_mod4 >> 1]) << 8)
15 + (u64::from(from[size_mod4 - 1]) << 16)
16}
17
18pub const PACKET_SIZE: usize = 32;
19
20#[repr(C)]
24#[derive(Default, Debug, Clone, Copy)]
25pub struct HashPacket {
26 pub(crate) buf: [u8; PACKET_SIZE],
27 buf_index: usize,
28}
29
30impl HashPacket {
31 #[inline]
32 pub const fn len(&self) -> usize {
33 self.buf_index
34 }
35
36 #[inline]
37 pub const fn is_empty(&self) -> bool {
38 self.buf_index == 0
39 }
40
41 #[inline]
42 pub fn as_slice(&self) -> &[u8] {
43 debug_assert!(self.buf_index <= self.buf.len(), "buf index too long");
44 self.buf.get(..self.buf_index).unwrap_or(&self.buf)
45 }
46
47 #[inline]
48 pub const fn inner(&self) -> &[u8; PACKET_SIZE] {
49 &self.buf
50 }
51
52 #[inline]
53 pub fn fill<'a>(&mut self, data: &'a [u8]) -> Option<&'a [u8]> {
54 let dest = self.buf.get_mut(self.buf_index..).unwrap_or_default();
55 if dest.len() > data.len() {
56 dest[..data.len()].copy_from_slice(data);
57 self.buf_index += data.len();
58 None
59 } else {
60 let (head, tail) = data.split_at(dest.len());
61 dest.copy_from_slice(head);
62 self.buf_index = PACKET_SIZE;
63 Some(tail)
64 }
65 }
66
67 #[inline]
68 pub fn set_to(&mut self, data: &[u8]) {
69 debug_assert!(
70 data.len() < PACKET_SIZE,
71 "data large enough to process packet"
72 );
73 self.buf_index = data.len();
74 if !data.is_empty() {
75 self.buf[..data.len()].copy_from_slice(data);
76 }
77 }
78}
79
80#[cfg(test)]
81mod tests {
82 use super::*;
83
84 #[test]
85 fn test_hash_packet() {
86 let mut packet: HashPacket = Default::default();
87 for i in 0..31 {
88 assert_eq!(&vec![0; i as usize][..], packet.as_slice());
89 if let Some(_) = packet.fill(&[0]) {
90 assert!(false);
91 }
92
93 assert_eq!(i + 1, packet.len() as u8);
94 assert_eq!(&vec![0; (i + 1) as usize][..], packet.as_slice());
95 }
96 }
97
98 #[test]
99 fn test_hash_cusp_full_packet() {
100 let mut packet: HashPacket = Default::default();
101 assert_eq!(Some(&[][..]), packet.fill(&[0; 32]));
102 assert_eq!(32, packet.len());
103 }
104
105 #[test]
106 fn test_hash_packet_set_to() {
107 let mut packet: HashPacket = Default::default();
108 for i in 0..31 {
109 let d = vec![0; i as usize];
110 packet.set_to(&d[..]);
111 assert_eq!(&d[..], packet.as_slice());
112 assert_eq!(d.len(), packet.len());
113 }
114 }
115}