use std::borrow::Borrow;
use std::collections::HashSet;
use std::hash::{Hash, Hasher};
use std::rc::Rc;
use std::sync::Arc;
pub trait Index {
type Key: ?Sized + Hash + PartialEq + Eq;
fn index(&self) -> &Self::Key;
}
impl<T: Index> Index for Rc<T> {
type Key = T::Key;
fn index(&self) -> &Self::Key {
(**self).index()
}
}
impl<T: Index> Index for Arc<T> {
type Key = T::Key;
fn index(&self) -> &Self::Key {
(**self).index()
}
}
#[derive(Clone, Debug)]
struct Item<V>(V);
impl<V: Index> Hash for Item<V> {
fn hash<H: Hasher>(&self, state: &mut H) {
self.0.index().hash(state);
}
}
impl<V: Index> PartialEq for Item<V> {
fn eq(&self, other: &Self) -> bool {
self.0.index().eq(other.0.index())
}
}
impl<V: Index> Eq for Item<V> {}
impl<V: Index<Key = str>> Borrow<str> for Item<V> {
fn borrow(&self) -> &V::Key {
self.0.index()
}
}
impl<V: Index<Key = usize>> Borrow<usize> for Item<V> {
fn borrow(&self) -> &V::Key {
self.0.index()
}
}
#[derive(Default, Clone, Debug)]
pub struct IndexMap<V>(HashSet<Item<V>>);
impl<V> IndexMap<V> {
pub fn new() -> IndexMap<V> {
IndexMap(HashSet::new())
}
pub fn len(&self) -> usize {
self.0.len()
}
pub fn is_empty(&self) -> bool {
self.0.is_empty()
}
pub fn with_capacity(capacity: usize) -> IndexMap<V> {
Self(HashSet::with_capacity(capacity))
}
pub fn iter(&self) -> impl Iterator<Item = &V> {
self.0.iter().map(|v| &v.0)
}
}
impl<V: Index> IndexMap<V> {
pub fn insert(&mut self, value: V) {
self.0.insert(Item(value));
}
#[allow(private_bounds)] pub fn get(&self, key: &V::Key) -> Option<&V>
where
Item<V>: Borrow<V::Key>,
{
self.0.get(key).map(|v| &v.0)
}
}
impl<'a, V: Index> std::ops::Index<&'a V::Key> for IndexMap<V>
where
Item<V>: Borrow<V::Key>,
{
type Output = V;
fn index(&self, index: &'a V::Key) -> &Self::Output {
self.get(index).unwrap()
}
}