blob: 254ee39b32a7eeb6943c9052350a26019744d8f9 [file] [log] [blame]
//! A map-like object for maps with few entries.
//! TODO: this may not be needed at all, but the code used this pattern in a
//! few places so I figured I may as well name it.
use std::{borrow::Borrow, fmt::Debug};
/// A map-like object implemented as a list of pairs, for cases where the
/// number of entries in the map is small.
pub struct SmallMap<K, V>(Vec<(K, V)>);
impl<K, V> SmallMap<K, V> {
pub fn with_capacity(cap: usize) -> Self {
Self(Vec::with_capacity(cap))
}
pub fn len(&self) -> usize {
self.0.len()
}
}
impl<K, V> Default for SmallMap<K, V> {
fn default() -> Self {
SmallMap(Vec::default())
}
}
impl<K: PartialEq, V> SmallMap<K, V> {
pub fn insert(&mut self, k: K, v: V) {
for (ik, iv) in self.0.iter_mut() {
if *ik == k {
*iv = v;
return;
}
}
self.0.push((k, v));
}
// returns true if value was inserted, false if the key was already present.
pub fn insert_if_absent(&mut self, k: K, v: V) -> bool {
for (ik, _) in self.0.iter_mut() {
if *ik == k {
return false;
}
}
self.0.push((k, v));
true
}
pub fn get<Q>(&self, q: &Q) -> Option<&V>
where
K: Borrow<Q>,
Q: PartialEq + ?Sized,
{
for (k, v) in self.0.iter() {
if k.borrow() == q {
return Some(v);
}
}
None
}
pub fn iter(&self) -> std::slice::Iter<(K, V)> {
self.0.iter()
}
pub fn iter_mut(&mut self) -> std::slice::IterMut<(K, V)> {
self.0.iter_mut()
}
pub fn into_iter(self) -> std::vec::IntoIter<(K, V)> {
self.0.into_iter()
}
pub fn values(&self) -> impl Iterator<Item = &V> + '_ {
self.0.iter().map(|x| &x.1)
}
pub fn values_mut(&mut self) -> impl Iterator<Item = &mut V> + '_ {
self.0.iter_mut().map(|x| &mut x.1)
}
}
impl<K: PartialEq, V, const N: usize> std::convert::From<[(K, V); N]> for SmallMap<K, V> {
fn from(value: [(K, V); N]) -> Self {
let mut result = SmallMap::default();
for (k, v) in value {
result.insert(k, v);
}
result
}
}
impl<K: Debug, V: Debug> Debug for SmallMap<K, V> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
self.0.fmt(f)
}
}
// Only for tests because it is order-sensitive
#[cfg(test)]
impl<K: PartialEq, V: PartialEq> PartialEq for SmallMap<K, V> {
fn eq(&self, other: &Self) -> bool {
return self.0 == other.0;
}
}