extern crate fxhash;
use std::hash::Hash;
use std::borrow::Borrow;
#[derive(Debug, Copy, Clone)]
pub struct Map<'a, K: 'a, V: 'a> {
#[doc(hidden)]
pub hashes: &'a [u32],
#[doc(hidden)]
pub entries: &'a [(K, V)],
}
impl<'a, K, V> Map<'a, K, V>
where K: Hash + Eq
{
#[inline]
pub fn len(&self) -> usize {
self.entries.len()
}
#[inline]
pub fn is_empty(&self) -> bool {
self.entries.len() == 0
}
#[inline]
pub fn get<Q: ?Sized>(&self, key: &Q) -> Option<&'a V>
where K: Borrow<Q>,
Q: Hash + Eq
{
self.get_entry(key).map(|(_, v)| v)
}
#[inline]
pub fn get_entry<Q: ?Sized>(&self, key: &Q) -> Option<(&'a K, &'a V)>
where K: Borrow<Q>,
Q: Hash + Eq
{
assert!(self.entries.len().is_power_of_two(),
"Invalid StaticMap. The pool must be a power of two.");
assert!(self.entries.len() >= 16,
"Invalid StaticMap. The pool must have size >= 16.");
let mask = self.len() - 1;
let hash = Self::hash(key);
let mut pos = hash as usize & mask;
let mut dist = 0;
loop {
let entry_hash = self.hashes[pos];
if entry_hash == hash {
let entry = &self.entries[pos];
if key.eq(entry.0.borrow()) {
return Some((&entry.0, &entry.1));
}
}
if entry_hash == 0 {
return None;
}
let entry_dist = pos.wrapping_sub(entry_hash as usize) & mask;
if dist > entry_dist {
return None;
}
pos = pos.wrapping_add(1) & mask;
dist += 1;
}
}
#[inline]
pub fn entries(&self) -> Entries<'a, K, V> {
Entries {
cursor: 0,
hashes: self.hashes,
entries: self.entries,
}
}
#[inline]
pub fn keys(&self) -> Keys<'a, K, V> {
Keys { entries: self.entries() }
}
#[inline]
pub fn values(&self) -> Values<'a, K, V> {
Values { entries: self.entries() }
}
#[inline]
pub fn contains_key<Q: ?Sized>(&self, key: &Q) -> bool
where K: Borrow<Q>,
Q: Hash + Eq
{
self.get_entry(key).is_some()
}
#[inline]
fn hash<Q: ?Sized>(key: &Q) -> u32
where K: Borrow<Q>,
Q: Hash + Eq
{
fxhash::hash64(key) as u32 | 1
}
}
pub struct Entries<'a, K: 'a, V: 'a> {
cursor: usize,
hashes: &'a [u32],
entries: &'a [(K, V)],
}
impl<'a, K: 'a, V: 'a> Iterator for Entries<'a, K, V> {
type Item = &'a (K, V);
fn next(&mut self) -> Option<Self::Item> {
while self.cursor < self.hashes.len() {
if self.hashes[self.cursor] != 0 {
let result = Some(&self.entries[self.cursor]);
self.cursor += 1;
return result;
}
self.cursor += 1
}
None
}
}
pub struct Keys<'a, K: 'a, V: 'a> {
entries: Entries<'a, K, V>,
}
impl<'a, K: 'a, V: 'a> Iterator for Keys<'a, K, V> {
type Item = &'a K;
fn next(&mut self) -> Option<Self::Item> {
self.entries.next().map(|entry| &entry.0)
}
}
pub struct Values<'a, K: 'a, V: 'a> {
entries: Entries<'a, K, V>,
}
impl<'a, K: 'a, V: 'a> Iterator for Values<'a, K, V> {
type Item = &'a V;
fn next(&mut self) -> Option<Self::Item> {
self.entries.next().map(|entry| &entry.1)
}
}
impl<'a, K: 'a, V: 'a> IntoIterator for Map<'a, K, V>
where K: Hash + Eq
{
type Item = &'a (K, V);
type IntoIter = Entries<'a, K, V>;
fn into_iter(self) -> Entries<'a, K, V> {
self.entries()
}
}
#[macro_export]
macro_rules! static_map {
(Default: $default:expr, $($key:expr => $value:expr),* $(,)*) => (
static_map!(@stringify $default $(@ $key ? $value )*)
);
(@stringify $($tt:tt)*) => ({
#[derive(StaticMapMacro)]
enum __StaticMap__ {
A = static_map!(@zero $($tt)*)
}
__static_map__construct_map!()
});
(@zero $($tt:tt)*) => { 0 }
}