mod entry;
#[cfg(feature = "rkyv")]
mod rkyv_impl;
#[cfg(feature = "serde")]
mod serde;
pub use entry::{Entry, OccupiedEntry, VacantEntry};
use core::borrow::Borrow;
use core::fmt;
use core::ops::Index;
use crate::EcoVec;
use crate::allocator::Global;
#[derive(Clone)]
pub struct EcoMap<K: Clone, V: Clone> {
pub(crate) keys: EcoVec<K>,
pub(crate) vals: EcoVec<V>,
}
impl<K: Clone, V: Clone> EcoMap<K, V> {
#[inline]
pub fn new() -> Self {
Self { keys: EcoVec::new(), vals: EcoVec::new() }
}
#[inline]
pub fn with_capacity(capacity: usize) -> Self {
Self {
keys: EcoVec::with_capacity(capacity),
vals: EcoVec::with_capacity(capacity),
}
}
#[inline]
pub fn len(&self) -> usize {
self.keys.len()
}
#[inline]
pub fn is_empty(&self) -> bool {
self.keys.is_empty()
}
#[inline]
pub fn clear(&mut self) {
self.keys.clear();
self.vals.clear();
}
#[inline]
pub fn capacity(&self) -> usize {
self.keys.capacity().min(self.vals.capacity())
}
#[inline]
pub fn reserve(&mut self, additional: usize) {
self.keys.reserve(additional);
self.vals.reserve(additional);
}
#[inline]
pub fn shrink_to_fit(&mut self) {
self.keys.shrink_to_fit();
self.vals.shrink_to_fit();
}
}
impl<K: Clone + PartialEq, V: Clone> EcoMap<K, V> {
#[inline]
pub fn get<Q>(&self, key: &Q) -> Option<&V>
where
K: Borrow<Q>,
Q: PartialEq + ?Sized,
{
self.index_of(key).map(|i| &self.vals[i])
}
#[inline]
pub fn get_key_value<Q>(&self, key: &Q) -> Option<(&K, &V)>
where
K: Borrow<Q>,
Q: PartialEq + ?Sized,
{
self.index_of(key).map(|i| (&self.keys[i], &self.vals[i]))
}
#[inline]
pub fn get_mut<Q>(&mut self, key: &Q) -> Option<&mut V>
where
K: Borrow<Q>,
Q: PartialEq + ?Sized,
{
self.index_of(key).map(|i| &mut self.vals.make_mut()[i])
}
#[inline]
pub fn contains_key<Q>(&self, key: &Q) -> bool
where
K: Borrow<Q>,
Q: PartialEq + ?Sized,
{
self.index_of(key).is_some()
}
pub fn insert(&mut self, key: K, val: V) -> Option<V> {
if let Some(i) = self.index_of(&key) {
let vals = self.vals.make_mut();
Some(core::mem::replace(&mut vals[i], val))
} else {
self.push_unchecked(key, val);
None
}
}
#[inline]
fn push_unchecked(&mut self, key: K, val: V) {
self.keys.push(key);
self.vals.push(val);
}
#[inline]
pub fn insert_unique(&mut self, key: K, val: V) {
debug_assert!(
!self.contains_key(&key),
"insert_unique called with a key already present in the map"
);
self.push_unchecked(key, val);
}
pub fn extend_unique<I: IntoIterator<Item = (K, V)>>(&mut self, iter: I) {
let iter = iter.into_iter();
let (hint, _) = iter.size_hint();
self.reserve(hint);
for (k, v) in iter {
self.push_unchecked(k, v);
}
}
pub fn remove<Q>(&mut self, key: &Q) -> Option<V>
where
K: Borrow<Q>,
Q: PartialEq + ?Sized,
{
let i = self.index_of(key)?;
let last = self.len() - 1;
let keys = self.keys.make_mut();
let vals = self.vals.make_mut();
keys.swap(i, last);
vals.swap(i, last);
self.keys.pop();
Some(self.vals.pop().unwrap())
}
pub fn retain<F>(&mut self, mut f: F)
where
F: FnMut(&K, &mut V) -> bool,
{
let keys = self.keys.make_mut();
let vals = self.vals.make_mut();
let mut i = 0;
let mut len = keys.len();
while i < len {
if f(&keys[i], &mut vals[i]) {
i += 1;
} else {
len -= 1;
keys.swap(i, len);
vals.swap(i, len);
}
}
self.keys.truncate(len);
self.vals.truncate(len);
}
#[inline]
pub fn entry(&mut self, key: K) -> Entry<'_, K, V> {
match self.index_of(&key) {
Some(i) => Entry::Occupied(OccupiedEntry::new(self, i)),
None => Entry::Vacant(VacantEntry::new(self, key)),
}
}
#[inline]
fn index_of<Q>(&self, key: &Q) -> Option<usize>
where
K: Borrow<Q>,
Q: PartialEq + ?Sized,
{
self.keys.iter().position(|k| k.borrow() == key)
}
}
impl<K: Clone, V: Clone> EcoMap<K, V> {
#[inline]
pub fn iter(&self) -> Iter<'_, K, V> {
Iter { keys: self.keys.iter(), vals: self.vals.iter() }
}
#[inline]
pub fn iter_mut(&mut self) -> IterMut<'_, K, V> {
let vals = self.vals.make_mut().iter_mut();
let keys = self.keys.iter();
IterMut { keys, vals }
}
#[inline]
pub fn keys(&self) -> Keys<'_, K> {
Keys(self.keys.iter())
}
#[inline]
pub fn values(&self) -> Values<'_, V> {
Values(self.vals.iter())
}
#[inline]
pub fn values_mut(&mut self) -> ValuesMut<'_, V> {
ValuesMut(self.vals.make_mut().iter_mut())
}
}
pub struct Iter<'a, K, V> {
keys: core::slice::Iter<'a, K>,
vals: core::slice::Iter<'a, V>,
}
impl<'a, K, V> Iterator for Iter<'a, K, V> {
type Item = (&'a K, &'a V);
#[inline]
fn next(&mut self) -> Option<Self::Item> {
Some((self.keys.next()?, self.vals.next()?))
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
self.keys.size_hint()
}
}
impl<K, V> ExactSizeIterator for Iter<'_, K, V> {}
impl<K, V> DoubleEndedIterator for Iter<'_, K, V> {
#[inline]
fn next_back(&mut self) -> Option<Self::Item> {
Some((self.keys.next_back()?, self.vals.next_back()?))
}
}
impl<K: fmt::Debug, V: fmt::Debug> fmt::Debug for Iter<'_, K, V> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_list()
.entries(self.keys.as_slice().iter().zip(self.vals.as_slice()))
.finish()
}
}
impl<K, V> Clone for Iter<'_, K, V> {
#[inline]
fn clone(&self) -> Self {
Iter { keys: self.keys.clone(), vals: self.vals.clone() }
}
}
pub struct IterMut<'a, K, V> {
keys: core::slice::Iter<'a, K>,
vals: core::slice::IterMut<'a, V>,
}
impl<'a, K, V> Iterator for IterMut<'a, K, V> {
type Item = (&'a K, &'a mut V);
#[inline]
fn next(&mut self) -> Option<Self::Item> {
Some((self.keys.next()?, self.vals.next()?))
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
self.keys.size_hint()
}
}
impl<K, V> ExactSizeIterator for IterMut<'_, K, V> {}
impl<K, V> DoubleEndedIterator for IterMut<'_, K, V> {
#[inline]
fn next_back(&mut self) -> Option<Self::Item> {
Some((self.keys.next_back()?, self.vals.next_back()?))
}
}
pub struct IntoIter<K: Clone, V: Clone> {
keys: crate::vec::IntoIter<K, Global>,
vals: crate::vec::IntoIter<V, Global>,
}
impl<K: Clone, V: Clone> Iterator for IntoIter<K, V> {
type Item = (K, V);
#[inline]
fn next(&mut self) -> Option<Self::Item> {
Some((self.keys.next()?, self.vals.next()?))
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
self.keys.size_hint()
}
}
impl<K: Clone, V: Clone> ExactSizeIterator for IntoIter<K, V> {}
impl<K: Clone, V: Clone> DoubleEndedIterator for IntoIter<K, V> {
#[inline]
fn next_back(&mut self) -> Option<Self::Item> {
Some((self.keys.next_back()?, self.vals.next_back()?))
}
}
impl<K: Clone + fmt::Debug, V: Clone + fmt::Debug> fmt::Debug for IntoIter<K, V> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_list()
.entries(self.keys.as_slice().iter().zip(self.vals.as_slice()))
.finish()
}
}
pub struct Keys<'a, K>(core::slice::Iter<'a, K>);
impl<'a, K> Iterator for Keys<'a, K> {
type Item = &'a K;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
self.0.next()
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
self.0.size_hint()
}
}
impl<K> ExactSizeIterator for Keys<'_, K> {}
impl<K> DoubleEndedIterator for Keys<'_, K> {
#[inline]
fn next_back(&mut self) -> Option<Self::Item> {
self.0.next_back()
}
}
pub struct Values<'a, V>(core::slice::Iter<'a, V>);
impl<'a, V> Iterator for Values<'a, V> {
type Item = &'a V;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
self.0.next()
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
self.0.size_hint()
}
}
impl<V> ExactSizeIterator for Values<'_, V> {}
impl<V> DoubleEndedIterator for Values<'_, V> {
#[inline]
fn next_back(&mut self) -> Option<Self::Item> {
self.0.next_back()
}
}
pub struct ValuesMut<'a, V>(core::slice::IterMut<'a, V>);
impl<'a, V> Iterator for ValuesMut<'a, V> {
type Item = &'a mut V;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
self.0.next()
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
self.0.size_hint()
}
}
impl<V> ExactSizeIterator for ValuesMut<'_, V> {}
impl<V> DoubleEndedIterator for ValuesMut<'_, V> {
#[inline]
fn next_back(&mut self) -> Option<Self::Item> {
self.0.next_back()
}
}
impl<K: Clone, V: Clone> Default for EcoMap<K, V> {
#[inline]
fn default() -> Self {
Self::new()
}
}
impl<K: Clone + fmt::Debug, V: Clone + fmt::Debug> fmt::Debug for EcoMap<K, V> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_map().entries(self.iter()).finish()
}
}
impl<K: Clone + PartialEq, V: Clone + PartialEq> PartialEq for EcoMap<K, V> {
fn eq(&self, other: &Self) -> bool {
if self.len() != other.len() {
return false;
}
if self.keys == other.keys && self.vals == other.vals {
return true;
}
self.iter().all(|(k, v)| other.get(k) == Some(v))
}
}
impl<K: Clone + Eq, V: Clone + Eq> Eq for EcoMap<K, V> {}
impl<K: Clone + PartialEq, V: Clone> FromIterator<(K, V)> for EcoMap<K, V> {
fn from_iter<I: IntoIterator<Item = (K, V)>>(iter: I) -> Self {
let iter = iter.into_iter();
let (hint, _) = iter.size_hint();
let mut map = Self::with_capacity(hint);
for (k, v) in iter {
map.insert(k, v);
}
map
}
}
impl<K: Clone + PartialEq, V: Clone> Extend<(K, V)> for EcoMap<K, V> {
fn extend<I: IntoIterator<Item = (K, V)>>(&mut self, iter: I) {
for (k, v) in iter {
self.insert(k, v);
}
}
}
impl<'a, K: Clone + PartialEq, V: Clone> Extend<(&'a K, &'a V)> for EcoMap<K, V> {
fn extend<I: IntoIterator<Item = (&'a K, &'a V)>>(&mut self, iter: I) {
for (k, v) in iter {
self.insert(k.clone(), v.clone());
}
}
}
impl<'a, K: Clone, V: Clone> IntoIterator for &'a EcoMap<K, V> {
type Item = (&'a K, &'a V);
type IntoIter = Iter<'a, K, V>;
#[inline]
fn into_iter(self) -> Self::IntoIter {
self.iter()
}
}
impl<K: Clone, V: Clone> IntoIterator for EcoMap<K, V> {
type Item = (K, V);
type IntoIter = IntoIter<K, V>;
#[inline]
fn into_iter(self) -> Self::IntoIter {
IntoIter {
keys: self.keys.into_iter(),
vals: self.vals.into_iter(),
}
}
}
impl<K, Q, V> Index<&Q> for EcoMap<K, V>
where
K: Clone + PartialEq + Borrow<Q>,
V: Clone,
Q: PartialEq + ?Sized,
{
type Output = V;
#[inline]
fn index(&self, key: &Q) -> &V {
self.get(key).expect("no entry found for key")
}
}
impl<K: Clone + PartialEq, V: Clone, const N: usize> From<[(K, V); N]> for EcoMap<K, V> {
fn from(arr: [(K, V); N]) -> Self {
arr.into_iter().collect()
}
}
impl<K: Clone, V: Clone> EcoMap<K, V> {
#[inline]
pub fn into_keys(self) -> IntoKeys<K> {
IntoKeys(self.keys.into_iter())
}
#[inline]
pub fn into_values(self) -> IntoValues<V> {
IntoValues(self.vals.into_iter())
}
#[inline]
pub fn drain(&mut self) -> Drain<K, V> {
let keys = core::mem::take(&mut self.keys);
let vals = core::mem::take(&mut self.vals);
Drain { keys: keys.into_iter(), vals: vals.into_iter() }
}
}
pub struct IntoKeys<K: Clone>(crate::vec::IntoIter<K, Global>);
impl<K: Clone> Iterator for IntoKeys<K> {
type Item = K;
#[inline]
fn next(&mut self) -> Option<K> {
self.0.next()
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
self.0.size_hint()
}
}
impl<K: Clone> ExactSizeIterator for IntoKeys<K> {}
impl<K: Clone> DoubleEndedIterator for IntoKeys<K> {
#[inline]
fn next_back(&mut self) -> Option<K> {
self.0.next_back()
}
}
pub struct IntoValues<V: Clone>(crate::vec::IntoIter<V, Global>);
impl<V: Clone> Iterator for IntoValues<V> {
type Item = V;
#[inline]
fn next(&mut self) -> Option<V> {
self.0.next()
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
self.0.size_hint()
}
}
impl<V: Clone> ExactSizeIterator for IntoValues<V> {}
impl<V: Clone> DoubleEndedIterator for IntoValues<V> {
#[inline]
fn next_back(&mut self) -> Option<V> {
self.0.next_back()
}
}
pub struct Drain<K: Clone, V: Clone> {
keys: crate::vec::IntoIter<K, Global>,
vals: crate::vec::IntoIter<V, Global>,
}
impl<K: Clone, V: Clone> Iterator for Drain<K, V> {
type Item = (K, V);
#[inline]
fn next(&mut self) -> Option<(K, V)> {
Some((self.keys.next()?, self.vals.next()?))
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
self.keys.size_hint()
}
}
impl<K: Clone, V: Clone> ExactSizeIterator for Drain<K, V> {}
impl<K: Clone, V: Clone> DoubleEndedIterator for Drain<K, V> {
#[inline]
fn next_back(&mut self) -> Option<(K, V)> {
Some((self.keys.next_back()?, self.vals.next_back()?))
}
}