1use std::{cmp::min, hash::Hasher};
2
3pub trait KeyBase {
5 fn len(&self) -> usize;
7 fn is_empty(&self) -> bool {
8 self.len() == 0
9 }
10 fn hash<H: Hasher>(&self, state: &mut H);
13}
14
15impl KeyBase for &'_ [u8] {
16 fn len(&self) -> usize {
17 <[u8]>::len(self)
18 }
19
20 fn is_empty(&self) -> bool {
21 <[u8]>::is_empty(self)
22 }
23
24 fn hash<H: Hasher>(&self, state: &mut H) {
25 state.write(self);
26 }
27}
28
29impl<const N: usize> KeyBase for [u8; N] {
30 fn len(&self) -> usize {
31 N
32 }
33
34 fn is_empty(&self) -> bool {
35 N > 0
36 }
37
38 fn hash<H: Hasher>(&self, state: &mut H) {
39 state.write(self);
40 }
41}
42
43impl KeyBase for Vec<u8> {
44 fn len(&self) -> usize {
45 self.len()
46 }
47
48 fn is_empty(&self) -> bool {
49 self.is_empty()
50 }
51
52 fn hash<H: Hasher>(&self, state: &mut H) {
53 state.write(self);
54 }
55}
56
57impl KeyBase for Box<[u8]> {
58 fn len(&self) -> usize {
59 (**self).len()
60 }
61
62 fn is_empty(&self) -> bool {
63 (**self).is_empty()
64 }
65
66 fn hash<H: Hasher>(&self, state: &mut H) {
67 state.write(self);
68 }
69}
70
71impl KeyBase for u8 {
72 fn len(&self) -> usize {
73 1
74 }
75
76 fn is_empty(&self) -> bool {
77 false
78 }
79
80 fn hash<H: Hasher>(&self, state: &mut H) {
81 state.write_u8(*self);
82 }
83}
84
85impl<A: KeyBase, B: KeyBase> KeyBase for (A, B) {
86 fn len(&self) -> usize {
87 let (a, b) = self;
88 a.len() + b.len()
89 }
90
91 fn is_empty(&self) -> bool {
92 let (a, b) = self;
93 a.is_empty() && b.is_empty()
94 }
95
96 fn hash<H: Hasher>(&self, state: &mut H) {
97 let (a, b) = self;
98 KeyBase::hash(a, state);
99 KeyBase::hash(b, state);
100 }
101}
102
103impl<T: KeyBase> KeyBase for &'_ T {
104 fn len(&self) -> usize {
105 (*self).len()
106 }
107
108 fn is_empty(&self) -> bool {
109 (*self).is_empty()
110 }
111
112 fn hash<H: Hasher>(&self, state: &mut H) {
113 (*self).hash(state)
114 }
115}
116
117pub trait QueryKey: KeyBase {
120 fn cmp(&self, key: &[u8]) -> std::cmp::Ordering;
121}
122
123impl QueryKey for &'_ [u8] {
124 fn cmp(&self, key: &[u8]) -> std::cmp::Ordering {
125 Ord::cmp(self, &key)
126 }
127}
128
129impl<const N: usize> QueryKey for [u8; N] {
130 fn cmp(&self, key: &[u8]) -> std::cmp::Ordering {
131 Ord::cmp(&self[..], key)
132 }
133}
134
135impl QueryKey for Vec<u8> {
136 fn cmp(&self, key: &[u8]) -> std::cmp::Ordering {
137 Ord::cmp(&**self, key)
138 }
139}
140
141impl QueryKey for Box<[u8]> {
142 fn cmp(&self, key: &[u8]) -> std::cmp::Ordering {
143 Ord::cmp(&**self, key)
144 }
145}
146
147impl QueryKey for u8 {
148 fn cmp(&self, key: &[u8]) -> std::cmp::Ordering {
149 Ord::cmp(&[*self][..], key)
150 }
151}
152
153impl<A: QueryKey, B: QueryKey> QueryKey for (A, B) {
154 fn cmp(&self, mut key: &[u8]) -> std::cmp::Ordering {
155 let (a, b) = self;
156 let len = a.len();
157 let key_len = key.len();
158 let key_part = &key[..min(key_len, len)];
159 match a.cmp(key_part) {
160 std::cmp::Ordering::Equal => {
161 key = &key[len..];
162 b.cmp(key)
163 }
164 ord => ord,
165 }
166 }
167}
168
169impl<T: QueryKey> QueryKey for &'_ T {
170 fn cmp(&self, key: &[u8]) -> std::cmp::Ordering {
171 (*self).cmp(key)
172 }
173}
174
175pub trait StoreKey: KeyBase + Ord {
177 fn write_to(&self, buf: &mut Vec<u8>);
178}
179
180impl<const N: usize> StoreKey for [u8; N] {
181 fn write_to(&self, buf: &mut Vec<u8>) {
182 buf.extend_from_slice(&self[..]);
183 }
184}
185
186impl StoreKey for Vec<u8> {
187 fn write_to(&self, buf: &mut Vec<u8>) {
188 buf.extend_from_slice(self);
189 }
190}
191
192impl StoreKey for Box<[u8]> {
193 fn write_to(&self, buf: &mut Vec<u8>) {
194 buf.extend_from_slice(self);
195 }
196}
197
198impl StoreKey for &'_ [u8] {
199 fn write_to(&self, buf: &mut Vec<u8>) {
200 buf.extend_from_slice(self);
201 }
202}
203
204impl StoreKey for u8 {
205 fn write_to(&self, buf: &mut Vec<u8>) {
206 buf.push(*self);
207 }
208}
209
210impl<A: StoreKey, B: StoreKey> StoreKey for (A, B) {
211 fn write_to(&self, buf: &mut Vec<u8>) {
212 self.0.write_to(buf);
213 self.1.write_to(buf);
214 }
215}
216
217impl<T: StoreKey> StoreKey for &'_ T {
218 fn write_to(&self, buf: &mut Vec<u8>) {
219 (*self).write_to(buf);
220 }
221}
222
223pub fn hash_key(key: &impl KeyBase) -> u64 {
225 let mut hasher = xxhash_rust::xxh3::Xxh3Default::new();
226 key.hash(&mut hasher);
227 hasher.finish()
228}
229
230#[cfg(test)]
231mod tests {
232 use std::cmp::Ordering;
233
234 use crate::{QueryKey, key::hash_key};
235
236 #[test]
237 fn tuple() {
238 let key = (&[1, 2], &[3, 4]);
239 assert_eq!(QueryKey::cmp(&key, &[1, 2, 3, 4]), Ordering::Equal);
240 assert_eq!(QueryKey::cmp(&key, &[1, 2, 3, 3]), Ordering::Greater);
241 assert_eq!(QueryKey::cmp(&key, &[1, 2, 3, 5]), Ordering::Less);
242 assert_eq!(QueryKey::cmp(&key, &[0, 2, 3, 4]), Ordering::Greater);
243 assert_eq!(QueryKey::cmp(&key, &[2, 2, 3, 4]), Ordering::Less);
244 assert_eq!(QueryKey::cmp(&key, &[1, 2, 3, 4, 5]), Ordering::Less);
245 assert_eq!(QueryKey::cmp(&key, &[1, 2, 3]), Ordering::Greater);
246 assert_eq!(QueryKey::cmp(&key, &[1, 2]), Ordering::Greater);
247 assert_eq!(QueryKey::cmp(&key, &[1]), Ordering::Greater);
248 assert_eq!(QueryKey::cmp(&key, &[]), Ordering::Greater);
249 }
250
251 #[test]
252 fn hash() {
253 let h1 = hash_key(&[1, 2, 3, 4]);
254 let h2 = hash_key(&(&[1, 2], &[3, 4]));
255 let h3 = hash_key(&(vec![1, 2, 3], 4u8));
256 assert_eq!(h2, h1);
257 assert_eq!(h3, h1);
258 }
259}