#![deny(missing_docs)]
#![allow(clippy::manual_map)]
#![cfg_attr(docsrs, feature(doc_cfg))]
#![cfg_attr(feature = "map_entry_replace", feature(map_entry_replace))] #![cfg_attr(feature = "extract_if", feature(hash_extract_if))] #![cfg_attr(feature = "entry_insert", feature(entry_insert))] #![cfg_attr(feature = "map_try_insert", feature(map_try_insert))] #![cfg_attr(feature = "many_mut", feature(map_many_mut))] #![cfg_attr(feature = "many_mut", feature(get_many_mut))]
use std::borrow::Borrow;
use std::collections::HashMap;
use std::fmt;
use std::fmt::Debug;
use std::hash::{BuildHasher, Hash};
use std::iter::FusedIterator;
use std::ops::Index;
mod base;
mod utils;
#[cfg(feature = "map_try_insert")]
pub use base::entry::OccupiedError;
pub use base::{
entry::{Entry, OccupiedEntry, VacantEntry},
TryReserveError,
};
const DEFAULT_MAX_INLINE_ENTRIES: usize = 16;
pub struct CompactMap<K, V, const N: usize> {
base: base::MapImpl<K, V, N>,
}
impl<K, V, const N: usize> CompactMap<K, V, N> {
#[inline(always)]
#[must_use]
pub const fn new() -> Self {
Self {
base: base::MapImpl::new(),
}
}
#[inline(always)]
pub const fn spilled(&self) -> bool {
self.base.spilled()
}
#[inline(always)]
pub fn capacity(&self) -> usize {
self.base.capacity()
}
#[inline]
pub fn keys(&self) -> Keys<'_, K, V, N> {
Keys {
inner: self.base.iter(),
}
}
#[inline]
pub fn into_keys(self) -> IntoKeys<K, V, N> {
IntoKeys {
inner: self.base.into_iter(),
}
}
pub fn values(&self) -> Values<'_, K, V, N> {
Values {
base: self.base.iter(),
}
}
pub fn values_mut(&mut self) -> ValuesMut<'_, K, V, N> {
ValuesMut {
inner: self.base.iter_mut(),
}
}
#[inline]
pub fn into_values(self) -> IntoValues<K, V, N> {
IntoValues {
inner: self.base.into_iter(),
}
}
#[inline]
pub fn iter(&self) -> Iter<'_, K, V, N> {
Iter {
base: self.base.iter(),
}
}
pub fn iter_mut(&mut self) -> IterMut<'_, K, V, N> {
IterMut {
base: self.base.iter_mut(),
}
}
pub fn len(&self) -> usize {
self.base.len()
}
#[inline]
pub fn is_empty(&self) -> bool {
self.base.is_empty()
}
#[inline]
pub fn drain(&mut self) -> Drain<'_, K, V, N> {
Drain {
base: self.base.drain(),
}
}
#[cfg_attr(docsrs, doc(cfg(feature = "extract_if")))]
#[cfg(feature = "extract_if")]
#[inline]
pub fn extract_if<F>(&mut self, pred: F) -> ExtractIf<'_, K, V, F, N>
where
F: FnMut(&K, &mut V) -> bool,
{
ExtractIf {
base: self.base.extract_if(pred),
}
}
#[inline]
pub fn retain<F>(&mut self, f: F)
where
F: FnMut(&K, &mut V) -> bool,
{
self.base.retain(f)
}
#[inline]
pub fn clear(&mut self) {
self.base.clear();
}
}
impl<K, V, const N: usize> CompactMap<K, V, N>
where
K: Eq + Hash,
{
#[inline]
pub fn reserve(&mut self, additional: usize) {
self.base.reserve(additional)
}
#[inline]
pub fn try_reserve(&mut self, additional: usize) -> Result<(), TryReserveError> {
self.base.try_reserve(additional)
}
#[inline]
pub fn spill(&mut self) {
self.base.spill()
}
#[inline]
pub fn shrink_into_heapless<const M: usize>(
self,
) -> Result<CompactMap<K, V, M>, CompactMap<K, V, N>> {
self.base
.shrink_into_heapless()
.map(|base| CompactMap { base })
.map_err(|base| CompactMap { base })
}
#[inline]
pub fn shrink_to_fit(&mut self) {
self.base.shrink_to_fit();
}
#[inline]
pub fn shrink_to(&mut self, min_capacity: usize) {
self.base.shrink_to(min_capacity);
}
#[inline]
pub fn entry(&mut self, key: K) -> Entry<'_, K, V, N> {
self.base.entry(key)
}
#[inline]
pub fn get<Q>(&self, k: &Q) -> Option<&V>
where
K: Borrow<Q>,
Q: Hash + Eq + ?Sized,
{
self.base.get(k)
}
#[inline]
pub fn get_key_value<Q>(&self, k: &Q) -> Option<(&K, &V)>
where
K: Borrow<Q>,
Q: Hash + Eq + ?Sized,
{
self.base.get_key_value(k)
}
#[cfg_attr(docsrs, doc(cfg(feature = "many_mut")))]
#[cfg(feature = "many_mut")]
#[inline]
pub fn get_many_mut<Q, const M: usize>(&mut self, ks: [&Q; M]) -> Option<[&'_ mut V; M]>
where
K: Borrow<Q>,
Q: Hash + Eq + ?Sized,
{
self.base.get_many_mut(ks)
}
#[cfg_attr(docsrs, doc(cfg(feature = "many_mut")))]
#[cfg(feature = "many_mut")]
#[inline]
pub unsafe fn get_many_unchecked_mut<Q, const M: usize>(
&mut self,
ks: [&Q; M],
) -> Option<[&'_ mut V; M]>
where
K: Borrow<Q>,
Q: Hash + Eq + ?Sized,
{
self.base.get_many_unchecked_mut(ks)
}
#[inline]
pub fn contains_key<Q>(&self, k: &Q) -> bool
where
K: Borrow<Q>,
Q: Hash + Eq + ?Sized,
{
self.base.contains_key(k)
}
#[inline]
pub fn get_mut<Q>(&mut self, k: &Q) -> Option<&mut V>
where
K: Borrow<Q>,
Q: Hash + Eq + ?Sized,
{
self.base.get_mut(k)
}
#[inline]
pub fn insert(&mut self, k: K, v: V) -> Option<V> {
self.base.insert(k, v)
}
#[cfg_attr(docsrs, doc(cfg(feature = "map_try_insert")))]
#[cfg(feature = "map_try_insert")]
pub fn try_insert(&mut self, key: K, value: V) -> Result<&mut V, OccupiedError<'_, K, V, N>> {
match self.entry(key) {
Entry::Occupied(entry) => Err(OccupiedError { entry, value }),
Entry::Vacant(entry) => Ok(entry.insert(value)),
}
}
#[inline]
pub fn remove<Q>(&mut self, k: &Q) -> Option<V>
where
K: Borrow<Q>,
Q: Hash + Eq + ?Sized,
{
self.base.remove(k)
}
#[inline]
pub fn remove_entry<Q>(&mut self, k: &Q) -> Option<(K, V)>
where
K: Borrow<Q>,
Q: Hash + Eq + ?Sized,
{
self.base.remove_entry(k)
}
#[inline]
pub fn into_hashmap(self) -> HashMap<K, V> {
self.base.into_hashmap()
}
#[inline]
pub fn into_hashmap_with_hasher<S: BuildHasher>(self, hash_builder: S) -> HashMap<K, V, S> {
let mut map = HashMap::with_capacity_and_hasher(self.len(), hash_builder);
map.extend(self.base);
map
}
#[inline]
pub fn into_hashmap_with_capacity_and_hasher<S: BuildHasher>(
self,
capacity: usize,
hash_builder: S,
) -> HashMap<K, V, S> {
let mut map = HashMap::with_capacity_and_hasher(capacity.max(self.len()), hash_builder);
map.extend(self.base);
map
}
}
impl<K, V, const N: usize, const M: usize> PartialEq<CompactMap<K, V, M>> for CompactMap<K, V, N>
where
K: Eq + Hash,
V: PartialEq,
{
fn eq(&self, other: &CompactMap<K, V, M>) -> bool {
if self.len() != other.len() {
return false;
}
self.iter()
.all(|(key, value)| other.get(key).map_or(false, |v| *value == *v))
}
}
impl<K, V, const N: usize> Eq for CompactMap<K, V, N>
where
K: Eq + Hash,
V: Eq,
{
}
impl<K, V, const N: usize> Debug for CompactMap<K, V, N>
where
K: Debug,
V: Debug,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_map().entries(self.iter()).finish()
}
}
impl<K, V> Default for CompactMap<K, V, DEFAULT_MAX_INLINE_ENTRIES> {
fn default() -> Self {
Self::new()
}
}
impl<K, Q: ?Sized, V, const N: usize> Index<&Q> for CompactMap<K, V, N>
where
K: Eq + Hash + Borrow<Q>,
Q: Eq + Hash,
{
type Output = V;
#[inline]
fn index(&self, key: &Q) -> &V {
self.get(key).expect("no entry found for key")
}
}
impl<K, V, const N: usize, const M: usize> From<[(K, V); N]> for CompactMap<K, V, M>
where
K: Eq + Hash,
{
fn from(arr: [(K, V); N]) -> Self {
Self {
base: base::MapImpl::from(arr),
}
}
}
pub struct Keys<'a, K, V, const N: usize> {
pub(crate) inner: base::iter::IterInner<'a, K, V, N>,
}
impl<K, V, const N: usize> Clone for Keys<'_, K, V, N> {
fn clone(&self) -> Self {
Self {
inner: self.inner.clone(),
}
}
}
impl<K: Debug, V, const N: usize> Debug for Keys<'_, K, V, N> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_list().entries(self.clone()).finish()
}
}
impl<'a, K, V, const N: usize> Iterator for Keys<'a, K, V, N> {
type Item = &'a K;
#[inline]
fn next(&mut self) -> Option<&'a K> {
self.inner.next().map(|(k, _)| k)
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
self.inner.size_hint()
}
#[inline]
fn count(self) -> usize {
self.inner.len()
}
#[inline]
fn fold<B, F>(self, init: B, mut f: F) -> B
where
Self: Sized,
F: FnMut(B, Self::Item) -> B,
{
self.inner.fold(init, |acc, (k, _)| f(acc, k))
}
}
impl<K, V, const N: usize> ExactSizeIterator for Keys<'_, K, V, N> {
#[inline]
fn len(&self) -> usize {
self.inner.len()
}
}
impl<K, V, const N: usize> FusedIterator for Keys<'_, K, V, N> {}
pub struct IntoKeys<K, V, const N: usize> {
pub(crate) inner: base::iter::IntoIterInner<K, V, N>,
}
impl<K, V, const N: usize> Iterator for IntoKeys<K, V, N> {
type Item = K;
#[inline]
fn next(&mut self) -> Option<K> {
self.inner.next().map(|(k, _)| k)
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
self.inner.size_hint()
}
#[inline]
fn count(self) -> usize {
self.inner.len()
}
#[inline]
fn fold<B, F>(self, init: B, mut f: F) -> B
where
Self: Sized,
F: FnMut(B, Self::Item) -> B,
{
self.inner.fold(init, |acc, (k, _)| f(acc, k))
}
}
impl<K, V, const N: usize> ExactSizeIterator for IntoKeys<K, V, N> {
#[inline]
fn len(&self) -> usize {
self.inner.len()
}
}
impl<K, V, const N: usize> FusedIterator for IntoKeys<K, V, N> {}
pub struct Values<'a, K: 'a, V: 'a, const N: usize> {
base: base::iter::IterInner<'a, K, V, N>,
}
impl<'a, K, V, const N: usize> Iterator for Values<'a, K, V, N> {
type Item = &'a V;
#[inline]
fn next(&mut self) -> Option<&'a V> {
self.base.next().map(|(_, v)| v)
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
self.base.size_hint()
}
#[inline]
fn count(self) -> usize {
self.base.len()
}
#[inline]
fn fold<B, F>(self, init: B, mut f: F) -> B
where
Self: Sized,
F: FnMut(B, Self::Item) -> B,
{
self.base.fold(init, |acc, (_, v)| f(acc, v))
}
}
impl<K, V, const N: usize> ExactSizeIterator for Values<'_, K, V, N> {
#[inline]
fn len(&self) -> usize {
self.base.len()
}
}
impl<K, V, const N: usize> FusedIterator for Values<'_, K, V, N> {}
pub struct ValuesMut<'a, K: 'a, V: 'a, const N: usize> {
inner: base::iter::IterMutInner<'a, K, V, N>,
}
impl<'a, K, V, const N: usize> Iterator for ValuesMut<'a, K, V, N> {
type Item = &'a mut V;
#[inline]
fn next(&mut self) -> Option<&'a mut V> {
self.inner.next().map(|(_, v)| v)
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
self.inner.size_hint()
}
#[inline]
fn count(self) -> usize {
self.inner.len()
}
#[inline]
fn fold<B, F>(self, init: B, mut f: F) -> B
where
Self: Sized,
F: FnMut(B, Self::Item) -> B,
{
self.inner.fold(init, |acc, (_, v)| f(acc, v))
}
}
impl<K, V, const N: usize> ExactSizeIterator for ValuesMut<'_, K, V, N> {
#[inline]
fn len(&self) -> usize {
self.inner.len()
}
}
impl<K, V, const N: usize> FusedIterator for ValuesMut<'_, K, V, N> {}
pub struct IntoValues<K, V, const N: usize> {
inner: base::iter::IntoIterInner<K, V, N>,
}
impl<K, V, const N: usize> Iterator for IntoValues<K, V, N> {
type Item = V;
#[inline]
fn next(&mut self) -> Option<V> {
self.inner.next().map(|(_, v)| v)
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
self.inner.size_hint()
}
#[inline]
fn count(self) -> usize {
self.inner.len()
}
#[inline]
fn fold<B, F>(self, init: B, mut f: F) -> B
where
Self: Sized,
F: FnMut(B, Self::Item) -> B,
{
self.inner.fold(init, |acc, (_, v)| f(acc, v))
}
}
impl<K, V, const N: usize> ExactSizeIterator for IntoValues<K, V, N> {
#[inline]
fn len(&self) -> usize {
self.inner.len()
}
}
impl<K, V, const N: usize> FusedIterator for IntoValues<K, V, N> {}
pub struct Iter<'a, K, V, const N: usize> {
pub(crate) base: base::iter::IterInner<'a, K, V, N>,
}
impl<'a, K, V, const N: usize> Iterator for Iter<'a, K, V, N> {
type Item = (&'a K, &'a V);
#[inline]
fn next(&mut self) -> Option<(&'a K, &'a V)> {
self.base.next()
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
self.base.size_hint()
}
#[inline]
fn count(self) -> usize {
self.base.count()
}
#[inline]
fn fold<B, F>(self, init: B, f: F) -> B
where
Self: Sized,
F: FnMut(B, Self::Item) -> B,
{
self.base.fold(init, f)
}
}
impl<'a, K, V, const N: usize> ExactSizeIterator for Iter<'a, K, V, N> {
#[inline]
fn len(&self) -> usize {
self.base.len()
}
}
impl<'a, K, V, const N: usize> FusedIterator for Iter<'a, K, V, N> {}
pub struct IterMut<'a, K: 'a, V: 'a, const N: usize> {
base: base::iter::IterMutInner<'a, K, V, N>,
}
impl<'a, K, V, const N: usize> Iterator for IterMut<'a, K, V, N> {
type Item = (&'a K, &'a mut V);
#[inline]
fn next(&mut self) -> Option<(&'a K, &'a mut V)> {
self.base.next()
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
self.base.size_hint()
}
#[inline]
fn count(self) -> usize {
self.base.len()
}
#[inline]
fn fold<B, F>(self, init: B, f: F) -> B
where
Self: Sized,
F: FnMut(B, Self::Item) -> B,
{
self.base.fold(init, f)
}
}
impl<K, V, const N: usize> ExactSizeIterator for IterMut<'_, K, V, N> {
#[inline]
fn len(&self) -> usize {
self.base.len()
}
}
impl<K, V, const N: usize> FusedIterator for IterMut<'_, K, V, N> {}
pub struct IntoIter<K, V, const N: usize> {
base: base::iter::IntoIterInner<K, V, N>,
}
impl<K: Debug, V: Debug, const N: usize> Debug for IntoIter<K, V, N> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.base.fmt(f)
}
}
impl<K, V, const N: usize> Iterator for IntoIter<K, V, N> {
type Item = (K, V);
#[inline]
fn next(&mut self) -> Option<(K, V)> {
self.base.next()
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
self.base.size_hint()
}
#[inline]
fn count(self) -> usize {
self.base.len()
}
#[inline]
fn fold<B, F>(self, init: B, f: F) -> B
where
Self: Sized,
F: FnMut(B, Self::Item) -> B,
{
self.base.fold(init, f)
}
}
impl<K, V, const N: usize> ExactSizeIterator for IntoIter<K, V, N> {
#[inline]
fn len(&self) -> usize {
self.base.len()
}
}
impl<K, V, const N: usize> FusedIterator for IntoIter<K, V, N> {}
impl<'a, K, V, const N: usize> IntoIterator for &'a CompactMap<K, V, N> {
type Item = (&'a K, &'a V);
type IntoIter = Iter<'a, K, V, N>;
#[inline]
fn into_iter(self) -> Iter<'a, K, V, N> {
self.iter()
}
}
impl<'a, K, V, const N: usize> IntoIterator for &'a mut CompactMap<K, V, N> {
type Item = (&'a K, &'a mut V);
type IntoIter = IterMut<'a, K, V, N>;
#[inline]
fn into_iter(self) -> IterMut<'a, K, V, N> {
self.iter_mut()
}
}
pub struct Drain<'a, K: 'a, V: 'a, const N: usize> {
base: base::drain::DrainInner<'a, K, V, N>,
}
impl<K: Debug, V: Debug, const N: usize> Debug for Drain<'_, K, V, N> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.base.fmt(f)
}
}
impl<'a, K, V, const N: usize> Iterator for Drain<'a, K, V, N> {
type Item = (K, V);
#[inline]
fn next(&mut self) -> Option<(K, V)> {
self.base.next()
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
self.base.size_hint()
}
#[inline]
fn count(self) -> usize {
self.base.count()
}
#[inline]
fn fold<B, F>(self, init: B, f: F) -> B
where
Self: Sized,
F: FnMut(B, Self::Item) -> B,
{
self.base.fold(init, f)
}
}
impl<K, V, const N: usize> ExactSizeIterator for Drain<'_, K, V, N> {
#[inline]
fn len(&self) -> usize {
self.base.len()
}
}
impl<K, V, const N: usize> FusedIterator for Drain<'_, K, V, N> {}
#[cfg_attr(docsrs, doc(cfg(feature = "extract_if")))]
#[cfg(feature = "extract_if")]
#[must_use = "iterators are lazy and do nothing unless consumed"]
pub struct ExtractIf<'a, K, V, F, const N: usize>
where
F: FnMut(&K, &mut V) -> bool,
{
base: base::extract_if::ExtractIfInner<'a, K, V, F, N>,
}
#[cfg_attr(docsrs, doc(cfg(feature = "extract_if")))]
#[cfg(feature = "extract_if")]
impl<K, V, F, const N: usize> Iterator for ExtractIf<'_, K, V, F, N>
where
F: FnMut(&K, &mut V) -> bool,
{
type Item = (K, V);
#[inline]
fn next(&mut self) -> Option<(K, V)> {
self.base.next()
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
self.base.size_hint()
}
}
#[cfg_attr(docsrs, doc(cfg(feature = "extract_if")))]
#[cfg(feature = "extract_if")]
impl<K, V, F, const N: usize> FusedIterator for ExtractIf<'_, K, V, F, N> where
F: FnMut(&K, &mut V) -> bool
{
}
#[cfg_attr(docsrs, doc(cfg(feature = "extract_if")))]
#[cfg(feature = "extract_if")]
impl<'a, K, V, F, const N: usize> Debug for ExtractIf<'a, K, V, F, N>
where
F: FnMut(&K, &mut V) -> bool,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("ExtractIf").finish_non_exhaustive()
}
}
impl<K, V, const N: usize> IntoIterator for CompactMap<K, V, N> {
type Item = (K, V);
type IntoIter = IntoIter<K, V, N>;
#[inline]
fn into_iter(self) -> IntoIter<K, V, N> {
IntoIter {
base: self.base.into_iter(),
}
}
}
impl<K, V, const N: usize> FromIterator<(K, V)> for CompactMap<K, V, N>
where
K: Eq + Hash,
{
fn from_iter<T: IntoIterator<Item = (K, V)>>(iter: T) -> Self {
let mut map = CompactMap::new();
map.extend(iter);
map
}
}
impl<K, V, const N: usize> Extend<(K, V)> for CompactMap<K, V, N>
where
K: Eq + Hash,
{
fn extend<T: IntoIterator<Item = (K, V)>>(&mut self, iter: T) {
self.base.extend(iter);
}
}