1#![allow(non_camel_case_types)]
5
6use core::hash::{BuildHasher, Hasher};
7
8use osom_lib_reprc::macros::reprc;
9
10use super::traits::HashFunction;
11
12macro_rules! build_fnv {
13 ( $variant: tt, $underlying_type: tt ) => {
14 ::paste::paste! {
15 #[doc = "The [FNV](https://en.wikipedia.org/wiki/Fowler%E2%80%93Noll%E2%80%93Vo_hash_function) algorithm in version " $variant " with " $underlying_type "bit size."]
16 #[derive(PartialEq, Eq)]
17 #[reprc]
18 #[must_use]
19 pub struct [< FNV $variant _ $underlying_type >] {
20 state: [< u $underlying_type >],
21 }
22
23 impl Default for [< FNV $variant _ $underlying_type >] {
24 #[inline(always)]
25 fn default() -> Self {
26 Self::new()
27 }
28 }
29
30 impl [< FNV $variant _ $underlying_type >] {
31 #[doc = "Creates a new instance of [`FNV" $variant "_" $underlying_type "`] with the default initial state."]
32 #[inline(always)]
33 pub const fn new() -> Self {
34 Self {
35 state: Self::INITIAL,
36 }
37 }
38
39 #[doc = "Creates a new instance of [`FNV" $variant "_" $underlying_type "`] from seed."]
40 pub const fn with_seed(seed: [< u $underlying_type >]) -> Self {
41 let seed = seed.to_le_bytes();
42 let mut result = Self::new();
43 result.result_const(&seed);
44 result
45 }
46
47 #[doc = "Returns calculated hash."]
48 #[inline(always)]
49 pub const fn update_const(&self) -> [< u $underlying_type >] {
50 self.state
51 }
52
53 #[inline(always)]
54 const fn clone_const(&self) -> Self {
55 Self {
56 state: self.state,
57 }
58 }
59 }
60
61 impl Hasher for [< FNV $variant _ $underlying_type >] {
62 #[allow(clippy::cast_possible_truncation)]
63 #[inline(always)]
64 fn finish(&self) -> u64 {
65 self.update_const() as u64
66 }
67
68 #[inline(always)]
69 fn write(&mut self, bytes: &[u8]) {
70 self.update(bytes);
71 }
72 }
73
74 impl HashFunction for [< FNV $variant _ $underlying_type >] {
75 type Output = [u8; size_of::<[< u $underlying_type >]>()];
76
77 #[inline(always)]
78 fn update(&mut self, data: impl AsRef<[u8]>) {
79 self.result_const(data.as_ref())
80 }
81
82 #[inline(always)]
83 fn write_result(&self, output: &mut Self::Output ) {
84 *output = self.update_const().to_le_bytes();
85 }
86 }
87
88 #[doc = "A standard builder that produces [`FNV" $variant "_" $underlying_type "`] hash with fixed seed."]
89 #[reprc]
90 #[derive(PartialEq, Eq)]
91 #[must_use]
92 pub struct [< FNV $variant _ $underlying_type HasherBuilder >] {
93 inner: [< FNV $variant _ $underlying_type >],
94 }
95
96 impl [< FNV $variant _ $underlying_type HasherBuilder >] {
97 #[doc = "Creates new [`FNV" $variant "_" $underlying_type "HasherBuilder`]."]
98 #[inline(always)]
99 pub const fn new() -> Self {
100 Self {
101 inner: [< FNV $variant _ $underlying_type >]::new(),
102 }
103 }
104
105 #[doc = "Creates new [`FNV" $variant "_" $underlying_type "HasherBuilder`] with a fixed seed,"]
106 #[doc = "which will be used to initialize the hash function."]
107 #[inline(always)]
108 pub const fn with_seed(seed: [< u $underlying_type >]) -> Self {
109 Self {
110 inner: [< FNV $variant _ $underlying_type >]::with_seed(seed),
111 }
112 }
113
114
115 #[doc = "Creates new [`FNV" $variant "_" $underlying_type "`] instance."]
116 #[inline(always)]
117 pub const fn create_hasher(&self) -> [< FNV $variant _ $underlying_type >] {
118 self.inner.clone_const()
119 }
120 }
121
122 impl Default for [< FNV $variant _ $underlying_type HasherBuilder >] {
123 #[inline(always)]
124 fn default() -> Self {
125 Self::new()
126 }
127 }
128
129 impl Clone for [< FNV $variant _ $underlying_type HasherBuilder >] {
130 #[inline(always)]
131 fn clone(&self) -> Self {
132 Self {
133 inner: self.inner.clone_const(),
134 }
135 }
136 }
137
138 impl BuildHasher for [< FNV $variant _ $underlying_type HasherBuilder >] {
139 type Hasher = [< FNV $variant _ $underlying_type >];
140
141 #[inline(always)]
142 fn build_hasher(&self) -> Self::Hasher {
143 self.create_hasher()
144 }
145 }
146 }
147 };
148}
149
150build_fnv!(1a, 64);
151build_fnv!(1, 64);
152build_fnv!(1a, 128);
153build_fnv!(1, 128);
154
155impl FNV1a_64 {
156 const INITIAL: u64 = 0xcbf29ce484222325;
157 const MULTIPLIER: u64 = 0x00000100000001b3;
158
159 pub const fn result_const(&mut self, data: &[u8]) {
161 let mut current = self.state;
162 let mut index = 0;
163 let len = data.len();
164 while index < len {
165 let byte = data[index];
166 current = current ^ (byte as u64);
167 current = current.wrapping_mul(Self::MULTIPLIER);
168 index += 1;
169 }
170 self.state = current;
171 }
172}
173
174impl FNV1_64 {
175 const INITIAL: u64 = 0xcbf29ce484222325;
176 const MULTIPLIER: u64 = 0x00000100000001b3;
177
178 pub const fn result_const(&mut self, data: &[u8]) {
180 let mut current = self.state;
181 let mut index = 0;
182 let len = data.len();
183 while index < len {
184 let byte = data[index];
185 current = current.wrapping_mul(Self::MULTIPLIER);
186 current = current ^ (byte as u64);
187 index += 1;
188 }
189 self.state = current;
190 }
191}
192
193impl FNV1a_128 {
194 const INITIAL: u128 = 0x6c62272e07bb014262b821756295c58d;
195 const MULTIPLIER: u128 = 0x0000000001000000000000000000013b;
196
197 pub const fn result_const(&mut self, data: &[u8]) {
199 let mut current = self.state;
200 let mut index = 0;
201 let len = data.len();
202 while index < len {
203 let byte = data[index];
204 current = current ^ (byte as u128);
205 current = current.wrapping_mul(Self::MULTIPLIER);
206 index += 1;
207 }
208 self.state = current;
209 }
210}
211
212impl FNV1_128 {
213 const INITIAL: u128 = 0x6c62272e07bb014262b821756295c58d;
214 const MULTIPLIER: u128 = 0x0000000001000000000000000000013b;
215
216 pub const fn result_const(&mut self, data: &[u8]) {
218 let mut current = self.state;
219 let mut index = 0;
220 let len = data.len();
221 while index < len {
222 let byte = data[index];
223 current = current.wrapping_mul(Self::MULTIPLIER);
224 current = current ^ (byte as u128);
225 index += 1;
226 }
227 self.state = current;
228 }
229}