associative_cache/
indices.rs1use super::{Capacity, Indices};
4use std::collections::hash_map::DefaultHasher;
5use std::hash::{Hash, Hasher};
6use std::marker::PhantomData;
7use std::ops::Range;
8
9#[inline]
10fn hash_to_usize<H>(mut hasher: impl Hasher, h: &H) -> usize
11where
12 H: ?Sized + Hash,
13{
14 h.hash(&mut hasher);
15 hasher.finish() as usize
16}
17
18macro_rules! define_hash_n_way {
19 ( $( $( #[$attr:meta] )* $name:ident => $n:expr; )* ) => { $(
20 $( #[ $attr ] )*
21 #[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
22 pub struct $name<H = DefaultHasher> {
23 _hasher: PhantomData<H>,
24 }
25
26 impl<T, C, H> Indices<T, C> for $name<H>
27 where
28 T: ?Sized + Hash,
29 C: Capacity,
30 H: Hasher + Default,
31 {
32 type Indices = Range<usize>;
33
34 #[inline]
35 fn indices(key: &T) -> Self::Indices {
36 assert!(C::CAPACITY >= $n);
37 let hasher = H::default();
38 let base = hash_to_usize(hasher, key) % (C::CAPACITY / $n) * $n;
39 base..base + $n
40 }
41 }
42 )* }
43}
44
45define_hash_n_way! {
46 HashDirectMapped => 1;
51 HashTwoWay => 2;
56 HashFourWay => 4;
61 HashEightWay => 8;
66 HashSixteenWay => 16;
71 HashThirtyTwoWay => 32;
75}
76
77macro_rules! define_pointer_n_way {
78 ( $( $( #[$attr:meta] )* $name: ident => $n:expr; )* ) => {
79 $(
80 $( #[$attr] )*
81 #[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
82 pub struct $name;
83
84 impl<T, C> Indices<*mut T, C> for $name
85 where
86 C: Capacity
87 {
88 type Indices = Range<usize>;
89
90 #[inline]
91 fn indices(&ptr: &*mut T) -> Self::Indices {
92 assert!(C::CAPACITY >= $n);
93
94 let ptr = ptr as usize;
95
96 let i = ptr / std::mem::align_of::<T>();
101
102 let base = i % (C::CAPACITY / $n) * $n;
103 base..(base + $n)
104 }
105 }
106
107 impl<T, C> Indices<*const T, C> for $name
108 where
109 C: Capacity
110 {
111 type Indices = <Self as Indices<*mut T, C>>::Indices;
112
113 #[inline]
114 fn indices(&ptr: &*const T) -> Self::Indices {
115 <Self as Indices<*mut T, C>>::indices(&(ptr as *mut T))
116 }
117 }
118 )*
119 };
120}
121
122define_pointer_n_way! {
123 PointerDirectMapped => 1;
128 PointerTwoWay => 2;
132 PointerFourWay => 4;
136 PointerEightWay => 8;
140 PointerSixteenWay => 16;
144 PointerThirtyTwoWay => 32;
148}
149
150#[cfg(test)]
151mod tests {
152 use super::*;
153 use crate::Capacity4;
154
155 #[test]
156 fn pointer_direct_mapped() {
157 assert_eq!(
158 <PointerDirectMapped as Indices<*mut u64, Capacity4>>::indices(&(0 as *mut u64)),
159 0..1
160 );
161 assert_eq!(
162 <PointerDirectMapped as Indices<*mut u64, Capacity4>>::indices(&(8 as *mut u64)),
163 1..2
164 );
165 assert_eq!(
166 <PointerDirectMapped as Indices<*mut u64, Capacity4>>::indices(&(16 as *mut u64)),
167 2..3
168 );
169 assert_eq!(
170 <PointerDirectMapped as Indices<*mut u64, Capacity4>>::indices(&(24 as *mut u64)),
171 3..4
172 );
173 assert_eq!(
174 <PointerDirectMapped as Indices<*mut u64, Capacity4>>::indices(&(32 as *mut u64)),
175 0..1
176 );
177 }
178
179 #[test]
180 fn pointer_two_way() {
181 assert_eq!(
182 <PointerTwoWay as Indices<*mut u64, Capacity4>>::indices(&(0 as *mut u64)),
183 0..2
184 );
185 assert_eq!(
186 <PointerTwoWay as Indices<*mut u64, Capacity4>>::indices(&(8 as *mut u64)),
187 2..4
188 );
189 assert_eq!(
190 <PointerTwoWay as Indices<*mut u64, Capacity4>>::indices(&(16 as *mut u64)),
191 0..2
192 );
193 assert_eq!(
194 <PointerTwoWay as Indices<*mut u64, Capacity4>>::indices(&(24 as *mut u64)),
195 2..4
196 );
197 assert_eq!(
198 <PointerTwoWay as Indices<*mut u64, Capacity4>>::indices(&(32 as *mut u64)),
199 0..2
200 );
201 }
202}