1extern crate fxhash;
2use std::hash::Hash;
3use std::borrow::Borrow;
4
5#[derive(Debug, Copy, Clone)]
6pub struct Map<'a, K: 'a, V: 'a> {
7 #[doc(hidden)]
8 pub hashes: &'a [usize],
9
10 #[doc(hidden)]
11 pub entries: &'a [(K, V)],
12}
13
14impl<'a, K, V> Map<'a, K, V>
15 where K: Hash + Eq
16{
17 #[inline]
18 pub fn len(&self) -> usize {
19 self.entries.len()
20 }
21
22 #[inline]
23 pub fn is_empty(&self) -> bool {
24 self.entries.len() == 0
25 }
26
27 #[inline]
28 pub fn get<Q: ?Sized>(&self, key: &Q) -> Option<&'a V>
29 where K: Borrow<Q>,
30 Q: Hash + Eq
31 {
32 self.get_entry(key).map(|(_, v)| v)
33 }
34
35 #[inline]
36 pub fn get_entry<Q: ?Sized>(&self, key: &Q) -> Option<(&'a K, &'a V)>
37 where K: Borrow<Q>,
38 Q: Hash + Eq
39 {
40 assert!(self.entries.len().is_power_of_two(),
41 "Invalid StaticMap. The pool must be a power of two.");
42 assert!(self.entries.len() >= 16,
43 "Invalid StaticMap. The pool must have size >= 16.");
44
45 let mask = self.len() - 1;
48 let hash = Self::hash(key);
49
50 let mut pos = hash & mask;
51 let mut dist = 0;
52
53 loop {
54 let entry_hash = self.hashes[pos];
55
56 if entry_hash == hash {
58 let entry = &self.entries[pos];
59 if key.eq(entry.0.borrow()) {
60 return Some((&entry.0, &entry.1));
61 }
62 }
63
64 if entry_hash == 0 {
66 return None;
67 }
68
69 let entry_dist = pos.wrapping_sub(entry_hash) & mask;
78 if dist > entry_dist {
79 return None;
80 }
81
82 pos = pos.wrapping_add(1) & mask;
83 dist += 1;
84 }
85 }
86
87 #[inline]
88 pub fn entries(&self) -> Entries<'a, K, V> {
89 Entries {
90 cursor: 0,
91 hashes: self.hashes,
92 entries: self.entries,
93 }
94 }
95
96 #[inline]
97 pub fn keys(&self) -> Keys<'a, K, V> {
98 Keys { entries: self.entries() }
99 }
100
101 #[inline]
102 pub fn values(&self) -> Values<'a, K, V> {
103 Values { entries: self.entries() }
104 }
105
106 #[inline]
107 pub fn contains_key<Q: ?Sized>(&self, key: &Q) -> bool
108 where K: Borrow<Q>,
109 Q: Hash + Eq
110 {
111 self.get_entry(key).is_some()
112 }
113
114 #[inline]
115 fn hash<Q: ?Sized>(key: &Q) -> usize
116 where K: Borrow<Q>,
117 Q: Hash + Eq
118 {
119 fxhash::hash(key) as usize | 1
120 }
121}
122
123pub struct Entries<'a, K: 'a, V: 'a> {
124 cursor: usize,
125 hashes: &'a [usize],
126 entries: &'a [(K, V)],
127}
128
129impl<'a, K: 'a, V: 'a> Iterator for Entries<'a, K, V> {
130 type Item = &'a (K, V);
131 fn next(&mut self) -> Option<Self::Item> {
132 while self.cursor < self.hashes.len() {
133 if self.hashes[self.cursor] != 0 {
134 let result = Some(&self.entries[self.cursor]);
135 self.cursor += 1;
136 return result;
137 }
138 self.cursor += 1
139 }
140
141 None
142 }
143}
144
145pub struct Keys<'a, K: 'a, V: 'a> {
146 entries: Entries<'a, K, V>,
147}
148
149impl<'a, K: 'a, V: 'a> Iterator for Keys<'a, K, V> {
150 type Item = &'a K;
151 fn next(&mut self) -> Option<Self::Item> {
152 self.entries.next().map(|entry| &entry.0)
153 }
154}
155
156pub struct Values<'a, K: 'a, V: 'a> {
157 entries: Entries<'a, K, V>,
158}
159
160impl<'a, K: 'a, V: 'a> Iterator for Values<'a, K, V> {
161 type Item = &'a V;
162 fn next(&mut self) -> Option<Self::Item> {
163 self.entries.next().map(|entry| &entry.1)
164 }
165}
166
167impl<'a, K: 'a, V: 'a> IntoIterator for Map<'a, K, V>
168 where K: Hash + Eq
169{
170 type Item = &'a (K, V);
171 type IntoIter = Entries<'a, K, V>;
172 fn into_iter(self) -> Entries<'a, K, V> {
173 self.entries()
174 }
175}
176
177#[macro_export]
178macro_rules! static_map {
179 (Default: $default:expr, $($key:expr => $value:expr),* $(,)*) => (
180 static_map!(@stringify $default $(@ $key ? $value )*)
181 );
182
183 (@stringify $($tt:tt)*) => ({
186 #[derive(StaticMapMacro)]
187 enum __StaticMap__ {
188 A = static_map!(@zero $($tt)*)
189 }
190
191 __static_map__construct_map!()
192 });
193
194 (@zero $($tt:tt)*) => { 0 }
195}