1use alloc::string::String;
2use alloc::vec::Vec;
3use core::ops::{Add, Sub};
4use num_traits::{Bounded, NumCast, ToPrimitive, Zero};
5
6use crate::util::bytes::Prefix;
7
8pub trait Key:
9 Copy
10 + Clone
11 + Ord
12 + Default
13 + Send
14 + Sync
15 + ToPrimitive
16 + Bounded
17 + Zero
18 + Add<Output = Self>
19 + Sub<Output = Self>
20{
21 type Unsigned: Copy + Ord + ToPrimitive + NumCast;
22
23 fn to_unsigned(self) -> Self::Unsigned;
24
25 fn to_f64_fast(self) -> f64;
26
27 fn to_i64_fast(self) -> i64;
28}
29
30macro_rules! impl_key_unsigned {
31 ($($t:ty),*) => {
32 $(
33 impl Key for $t {
34 type Unsigned = $t;
35
36 #[inline]
37 fn to_unsigned(self) -> Self::Unsigned {
38 self
39 }
40
41 #[inline]
42 fn to_f64_fast(self) -> f64 {
43 self as f64
44 }
45
46 #[inline]
47 fn to_i64_fast(self) -> i64 {
48 self as i64
49 }
50 }
51 )*
52 };
53}
54
55macro_rules! impl_key_signed {
56 ($(($signed:ty, $unsigned:ty)),*) => {
57 $(
58 impl Key for $signed {
59 type Unsigned = $unsigned;
60
61 #[inline]
62 fn to_unsigned(self) -> Self::Unsigned {
63 const OFFSET: $unsigned = <$signed>::MIN as $unsigned;
64 (self as $unsigned).wrapping_sub(OFFSET)
65 }
66
67 #[inline]
68 fn to_f64_fast(self) -> f64 {
69 self as f64
70 }
71
72 #[inline]
73 fn to_i64_fast(self) -> i64 {
74 self as i64
75 }
76 }
77 )*
78 };
79}
80
81impl_key_unsigned!(u8, u16, u32, u64, u128, usize);
82impl_key_signed!(
83 (i8, u8),
84 (i16, u16),
85 (i32, u32),
86 (i64, u64),
87 (i128, u128),
88 (isize, usize)
89);
90
91pub trait Indexable {
112 type Key: Key;
114
115 fn index_key(&self) -> Self::Key;
117}
118
119macro_rules! impl_indexable_numeric {
120 ($($t:ty),*) => {
121 $(
122 impl Indexable for $t {
123 type Key = $t;
124
125 #[inline]
126 fn index_key(&self) -> Self::Key {
127 *self
128 }
129 }
130 )*
131 };
132}
133
134impl_indexable_numeric!(u8, u16, u32, u64, usize, i8, i16, i32, i64, isize);
135
136impl Indexable for String {
137 type Key = Prefix;
138
139 #[inline]
140 fn index_key(&self) -> Prefix {
141 Prefix::from_bytes(self.as_bytes())
142 }
143}
144
145impl Indexable for str {
146 type Key = Prefix;
147
148 #[inline]
149 fn index_key(&self) -> Prefix {
150 Prefix::from_bytes(self.as_bytes())
151 }
152}
153
154impl Indexable for [u8] {
155 type Key = Prefix;
156
157 #[inline]
158 fn index_key(&self) -> Prefix {
159 Prefix::from_bytes(self)
160 }
161}
162
163impl Indexable for Vec<u8> {
164 type Key = Prefix;
165
166 #[inline]
167 fn index_key(&self) -> Prefix {
168 Prefix::from_bytes(self)
169 }
170}
171
172impl<const N: usize> Indexable for [u8; N] {
173 type Key = Prefix;
174
175 #[inline]
176 fn index_key(&self) -> Prefix {
177 Prefix::from_bytes(self)
178 }
179}
180
181impl<T: Indexable + ?Sized> Indexable for &T {
183 type Key = T::Key;
184
185 #[inline]
186 fn index_key(&self) -> Self::Key {
187 (*self).index_key()
188 }
189}
190
191impl<T: Indexable + ?Sized> Indexable for &mut T {
192 type Key = T::Key;
193
194 #[inline]
195 fn index_key(&self) -> Self::Key {
196 (**self).index_key()
197 }
198}
199
200impl<T: Indexable + ?Sized> Indexable for alloc::boxed::Box<T> {
201 type Key = T::Key;
202
203 #[inline]
204 fn index_key(&self) -> Self::Key {
205 (**self).index_key()
206 }
207}
208
209impl<T: Indexable + ?Sized> Indexable for alloc::rc::Rc<T> {
210 type Key = T::Key;
211
212 #[inline]
213 fn index_key(&self) -> Self::Key {
214 (**self).index_key()
215 }
216}
217
218impl<T: Indexable + ?Sized> Indexable for alloc::sync::Arc<T> {
219 type Key = T::Key;
220
221 #[inline]
222 fn index_key(&self) -> Self::Key {
223 (**self).index_key()
224 }
225}
226
227impl Indexable for Prefix {
229 type Key = Prefix;
230
231 #[inline]
232 fn index_key(&self) -> Prefix {
233 *self
234 }
235}
236
237#[cfg(test)]
238mod tests {
239 use super::*;
240 use alloc::vec;
241 use alloc::vec::Vec;
242
243 #[test]
244 fn test_unsigned_monotonic() {
245 let vals: Vec<u64> = vec![0, 1, 100, 1000, u64::MAX];
246 for w in vals.windows(2) {
247 assert!(w[0].to_unsigned() < w[1].to_unsigned());
248 }
249 }
250
251 #[test]
252 fn test_signed_monotonic() {
253 let vals: Vec<i64> = vec![i64::MIN, -1000, -1, 0, 1, 1000, i64::MAX];
254 for w in vals.windows(2) {
255 assert!(
256 w[0].to_unsigned() < w[1].to_unsigned(),
257 "{} -> {} should be < {} -> {}",
258 w[0],
259 w[0].to_unsigned(),
260 w[1],
261 w[1].to_unsigned()
262 );
263 }
264 }
265
266 #[test]
267 fn test_numeric_indexable() {
268 assert_eq!(42u64.index_key(), 42u64);
269 assert_eq!((-10i32).index_key(), -10i32);
270 }
271
272 #[test]
273 fn test_string_indexable() {
274 let s = String::from("hello");
275 let key = s.index_key();
276 assert_eq!(key, Prefix::from_bytes(b"hello"));
277 }
278
279 #[test]
280 fn test_str_indexable() {
281 let s = "world";
282 let key = s.index_key();
283 assert_eq!(key, Prefix::from_bytes(b"world"));
284 }
285
286 #[test]
287 fn test_bytes_indexable() {
288 let bytes: Vec<u8> = vec![1, 2, 3, 4, 5];
289 let key = bytes.index_key();
290 assert_eq!(key, Prefix::from_bytes(&[1, 2, 3, 4, 5]));
291 }
292
293 #[test]
294 fn test_reference_indexable() {
295 let val = 100u64;
296 let ref_val = &val;
297 assert_eq!(ref_val.index_key(), 100u64);
298
299 let s = "test";
300 assert_eq!(s.index_key(), Prefix::from_bytes(b"test"));
301 }
302}