use std::{
collections::HashMap,
error::Error,
fmt::{self, Display, Formatter},
hash::Hash,
ops::Index,
};
#[derive(PartialEq, Eq, Debug, Clone)]
pub struct SeqMap<K, V>
where
K: Eq + Hash + Clone + Display,
{
key_to_index: HashMap<K, usize>, entries: Vec<(K, V)>, }
impl<K, V> Display for SeqMap<K, V>
where
K: Eq + Hash + Clone + Display,
V: Display,
{
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
write!(f, "SeqMap({})", self.entries.len())?;
for (key, value) in &self.entries {
write!(f, "\n{key}: {value}")?;
}
Ok(())
}
}
#[derive(Debug)]
pub enum SeqMapError {
KeyAlreadyExists,
}
impl Display for SeqMapError {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
match self {
SeqMapError::KeyAlreadyExists => write!(f, "The key already exists in the SeqMap."),
}
}
}
impl Error for SeqMapError {}
impl<K, V> SeqMap<K, V>
where
K: Eq + Hash + Clone + Display,
V: Display,
{
pub fn new() -> Self {
Self {
key_to_index: HashMap::new(),
entries: Vec::new(),
}
}
pub fn insert(&mut self, key: K, value: V) -> Result<(), SeqMapError> {
#[allow(clippy::map_entry)]
if self.key_to_index.contains_key(&key) {
Err(SeqMapError::KeyAlreadyExists)
} else {
self.entries.push((key.clone(), value));
self.key_to_index.insert(key, self.entries.len() - 1);
Ok(())
}
}
pub fn get_mut(&mut self, key: &K) -> Option<&mut V> {
self.key_to_index
.get(key)
.map(|&index| &mut self.entries[index].1)
}
pub fn len(&self) -> usize {
self.entries.len()
}
pub fn is_empty(&self) -> bool {
self.entries.is_empty()
}
pub fn keys(&self) -> impl Iterator<Item = &K> {
self.entries.iter().map(|(k, _)| k)
}
pub fn values(&self) -> impl Iterator<Item = &V> {
self.entries.iter().map(|(_, v)| v)
}
pub fn get(&self, key: &K) -> Option<&V> {
self.key_to_index
.get(key)
.map(|&index| &self.entries[index].1)
}
}
impl<K, V> Index<&K> for SeqMap<K, V>
where
K: Eq + Hash + Clone + Display,
V: Display,
{
type Output = V;
fn index(&self, key: &K) -> &Self::Output {
self.get(key).expect("Key not found in SeqMap")
}
}
impl<K, V> From<&[(K, V)]> for SeqMap<K, V>
where
K: Eq + Hash + Clone + Display,
V: Clone + Display,
{
fn from(slice: &[(K, V)]) -> Self {
let mut map = SeqMap::new();
for (key, value) in slice {
let _ = map.insert(key.clone(), value.clone());
}
map
}
}
impl<'a, K, V> IntoIterator for &'a SeqMap<K, V>
where
K: Eq + Hash + Clone + Display,
{
type Item = (&'a K, &'a V);
type IntoIter = std::iter::Map<std::slice::Iter<'a, (K, V)>, fn(&'a (K, V)) -> (&'a K, &'a V)>;
fn into_iter(self) -> Self::IntoIter {
self.entries.iter().map(|(k, v)| (k, v))
}
}
impl<K, V> Default for SeqMap<K, V>
where
K: Eq + Hash + Clone + Display,
V: Display,
{
fn default() -> Self {
Self::new()
}
}