use std::collections::HashSet;
use std::collections::hash_set;
use std::hash::{Hash, Hasher};
use std::marker::PhantomData;
use std::borrow::Borrow;
use std::fmt;
pub trait KeyComparator<T, K> where K: Eq + Hash {
fn extract_key(value: &T) -> &K;
fn key_eq(u: &T, v: &T) -> bool {
Self::extract_key(u) == Self::extract_key(v)
}
fn key_hash<H: Hasher>(value: &T, state: &mut H) {
Self::extract_key(value).hash(state)
}
}
pub struct IndexableValue<T, K, E> {
phantom_k: PhantomData<K>,
phantom_e: PhantomData<E>,
value: T
}
impl<T, K, E> IndexableValue<T, K, E> {
fn new(value: T) -> IndexableValue<T, K, E> {
IndexableValue {
phantom_k: PhantomData,
phantom_e: PhantomData,
value: value
}
}
}
impl<T, K, E> PartialEq<IndexableValue<T, K, E>> for IndexableValue<T, K, E>
where E: KeyComparator<T, K>, K: Eq + Hash
{
fn eq(&self, other: &IndexableValue<T, K, E>) -> bool {
E::key_eq(&self.value, &other.value)
}
}
impl<T, K, E> Eq for IndexableValue<T, K, E> where E: KeyComparator<T, K>, K: Eq + Hash {}
impl<T, K, E> Hash for IndexableValue<T, K, E> where E: KeyComparator<T, K>, K: Eq + Hash {
fn hash<H: Hasher>(&self, state: &mut H) {
E::key_hash(&self.value, state)
}
}
impl<T, K, E> Borrow<K> for IndexableValue<T, K, E>
where E: KeyComparator<T, K>, K: Eq + Hash
{
fn borrow(&self) -> &K {
E::extract_key(&self.value)
}
}
pub struct HashIndexed<T, K, E> {
set: HashSet<IndexableValue<T, K, E>>
}
impl<T, K, E> HashIndexed<T, K, E>
where E: KeyComparator<T, K>, K: Eq + Hash,
IndexableValue<T, K, E>: Borrow<K>
{
pub fn new() -> HashIndexed<T, K, E> {
HashIndexed { set: HashSet::new() }
}
pub fn with_capacity(capacity: usize) -> HashIndexed<T, K, E> {
HashIndexed { set: HashSet::with_capacity(capacity) }
}
pub fn capacity(&self) -> usize {
self.set.capacity()
}
pub fn reserve(&mut self, additional: usize) {
self.set.reserve(additional)
}
pub fn shrink_to_fit(&mut self) {
self.set.shrink_to_fit()
}
pub fn iter(&self) -> Iter<T, K, E> {
Iter { iter: self.set.iter() }
}
pub fn into_iter(self) -> IntoIter<T, K, E> {
IntoIter { iter: self.set.into_iter() }
}
pub fn len(&self) -> usize { self.set.len() }
pub fn is_empty(&self) -> bool { self.set.is_empty() }
pub fn clear(&mut self) { self.set.clear() }
pub fn contains(&self, k: &K) -> bool {
self.set.contains(k)
}
pub fn get(&self, k: &K) -> Option<&T> {
self.set.get(k).map(|v| &v.value)
}
pub fn insert(&mut self, value: T) -> bool {
self.set.insert(IndexableValue::new(value))
}
pub fn replace(&mut self, value: T) -> Option<T> {
let removed = self.remove(E::extract_key(&value));
self.insert(value);
removed
}
pub fn remove(&mut self, k: &K) -> Option<T> {
self.set.take(k).map(|v| v.value)
}
}
impl<T, K, E> PartialEq for HashIndexed<T, K, E>
where HashSet<IndexableValue<T, K, E>>: PartialEq
{
fn eq(&self, other: &HashIndexed<T, K, E>) -> bool {
self.set == other.set
}
}
impl<T, K, E> Eq for HashIndexed<T, K, E>
where HashIndexed<T, K, E>: PartialEq
{}
impl<T, K, E> fmt::Debug for HashIndexed<T, K, E>
where HashSet<IndexableValue<T, K, E>>: fmt::Debug
{
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
self.set.fmt(f)
}
}
pub struct Iter<'a, T: 'a, K: 'a, E: 'a> {
iter: hash_set::Iter<'a, IndexableValue<T, K, E>>
}
pub struct IntoIter<T, K, E> {
iter: hash_set::IntoIter<IndexableValue<T, K, E>>
}
impl<'a, T, K, E> IntoIterator for &'a HashIndexed<T, K, E>
where K: Eq + Hash, E: KeyComparator<T, K>,
IndexableValue<T, K, E>: Borrow<K>
{
type Item = &'a T;
type IntoIter = Iter<'a, T, K, E>;
fn into_iter(self) -> Iter<'a, T, K, E> {
self.iter()
}
}
impl<'a, T, K, E> IntoIterator for HashIndexed<T, K, E>
where K: Eq + Hash, E: KeyComparator<T, K>
{
type Item = T;
type IntoIter = IntoIter<T, K, E>;
fn into_iter(self) -> IntoIter<T, K, E> {
self.into_iter()
}
}
impl<'a, T, K, E> Iterator for Iter<'a, T, K, E> {
type Item = &'a T;
fn next(&mut self) -> Option<&'a T> { self.iter.next().map(|x| &x.value) }
fn size_hint(&self) -> (usize, Option<usize>) { self.iter.size_hint() }
}
impl<'a, T, K, E> ExactSizeIterator for Iter<'a, T, K, E> {
fn len(&self) -> usize { self.iter.len() }
}
impl<T, K, E> Iterator for IntoIter<T, K, E> {
type Item = T;
fn next(&mut self) -> Option<T> { self.iter.next().map(|x| x.value) }
fn size_hint(&self) -> (usize, Option<usize>) { self.iter.size_hint() }
}
impl<T, K, E> ExactSizeIterator for IntoIter<T, K, E> {
fn len(&self) -> usize { self.iter.len() }
}