use core::{borrow::Borrow, hash::Hash};
use core::fmt::Debug;
use crate::RawPhfMap;
#[derive(Debug)]
pub struct PhfMap<K: 'static, V: 'static> {
raw_map: RawPhfMap<K, (K, V)>,
}
impl<K, V> PhfMap<K, V> {
#[doc(hidden)]
pub const fn new(
seed: u64,
pilots_table: &'static [u16],
entries: &'static [(K, V)],
free: &'static [u32],
) -> PhfMap<K, V> {
Self {
raw_map: RawPhfMap::new(seed, pilots_table, entries, free),
}
}
pub fn get_key_value<Q>(&self, key: &Q) -> Option<(&K, &V)>
where
K: Borrow<Q>,
Q: Hash + Eq + ?Sized,
{
if self.is_empty() {
return None;
}
let item = self.raw_map.get(key);
if item.0.borrow() == key {
Some((&item.0, &item.1))
} else {
None
}
}
pub fn get<Q>(&self, key: &Q) -> Option<&V>
where
K: Borrow<Q>,
Q: Hash + Eq + ?Sized,
{
self.get_key_value(key).map(|e| e.1)
}
pub fn get_key<Q>(&self, key: &Q) -> Option<&K>
where
K: Borrow<Q>,
Q: Hash + Eq + ?Sized,
{
self.get_key_value(key).map(|e| e.0)
}
pub fn contains_key<Q>(&self, key: &Q) -> bool
where
K: Borrow<Q>,
Q: Hash + Eq + ?Sized,
{
self.get_key_value(key).is_some()
}
pub const fn len(&self) -> usize {
self.raw_map.len()
}
pub const fn is_empty(&self) -> bool {
self.raw_map.is_empty()
}
pub fn iter(&self) -> Iter<'_, K, V> {
Iter {
iter: self.raw_map.iter(),
}
}
pub fn keys(&self) -> Keys<'_, K, V> {
Keys { iter: self.iter() }
}
pub fn values(&self) -> Values<'_, K, V> {
Values { iter: self.iter() }
}
}
impl<K, V> PartialEq for PhfMap<K, V>
where
K: Eq + Hash,
V: PartialEq,
{
fn eq(&self, other: &Self) -> bool {
if self.len() != other.len() {
return false;
}
self.iter()
.all(|(k1, v1)| other.get(k1).map_or(false, |v2| *v1 == *v2))
}
}
impl<K, V> Eq for PhfMap<K, V>
where
K: Eq + Hash,
V: Eq,
{
}
#[derive(Clone)]
pub struct Iter<'a, K: 'a, V: 'a> {
iter: crate::raw_map::Iter<'a, (K, V)>,
}
impl<'a, K, V> Iterator for Iter<'a, K, V> {
type Item = &'a (K, V);
fn next(&mut self) -> Option<Self::Item> {
self.iter.next()
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.iter.size_hint()
}
}
impl<'a, K, V> ExactSizeIterator for Iter<'a, K, V> {}
impl<'a, K, V> core::iter::FusedIterator for Iter<'a, K, V> {}
#[derive(Clone)]
pub struct Values<'a, K: 'a, V: 'a> {
iter: Iter<'a, K, V>,
}
impl<'a, K, V> Iterator for Values<'a, K, V> {
type Item = &'a V;
fn next(&mut self) -> Option<Self::Item> {
self.iter.next().map(|t| &t.1)
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.iter.size_hint()
}
}
impl<'a, K, V> ExactSizeIterator for Values<'a, K, V> {}
impl<'a, K, V> core::iter::FusedIterator for Values<'a, K, V> {}
#[derive(Clone)]
pub struct Keys<'a, K: 'a, V: 'a> {
iter: Iter<'a, K, V>,
}
impl<'a, K, V> Iterator for Keys<'a, K, V> {
type Item = &'a K;
fn next(&mut self) -> Option<Self::Item> {
self.iter.next().map(|t| &t.0)
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.iter.size_hint()
}
}
impl<'a, K, V> ExactSizeIterator for Keys<'a, K, V> {}
impl<'a, K, V> core::iter::FusedIterator for Keys<'a, K, V> {}
#[cfg(test)]
mod tests {
use crate::examples::EMPTY_MAP;
use super::*;
#[test]
fn test_empty() {
assert_eq!(EMPTY_MAP.get("Nosy"), None);
assert_eq!(EMPTY_MAP.get_key("Smithy"), None);
assert_eq!(EMPTY_MAP.get_key_value("Nighteyes"), None);
assert!(EMPTY_MAP.iter().next().is_none());
assert!(EMPTY_MAP.keys().next().is_none());
assert!(EMPTY_MAP.values().next().is_none());
}
#[test]
fn test_sync() {
fn assert_sync<T: Sync>() {}
assert_sync::<PhfMap<u64, u64>>();
}
}