use std::{
borrow::Borrow,
collections::HashMap,
error::Error,
fmt::{self, Debug, Display, Formatter},
hash::{Hash, Hasher},
ops::Index,
};
#[derive(Clone)]
pub struct SeqMap<K, V> {
key_to_index: HashMap<K, usize>, entries: Vec<(K, V)>, }
impl<K, V> Hash for SeqMap<K, V>
where
K: Hash,
V: Hash,
{
fn hash<H: Hasher>(&self, state: &mut H) {
for (key, value) in &self.entries {
key.hash(state);
value.hash(state);
}
}
}
impl<K, V> PartialEq for SeqMap<K, V>
where
K: Eq,
V: Eq,
{
fn eq(&self, other: &Self) -> bool {
if self.entries.len() != other.entries.len() {
return false;
}
self.entries
.iter()
.zip(other.entries.iter())
.all(|(a, b)| a == b)
}
}
impl<K, V> Eq for SeqMap<K, V>
where
K: Eq,
V: Eq,
{
}
impl<K, V> Display for SeqMap<K, V>
where
K: Eq + Hash + 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(())
}
}
impl<K, V> Debug for SeqMap<K, V>
where
K: Eq + Hash + Debug,
V: Debug,
{
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
write!(f, "SeqMap(")?;
let mut first = true;
for (key, value) in &self.entries {
if !first {
write!(f, ", ")?;
}
first = false;
write!(f, "{key:?}: {value:?}")?;
}
write!(f, ")")
}
}
#[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, {
#[must_use]
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 contains_key<Q>(&self, key: &Q) -> bool
where
K: Borrow<Q>,
Q: Hash + Eq + ?Sized,
{
self.key_to_index.contains_key(key)
}
pub fn get_mut(&mut self, key: &K) -> Option<&mut V> {
self.key_to_index
.get(key)
.map(|&index| &mut self.entries[index].1)
}
#[must_use]
pub fn len(&self) -> usize {
self.entries.len()
}
#[must_use]
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 values_mut(&mut self) -> impl Iterator<Item = &mut V> {
self.entries.iter_mut().map(|(_, v)| v)
}
pub fn get_index<Q>(&self, key: &Q) -> Option<usize>
where
K: Borrow<Q>,
Q: Hash + Eq + ?Sized,
{
self.key_to_index.get(key).copied()
}
pub fn iter(&self) -> impl Iterator<Item = (&K, &V)> {
self.entries.iter().map(|(k, v)| (k, v))
}
pub fn iter_mut(&mut self) -> impl Iterator<Item = (&K, &mut V)> {
self.entries.iter_mut().map(|(k, v)| (&*k, v))
}
pub fn get<Q>(&self, key: &Q) -> Option<&V>
where
K: Borrow<Q>,
Q: Hash + Eq + ?Sized,
{
self.key_to_index
.get(key)
.map(|&index| &self.entries[index].1)
}
pub fn clear(&mut self) {
self.key_to_index.clear();
self.entries.clear();
}
pub fn remove(&mut self, key: &K) -> Option<V> {
if let Some(&index) = self.key_to_index.get(key) {
self.key_to_index.remove(key);
for k in self.entries[index + 1..].iter().map(|(k, _)| k) {
if let Some(idx) = self.key_to_index.get_mut(k) {
*idx -= 1;
}
}
Some(self.entries.remove(index).1)
} else {
None
}
}
pub fn drain(&mut self) -> impl Iterator<Item = (K, V)> + '_ {
self.key_to_index.clear();
self.entries.drain(..)
}
}
pub enum Entry<'a, K, V>
where
K: Eq + Hash + Clone,
{
Occupied(OccupiedEntry<'a, K, V>),
Vacant(VacantEntry<'a, K, V>),
}
pub struct OccupiedEntry<'a, K, V>
where
K: Eq + Hash + Clone,
{
map: &'a mut SeqMap<K, V>,
index: usize,
}
pub struct VacantEntry<'a, K, V>
where
K: Eq + Hash + Clone,
{
map: &'a mut SeqMap<K, V>,
key: Option<K>,
}
impl<'a, K, V> Entry<'a, K, V>
where
K: Eq + Hash + Clone,
{
pub fn or_insert(&mut self, default: V) -> &mut V {
match self {
Entry::Occupied(o) => o.get_mut(),
Entry::Vacant(v) => v.insert(default),
}
}
pub fn or_insert_with<F: FnOnce() -> V>(&mut self, f: F) -> &mut V {
match self {
Entry::Occupied(o) => o.get_mut(),
Entry::Vacant(v) => v.insert(f()),
}
}
pub fn or_default(&mut self) -> &mut V
where
V: Default,
{
match self {
Entry::Occupied(o) => o.get_mut(),
Entry::Vacant(v) => v.insert(V::default()),
}
}
pub fn and_modify<F: FnOnce(&mut V)>(&mut self, f: F) -> &mut Self {
match self {
Entry::Occupied(o) => {
f(o.get_mut());
}
Entry::Vacant(_) => {}
}
self
}
}
impl<'a, K, V> OccupiedEntry<'a, K, V>
where
K: Eq + Hash + Clone,
{
pub fn get(&self) -> &V {
&self.map.entries[self.index].1
}
pub fn get_mut(&mut self) -> &mut V {
&mut self.map.entries[self.index].1
}
pub fn insert(&mut self, value: V) -> V {
std::mem::replace(&mut self.map.entries[self.index].1, value)
}
pub fn remove(&mut self) -> V {
let key = self.map.entries[self.index].0.clone();
self.map.key_to_index.remove(&key);
for k in self.map.entries[self.index + 1..].iter().map(|(k, _)| k) {
if let Some(idx) = self.map.key_to_index.get_mut(k) {
*idx -= 1;
}
}
self.map.entries.remove(self.index).1
}
}
impl<'a, K, V> VacantEntry<'a, K, V>
where
K: Eq + Hash + Clone,
{
pub fn insert(&mut self, value: V) -> &mut V {
let key = self.key.take().expect("vacant entry key missing");
let index = self.map.entries.len();
self.map.entries.push((key.clone(), value));
self.map.key_to_index.insert(key, index);
&mut self.map.entries[index].1
}
pub fn key(&self) -> &K {
self.key.as_ref().expect("vacant entry key missing")
}
}
impl<K, V> Index<&K> for SeqMap<K, V>
where
K: Eq + Hash + Clone,
V: Clone,
{
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,
V: Clone,
{
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<K: Hash, V> FromIterator<(K, V)> for SeqMap<K, V>
where
K: Eq + Clone,
V: Clone,
{
fn from_iter<T: IntoIterator<Item = (K, V)>>(iter: T) -> Self {
let mut map = SeqMap::new();
for (k, v) in iter {
let _ = map.insert(k, v); }
map
}
}
impl<'a, K, V> IntoIterator for &'a SeqMap<K, V>
where
K: Eq + Hash + Clone,
{
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> {
fn default() -> Self {
Self {
key_to_index: HashMap::default(),
entries: Vec::default(),
}
}
}
impl<'a, K, V> IntoIterator for &'a mut SeqMap<K, V>
where
K: Eq + Hash + Clone,
{
type Item = (&'a K, &'a mut V);
type IntoIter =
std::iter::Map<std::slice::IterMut<'a, (K, V)>, fn(&'a mut (K, V)) -> (&'a K, &'a mut V)>;
fn into_iter(self) -> Self::IntoIter {
self.entries.iter_mut().map(|(k, v)| (&*k, v))
}
}
impl<K, V> IntoIterator for SeqMap<K, V>
where
K: Eq + Hash + Clone,
{
type Item = (K, V);
type IntoIter = std::vec::IntoIter<(K, V)>;
fn into_iter(self) -> Self::IntoIter {
self.entries.into_iter()
}
}
impl<K, V> SeqMap<K, V>
where
K: Eq + Hash + Clone,
{
pub fn entry(&mut self, key: K) -> Entry<'_, K, V> {
if let Some(&index) = self.key_to_index.get(&key) {
Entry::Occupied(OccupiedEntry { map: self, index })
} else {
Entry::Vacant(VacantEntry {
map: self,
key: Some(key),
})
}
}
pub fn into_keys(self) -> impl Iterator<Item = K> {
self.entries.into_iter().map(|(k, _)| k)
}
pub fn into_values(self) -> impl Iterator<Item = V> {
self.entries.into_iter().map(|(_, v)| v)
}
}
impl<K, V> Extend<(K, V)> for SeqMap<K, V>
where
K: Eq + Hash + Clone,
{
fn extend<T: IntoIterator<Item = (K, V)>>(&mut self, iter: T) {
for (k, v) in iter {
let _ = self.insert(k, v);
}
}
}
#[cfg(test)]
mod tests {
use crate::SeqMap;
#[test]
fn test_clear_and_drain() {
let mut map = SeqMap::new();
map.insert("a", 1).unwrap();
map.insert("b", 2).unwrap();
let mut other_map = SeqMap::new();
for (k, v) in map.drain() {
other_map.insert(k, v).unwrap();
}
assert!(map.is_empty());
assert_eq!(other_map.len(), 2);
other_map.clear();
assert!(other_map.is_empty());
assert_eq!(other_map.key_to_index.len(), 0);
assert_eq!(other_map.entries.len(), 0);
}
}