1#[inline(always)]
7pub fn read_int(buf: &[u8]) -> u64 {
8 let ptr = buf.as_ptr();
11
12 unsafe {
13 match buf.len() {
16 1 => *ptr as u64,
18 2 => (ptr as *const u16).read_unaligned().to_le() as u64,
20 3 => {
22 let a = (ptr as *const u16).read_unaligned().to_le() as u64;
23 let b = *ptr.offset(2) as u64;
24
25 a | (b << 16)
26 }
27 4 => (ptr as *const u32).read_unaligned().to_le() as u64,
29 5 => {
31 let a = (ptr as *const u32).read_unaligned().to_le() as u64;
32 let b = *ptr.offset(4) as u64;
33
34 a | (b << 32)
35 }
36 6 => {
38 let a = (ptr as *const u32).read_unaligned().to_le() as u64;
39 let b = (ptr.offset(4) as *const u16).read_unaligned().to_le() as u64;
40
41 a | (b << 32)
42 }
43 7 => {
45 let a = (ptr as *const u32).read_unaligned().to_le() as u64;
46 let b = (ptr.offset(4) as *const u16).read_unaligned().to_le() as u64;
47 let c = *ptr.offset(6) as u64;
48
49 a | (b << 32) | (c << 48)
50 }
51 _ => 0,
52 }
53 }
54}
55
56#[inline(always)]
58pub unsafe fn read_u64(ptr: *const u8) -> u64 {
59 #[cfg(target_pointer_width = "32")]
60 {
61 let a = (ptr as *const u32).read_unaligned().to_le();
64 let b = (ptr.offset(4) as *const u32).read_unaligned().to_le();
65
66 a as u64 | ((b as u64) << 32)
67 }
68
69 #[cfg(target_pointer_width = "64")]
70 {
71 (ptr as *const u64).read_unaligned().to_le()
72 }
73}
74
75pub const fn diffuse(mut x: u64) -> u64 {
80 x = x.wrapping_mul(0x6eed0e9da4d94a4f);
86 let a = x >> 32;
87 let b = x >> 60;
88 x ^= a >> b;
89 x = x.wrapping_mul(0x6eed0e9da4d94a4f);
90
91 x
92}
93
94pub const fn undiffuse(mut x: u64) -> u64 {
96 x = x.wrapping_mul(0x2f72b4215a3d8caf);
99 let a = x >> 32;
100 let b = x >> 60;
101 x ^= a >> b;
102 x = x.wrapping_mul(0x2f72b4215a3d8caf);
103
104 x
105}
106
107#[cfg(test)]
108mod tests {
109 use super::*;
110
111 fn diffuse_test(x: u64, y: u64) {
112 assert_eq!(diffuse(x), y);
113 assert_eq!(x, undiffuse(y));
114 assert_eq!(undiffuse(diffuse(x)), x);
115 }
116
117 #[test]
118 fn read_int_() {
119 assert_eq!(read_int(&[2, 3]), 770);
120 assert_eq!(read_int(&[3, 2]), 515);
121 assert_eq!(read_int(&[3, 2, 5]), 328195);
122 }
123
124 #[test]
125 fn read_u64_() {
126 unsafe {
127 assert_eq!(read_u64([1, 0, 0, 0, 0, 0, 0, 0].as_ptr()), 1);
128 assert_eq!(read_u64([2, 1, 0, 0, 0, 0, 0, 0].as_ptr()), 258);
129 }
130 }
131
132 #[test]
133 fn diffuse_test_vectors() {
134 diffuse_test(94203824938, 17289265692384716055);
135 diffuse_test(0xDEADBEEF, 12110756357096144265);
136 diffuse_test(0, 0);
137 diffuse_test(1, 15197155197312260123);
138 diffuse_test(2, 1571904453004118546);
139 diffuse_test(3, 16467633989910088880);
140 }
141}