#![doc = include_str!("../README.md")]
#![no_std]
#![cfg_attr(feature = "doc_auto_cfg", feature(doc_auto_cfg))]
#![cfg_attr(feature = "allocator_api", feature(allocator_api))]
use core::{
borrow::Borrow,
fmt::{self, Debug, Formatter},
marker::PhantomData,
mem,
ops::{Index, IndexMut},
slice::Iter,
};
extern crate alloc;
use alloc::{
collections::TryReserveError,
vec::{IntoIter, Vec},
};
pub mod allocator;
pub mod entry;
pub mod iter;
#[cfg(test)]
mod test;
use self::{
allocator::{Allocator, DefaultAllocator},
entry::{Entry, OccupiedEntry, VacantEntry},
iter::{Drain, IntoKeys, IntoValues, IterMut, Keys, Values, ValuesMut},
};
#[derive(Clone)]
pub struct AssocList<K, V, A: Allocator = DefaultAllocator> {
#[cfg(feature = "allocator_api")]
vec: Vec<(K, V), A>,
#[cfg(not(feature = "allocator_api"))]
vec: Vec<(K, V)>,
phantom: PhantomData<A>,
}
impl<K, V> AssocList<K, V> {
#[must_use]
#[inline]
pub const fn new() -> Self {
AssocList { vec: Vec::new(), phantom: PhantomData }
}
#[must_use]
#[inline]
pub fn with_capacity(capacity: usize) -> Self {
AssocList { vec: Vec::with_capacity(capacity), phantom: PhantomData }
}
}
#[macro_export]
macro_rules! assoc_list {
($(($key: expr, $value: expr)),* $(,)?) => {{
#[allow(unused_mut)]
let mut assoc_list = AssocList::with_capacity($crate::count!($($key),*));
$(
let _ = assoc_list.insert($key, $value);
)*
assoc_list
}};
}
#[macro_export]
macro_rules! count {
($(,)?) => {
0
};
($head: expr $(, $tail: expr)* $(,)?) => {{
1 + $crate::count!($($tail),*)
}};
}
#[cfg(feature = "allocator_api")]
impl<K, V, A: Allocator> AssocList<K, V, A> {
#[must_use]
#[inline]
pub const fn new_in(alloc: A) -> Self {
AssocList { vec: Vec::new_in(alloc), phantom: PhantomData }
}
#[must_use]
#[inline]
pub fn with_capacity_in(capacity: usize, alloc: A) -> Self {
AssocList { vec: Vec::with_capacity_in(capacity, alloc), phantom: PhantomData }
}
}
impl<K, V, A: Allocator> AssocList<K, V, A> {
#[inline]
pub fn keys(&self) -> Keys<'_, K, V> {
Keys(self.vec.iter())
}
#[inline]
pub fn into_keys(self) -> IntoKeys<K, V, A> {
IntoKeys { iter: self.vec.into_iter(), phantom: self.phantom }
}
#[inline]
pub fn values(&self) -> Values<'_, K, V> {
Values(self.vec.iter())
}
#[inline]
pub fn values_mut(&mut self) -> ValuesMut<'_, K, V> {
ValuesMut(self.vec.iter_mut())
}
#[inline]
pub fn into_values(self) -> IntoValues<K, V, A> {
IntoValues { iter: self.vec.into_iter(), phantom: self.phantom }
}
#[inline]
pub fn iter(&self) -> Iter<'_, (K, V)> {
self.vec.iter()
}
#[inline]
pub fn iter_mut(&mut self) -> IterMut<'_, K, V> {
IterMut(self.vec.iter_mut())
}
#[inline]
pub fn drain(&mut self) -> Drain<'_, K, V, A> {
Drain { iter: self.vec.drain(..), phantom: self.phantom }
}
#[must_use]
#[inline]
pub fn len(&self) -> usize {
self.vec.len()
}
#[must_use]
#[inline]
pub fn capacity(&self) -> usize {
self.vec.capacity()
}
#[must_use]
#[inline]
pub fn is_empty(&self) -> bool {
self.vec.is_empty()
}
#[inline]
pub fn clear(&mut self) {
self.vec.clear();
}
#[inline]
pub fn entry(&mut self, key: K) -> Entry<'_, K, V, A>
where
K: PartialEq,
{
for (index, (contained_key, _contained_value)) in self.vec.iter_mut().enumerate() {
if contained_key == &key {
return Entry::Occupied(OccupiedEntry {
vec: &mut self.vec,
phantom: self.phantom,
key,
index,
});
}
}
Entry::Vacant(VacantEntry { vec: &mut self.vec, phantom: self.phantom, key })
}
#[must_use]
#[inline]
pub fn contains_key<Q>(&self, key: &Q) -> bool
where
K: Borrow<Q>,
Q: PartialEq + ?Sized,
{
for (contained_key, _contained_value) in &self.vec {
if contained_key.borrow() == key {
return true;
}
}
false
}
#[must_use]
#[inline]
pub fn get<Q>(&self, key: &Q) -> Option<&V>
where
K: Borrow<Q>,
Q: PartialEq + ?Sized,
{
for (contained_key, contained_value) in &self.vec {
if contained_key.borrow() == key {
return Some(contained_value);
}
}
None
}
#[must_use]
#[inline]
pub fn get_key_value<Q>(&self, key: &Q) -> Option<(&K, &V)>
where
K: Borrow<Q>,
Q: PartialEq + ?Sized,
{
for (contained_key, contained_value) in &self.vec {
if contained_key.borrow() == key {
return Some((contained_key, contained_value));
}
}
None
}
#[must_use]
#[inline]
pub fn get_mut<Q>(&mut self, key: &Q) -> Option<&mut V>
where
K: Borrow<Q>,
Q: PartialEq + ?Sized,
{
for (contained_key, contained_value) in &mut self.vec {
if Borrow::<Q>::borrow(contained_key) == key {
return Some(contained_value);
}
}
None
}
#[must_use]
#[inline]
pub fn insert(&mut self, key: K, value: V) -> Option<V>
where
K: PartialEq,
{
for (contained_key, contained_value) in &mut self.vec {
if contained_key == &key {
let bisher = mem::replace(contained_value, value);
return Some(bisher);
}
}
self.vec.push((key, value));
None
}
#[must_use]
#[inline]
pub fn remove<Q>(&mut self, key: &Q) -> Option<V>
where
K: Borrow<Q>,
Q: PartialEq + ?Sized,
{
for (index, (enthaltener_key, _enthaltener_value)) in self.vec.iter().enumerate() {
if enthaltener_key.borrow() == key {
let (_old_key, old_value) = self.vec.swap_remove(index);
return Some(old_value);
}
}
None
}
#[must_use]
#[inline]
pub fn remove_entry<Q>(&mut self, key: &Q) -> Option<(K, V)>
where
K: Borrow<Q>,
Q: PartialEq + ?Sized,
{
for (index, (enthaltener_key, _enthaltener_value)) in self.vec.iter().enumerate() {
if enthaltener_key.borrow() == key {
let old_pair = self.vec.swap_remove(index);
return Some(old_pair);
}
}
None
}
#[inline]
pub fn reserve(&mut self, additional: usize) {
self.vec.reserve(additional);
}
#[inline]
pub fn reserve_exact(&mut self, additional: usize) {
self.vec.reserve_exact(additional);
}
#[inline]
pub fn try_reserve(&mut self, additional: usize) -> Result<(), TryReserveError> {
self.vec.try_reserve(additional)
}
#[inline]
pub fn try_reserve_exact(&mut self, additional: usize) -> Result<(), TryReserveError> {
self.vec.try_reserve_exact(additional)
}
#[inline]
pub fn shrink_to(&mut self, min_capacity: usize) {
self.vec.shrink_to(min_capacity);
}
#[inline]
pub fn shrink_to_fit(&mut self) {
self.vec.shrink_to_fit();
}
}
impl<K: Debug, V: Debug, A: Allocator> Debug for AssocList<K, V, A> {
#[inline]
fn fmt(&self, formatter: &mut Formatter<'_>) -> fmt::Result {
formatter
.debug_struct("AssocList")
.field("vec", &self.vec)
.field("phantom", &self.phantom)
.finish()
}
}
impl<K: PartialEq, V: PartialEq, A: Allocator> PartialEq for AssocList<K, V, A> {
#[inline]
fn eq(&self, other: &Self) -> bool {
if self.len() != other.len() {
return false;
}
for (key, value) in self {
if other.get(key) != Some(value) {
return false;
}
}
true
}
}
impl<K: Eq, V: Eq, A: Allocator> Eq for AssocList<K, V, A> {}
impl<K: Default, V: Default> Default for AssocList<K, V> {
#[inline]
fn default() -> Self {
Self { vec: Vec::new(), phantom: PhantomData }
}
}
impl<K: PartialEq, V, A: Allocator> Extend<(K, V)> for AssocList<K, V, A> {
#[inline]
fn extend<T: IntoIterator<Item = (K, V)>>(&mut self, iter: T) {
for (key, value) in iter {
let _ = self.insert(key, value);
}
}
}
impl<'a, K, V, A: Allocator> Extend<(&'a K, &'a V)> for AssocList<K, V, A>
where
K: PartialEq + Clone,
V: Clone,
{
#[inline]
fn extend<T: IntoIterator<Item = (&'a K, &'a V)>>(&mut self, iter: T) {
for (key, value) in iter {
let _ = self.insert(key.clone(), value.clone());
}
}
}
impl<K: PartialEq, V, const N: usize> From<[(K, V); N]> for AssocList<K, V> {
#[inline]
fn from(array: [(K, V); N]) -> Self {
let mut assoc_list = AssocList::with_capacity(N);
for (key, value) in array {
let _ = assoc_list.insert(key, value);
}
assoc_list
}
}
impl<Q: PartialEq, K: Borrow<Q>, V, A: Allocator> Index<Q> for AssocList<K, V, A> {
type Output = V;
#[inline]
fn index(&self, key: Q) -> &Self::Output {
self.get(&key).expect("Unknown key")
}
}
impl<Q: PartialEq, K: Borrow<Q>, V, A: Allocator> IndexMut<Q> for AssocList<K, V, A> {
#[inline]
fn index_mut(&mut self, key: Q) -> &mut Self::Output {
self.get_mut(&key).expect("Unknown key")
}
}
impl<K, V, A: Allocator> IntoIterator for AssocList<K, V, A> {
type Item = (K, V);
#[cfg(feature = "allocator_api")]
type IntoIter = IntoIter<(K, V), A>;
#[cfg(not(feature = "allocator_api"))]
type IntoIter = IntoIter<(K, V)>;
#[inline]
fn into_iter(self) -> Self::IntoIter {
self.vec.into_iter()
}
}
impl<'a, K, V, A: Allocator> IntoIterator for &'a AssocList<K, V, A> {
type Item = &'a (K, V);
type IntoIter = Iter<'a, (K, V)>;
#[inline]
fn into_iter(self) -> Self::IntoIter {
self.vec.iter()
}
}
impl<'a, K, V, A: Allocator> IntoIterator for &'a mut AssocList<K, V, A> {
type Item = (&'a K, &'a mut V);
type IntoIter = IterMut<'a, K, V>;
#[inline]
fn into_iter(self) -> Self::IntoIter {
IterMut(self.vec.iter_mut())
}
}
impl<K: PartialEq, V> FromIterator<(K, V)> for AssocList<K, V> {
#[inline]
fn from_iter<T: IntoIterator<Item = (K, V)>>(iter: T) -> Self {
let mut assoc_list = AssocList::new();
assoc_list.extend(iter);
assoc_list
}
}