use std::ops::Index;
pub trait OrdMapValue<K>
where
K: std::cmp::Eq + std::hash::Hash + Clone,
{
fn key(&self) -> Option<K>;
}
#[derive(Clone)]
pub struct OrdMap<K, V>
where
V: OrdMapValue<K>,
K: std::cmp::Eq + std::hash::Hash + Clone,
{
vec: Vec<V>,
map: std::collections::HashMap<K, usize>,
}
impl<K, V> Default for OrdMap<K, V>
where
V: OrdMapValue<K>,
K: std::cmp::Eq + std::hash::Hash + Clone,
{
fn default() -> Self {
Self {
vec: Default::default(),
map: Default::default(),
}
}
}
impl<K, V> std::fmt::Debug for OrdMap<K, V>
where
V: OrdMapValue<K> + std::fmt::Debug,
K: std::cmp::Eq + std::hash::Hash + Clone,
{
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("OrdMap").field("vec", &self.vec).finish()
}
}
impl<K, V> From<Vec<V>> for OrdMap<K, V>
where
V: OrdMapValue<K>,
K: std::cmp::Eq + std::hash::Hash + Clone,
{
fn from(vec: Vec<V>) -> Self {
let mut map = std::collections::HashMap::new();
for (i, item) in vec.iter().enumerate() {
if let Some(key) = item.key() {
map.insert(key, i);
}
}
Self { vec, map }
}
}
impl<K, V> OrdMap<K, V>
where
V: OrdMapValue<K>,
K: std::cmp::Eq + std::hash::Hash + Clone,
{
pub fn iter(&self) -> std::slice::Iter<'_, V> {
self.vec.iter()
}
pub fn len(&self) -> usize {
self.vec.len()
}
pub fn is_empty(&self) -> bool {
self.vec.is_empty()
}
pub fn try_push(&mut self, item: V) -> Result<(), K> {
if let Some(key) = item.key().clone() {
if self.map.contains_key(&key) {
return Err(key);
}
self.map.insert(key, self.vec.len());
}
self.vec.push(item);
Ok(())
}
pub fn get(&self, key: &K) -> Option<&V> {
self.map.get(key).map(|index| &self.vec[*index])
}
pub fn keys(&self) -> std::collections::hash_map::Keys<'_, K, usize> {
self.map.keys()
}
pub fn first(&self) -> Option<&V> {
self.vec.first()
}
}
impl<K, V> Index<usize> for OrdMap<K, V>
where
V: OrdMapValue<K>,
K: std::cmp::Eq + std::hash::Hash + Clone,
{
type Output = V;
fn index(&self, index: usize) -> &Self::Output {
&self.vec[index]
}
}
impl<K, V> Index<&K> for OrdMap<K, V>
where
V: OrdMapValue<K>,
K: std::cmp::Eq + std::hash::Hash + Clone,
{
type Output = V;
fn index(&self, key: &K) -> &Self::Output {
&self.vec[*self.map.get(key).expect("key not found")]
}
}