#![cfg_attr(not(feature = "std"), no_std)]
#![warn(
missing_debug_implementations,
missing_docs,
rust_2018_idioms,
unreachable_pub
)]
#![doc(test(
no_crate_inject,
attr(deny(warnings, rust_2018_idioms), allow(dead_code, unused_variables))
))]
#[cfg(not(feature = "std"))]
extern crate alloc;
#[cfg(feature = "std")]
extern crate std as alloc;
#[cfg(feature = "serde")]
mod serde;
mod builder;
use alloc::vec::{self, Vec};
use core::iter::{self, FromIterator, FusedIterator};
use core::{fmt, mem, ops, slice};
pub struct Slab<T> {
entries: Vec<Entry<T>>,
len: usize,
next: usize,
}
impl<T> Clone for Slab<T>
where
T: Clone,
{
fn clone(&self) -> Self {
Self {
entries: self.entries.clone(),
len: self.len,
next: self.next,
}
}
fn clone_from(&mut self, source: &Self) {
self.entries.clone_from(&source.entries);
self.len = source.len;
self.next = source.next;
}
}
impl<T> Default for Slab<T> {
fn default() -> Self {
Slab::new()
}
}
#[derive(Debug)]
pub struct VacantEntry<'a, T> {
slab: &'a mut Slab<T>,
key: usize,
}
pub struct IntoIter<T> {
entries: iter::Enumerate<vec::IntoIter<Entry<T>>>,
len: usize,
}
pub struct Iter<'a, T> {
entries: iter::Enumerate<slice::Iter<'a, Entry<T>>>,
len: usize,
}
impl<'a, T> Clone for Iter<'a, T> {
fn clone(&self) -> Self {
Self {
entries: self.entries.clone(),
len: self.len,
}
}
}
pub struct IterMut<'a, T> {
entries: iter::Enumerate<slice::IterMut<'a, Entry<T>>>,
len: usize,
}
pub struct Drain<'a, T> {
inner: vec::Drain<'a, Entry<T>>,
len: usize,
}
#[derive(Clone)]
enum Entry<T> {
Vacant(usize),
Occupied(T),
}
impl<T> Slab<T> {
#[cfg(not(slab_no_const_vec_new))]
pub const fn new() -> Self {
Self {
entries: Vec::new(),
next: 0,
len: 0,
}
}
#[cfg(slab_no_const_vec_new)]
pub fn new() -> Self {
Self {
entries: Vec::new(),
next: 0,
len: 0,
}
}
pub fn with_capacity(capacity: usize) -> Slab<T> {
Slab {
entries: Vec::with_capacity(capacity),
next: 0,
len: 0,
}
}
pub fn capacity(&self) -> usize {
self.entries.capacity()
}
pub fn reserve(&mut self, additional: usize) {
if self.capacity() - self.len >= additional {
return;
}
let need_add = additional - (self.entries.len() - self.len);
self.entries.reserve(need_add);
}
pub fn reserve_exact(&mut self, additional: usize) {
if self.capacity() - self.len >= additional {
return;
}
let need_add = additional - (self.entries.len() - self.len);
self.entries.reserve_exact(need_add);
}
pub fn shrink_to_fit(&mut self) {
let len_before = self.entries.len();
while let Some(&Entry::Vacant(_)) = self.entries.last() {
self.entries.pop();
}
if self.entries.len() != len_before {
self.recreate_vacant_list();
}
self.entries.shrink_to_fit();
}
fn recreate_vacant_list(&mut self) {
self.next = self.entries.len();
let mut remaining_vacant = self.entries.len() - self.len;
if remaining_vacant == 0 {
return;
}
for (i, entry) in self.entries.iter_mut().enumerate().rev() {
if let Entry::Vacant(ref mut next) = *entry {
*next = self.next;
self.next = i;
remaining_vacant -= 1;
if remaining_vacant == 0 {
break;
}
}
}
}
pub fn compact<F>(&mut self, mut rekey: F)
where
F: FnMut(&mut T, usize, usize) -> bool,
{
struct CleanupGuard<'a, T> {
slab: &'a mut Slab<T>,
decrement: bool,
}
impl<T> Drop for CleanupGuard<'_, T> {
fn drop(&mut self) {
if self.decrement {
self.slab.len -= 1;
}
self.slab.recreate_vacant_list();
}
}
let mut guard = CleanupGuard {
slab: self,
decrement: true,
};
let mut occupied_until = 0;
while guard.slab.entries.len() > guard.slab.len {
if let Some(Entry::Occupied(mut value)) = guard.slab.entries.pop() {
while let Some(&Entry::Occupied(_)) = guard.slab.entries.get(occupied_until) {
occupied_until += 1;
}
if !rekey(&mut value, guard.slab.entries.len(), occupied_until) {
guard.slab.entries.push(Entry::Occupied(value));
guard.decrement = false;
guard.slab.entries.shrink_to_fit();
return;
}
guard.slab.entries[occupied_until] = Entry::Occupied(value);
occupied_until += 1;
}
}
guard.slab.next = guard.slab.len;
guard.slab.entries.shrink_to_fit();
mem::forget(guard);
}
pub fn clear(&mut self) {
self.entries.clear();
self.len = 0;
self.next = 0;
}
pub fn len(&self) -> usize {
self.len
}
pub fn is_empty(&self) -> bool {
self.len == 0
}
pub fn iter(&self) -> Iter<'_, T> {
Iter {
entries: self.entries.iter().enumerate(),
len: self.len,
}
}
pub fn iter_mut(&mut self) -> IterMut<'_, T> {
IterMut {
entries: self.entries.iter_mut().enumerate(),
len: self.len,
}
}
pub fn get(&self, key: usize) -> Option<&T> {
match self.entries.get(key) {
Some(Entry::Occupied(val)) => Some(val),
_ => None,
}
}
pub fn get_mut(&mut self, key: usize) -> Option<&mut T> {
match self.entries.get_mut(key) {
Some(&mut Entry::Occupied(ref mut val)) => Some(val),
_ => None,
}
}
pub fn get2_mut(&mut self, key1: usize, key2: usize) -> Option<(&mut T, &mut T)> {
assert!(key1 != key2);
let (entry1, entry2);
if key1 > key2 {
let (slice1, slice2) = self.entries.split_at_mut(key1);
entry1 = slice2.get_mut(0);
entry2 = slice1.get_mut(key2);
} else {
let (slice1, slice2) = self.entries.split_at_mut(key2);
entry1 = slice1.get_mut(key1);
entry2 = slice2.get_mut(0);
}
match (entry1, entry2) {
(
Some(&mut Entry::Occupied(ref mut val1)),
Some(&mut Entry::Occupied(ref mut val2)),
) => Some((val1, val2)),
_ => None,
}
}
pub unsafe fn get_unchecked(&self, key: usize) -> &T {
match *self.entries.get_unchecked(key) {
Entry::Occupied(ref val) => val,
_ => unreachable!(),
}
}
pub unsafe fn get_unchecked_mut(&mut self, key: usize) -> &mut T {
match *self.entries.get_unchecked_mut(key) {
Entry::Occupied(ref mut val) => val,
_ => unreachable!(),
}
}
pub unsafe fn get2_unchecked_mut(&mut self, key1: usize, key2: usize) -> (&mut T, &mut T) {
debug_assert_ne!(key1, key2);
let ptr = self.entries.as_mut_ptr();
let ptr1 = ptr.add(key1);
let ptr2 = ptr.add(key2);
match (&mut *ptr1, &mut *ptr2) {
(&mut Entry::Occupied(ref mut val1), &mut Entry::Occupied(ref mut val2)) => {
(val1, val2)
}
_ => unreachable!(),
}
}
#[cfg_attr(not(slab_no_track_caller), track_caller)]
pub fn key_of(&self, present_element: &T) -> usize {
let element_ptr = present_element as *const T as usize;
let base_ptr = self.entries.as_ptr() as usize;
let byte_offset = element_ptr.wrapping_sub(base_ptr);
let key = byte_offset / mem::size_of::<Entry<T>>();
if key >= self.entries.len() {
panic!("The reference points to a value outside this slab");
}
key
}
pub fn insert(&mut self, val: T) -> usize {
let key = self.next;
self.insert_at(key, val);
key
}
pub fn vacant_key(&self) -> usize {
self.next
}
pub fn vacant_entry(&mut self) -> VacantEntry<'_, T> {
VacantEntry {
key: self.next,
slab: self,
}
}
fn insert_at(&mut self, key: usize, val: T) {
self.len += 1;
if key == self.entries.len() {
self.entries.push(Entry::Occupied(val));
self.next = key + 1;
} else {
self.next = match self.entries.get(key) {
Some(&Entry::Vacant(next)) => next,
_ => unreachable!(),
};
self.entries[key] = Entry::Occupied(val);
}
}
pub fn try_remove(&mut self, key: usize) -> Option<T> {
if let Some(entry) = self.entries.get_mut(key) {
let prev = mem::replace(entry, Entry::Vacant(self.next));
match prev {
Entry::Occupied(val) => {
self.len -= 1;
self.next = key;
return val.into();
}
_ => {
*entry = prev;
}
}
}
None
}
#[cfg_attr(not(slab_no_track_caller), track_caller)]
pub fn remove(&mut self, key: usize) -> T {
self.try_remove(key).expect("invalid key")
}
pub fn contains(&self, key: usize) -> bool {
match self.entries.get(key) {
Some(&Entry::Occupied(_)) => true,
_ => false,
}
}
pub fn retain<F>(&mut self, mut f: F)
where
F: FnMut(usize, &mut T) -> bool,
{
for i in 0..self.entries.len() {
let keep = match self.entries[i] {
Entry::Occupied(ref mut v) => f(i, v),
_ => true,
};
if !keep {
self.remove(i);
}
}
}
pub fn drain(&mut self) -> Drain<'_, T> {
let old_len = self.len;
self.len = 0;
self.next = 0;
Drain {
inner: self.entries.drain(..),
len: old_len,
}
}
}
impl<T> ops::Index<usize> for Slab<T> {
type Output = T;
#[cfg_attr(not(slab_no_track_caller), track_caller)]
fn index(&self, key: usize) -> &T {
match self.entries.get(key) {
Some(Entry::Occupied(v)) => v,
_ => panic!("invalid key"),
}
}
}
impl<T> ops::IndexMut<usize> for Slab<T> {
#[cfg_attr(not(slab_no_track_caller), track_caller)]
fn index_mut(&mut self, key: usize) -> &mut T {
match self.entries.get_mut(key) {
Some(&mut Entry::Occupied(ref mut v)) => v,
_ => panic!("invalid key"),
}
}
}
impl<T> IntoIterator for Slab<T> {
type Item = (usize, T);
type IntoIter = IntoIter<T>;
fn into_iter(self) -> IntoIter<T> {
IntoIter {
entries: self.entries.into_iter().enumerate(),
len: self.len,
}
}
}
impl<'a, T> IntoIterator for &'a Slab<T> {
type Item = (usize, &'a T);
type IntoIter = Iter<'a, T>;
fn into_iter(self) -> Iter<'a, T> {
self.iter()
}
}
impl<'a, T> IntoIterator for &'a mut Slab<T> {
type Item = (usize, &'a mut T);
type IntoIter = IterMut<'a, T>;
fn into_iter(self) -> IterMut<'a, T> {
self.iter_mut()
}
}
impl<T> FromIterator<(usize, T)> for Slab<T> {
fn from_iter<I>(iterable: I) -> Self
where
I: IntoIterator<Item = (usize, T)>,
{
let iterator = iterable.into_iter();
let mut builder = builder::Builder::with_capacity(iterator.size_hint().0);
for (key, value) in iterator {
builder.pair(key, value)
}
builder.build()
}
}
impl<T> fmt::Debug for Slab<T>
where
T: fmt::Debug,
{
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
if fmt.alternate() {
fmt.debug_map().entries(self.iter()).finish()
} else {
fmt.debug_struct("Slab")
.field("len", &self.len)
.field("cap", &self.capacity())
.finish()
}
}
}
impl<T> fmt::Debug for IntoIter<T>
where
T: fmt::Debug,
{
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt.debug_struct("IntoIter")
.field("remaining", &self.len)
.finish()
}
}
impl<T> fmt::Debug for Iter<'_, T>
where
T: fmt::Debug,
{
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt.debug_struct("Iter")
.field("remaining", &self.len)
.finish()
}
}
impl<T> fmt::Debug for IterMut<'_, T>
where
T: fmt::Debug,
{
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt.debug_struct("IterMut")
.field("remaining", &self.len)
.finish()
}
}
impl<T> fmt::Debug for Drain<'_, T> {
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt.debug_struct("Drain").finish()
}
}
impl<'a, T> VacantEntry<'a, T> {
pub fn insert(self, val: T) -> &'a mut T {
self.slab.insert_at(self.key, val);
match self.slab.entries.get_mut(self.key) {
Some(&mut Entry::Occupied(ref mut v)) => v,
_ => unreachable!(),
}
}
pub fn key(&self) -> usize {
self.key
}
}
impl<T> Iterator for IntoIter<T> {
type Item = (usize, T);
fn next(&mut self) -> Option<Self::Item> {
for (key, entry) in &mut self.entries {
if let Entry::Occupied(v) = entry {
self.len -= 1;
return Some((key, v));
}
}
debug_assert_eq!(self.len, 0);
None
}
fn size_hint(&self) -> (usize, Option<usize>) {
(self.len, Some(self.len))
}
}
impl<T> DoubleEndedIterator for IntoIter<T> {
fn next_back(&mut self) -> Option<Self::Item> {
while let Some((key, entry)) = self.entries.next_back() {
if let Entry::Occupied(v) = entry {
self.len -= 1;
return Some((key, v));
}
}
debug_assert_eq!(self.len, 0);
None
}
}
impl<T> ExactSizeIterator for IntoIter<T> {
fn len(&self) -> usize {
self.len
}
}
impl<T> FusedIterator for IntoIter<T> {}
impl<'a, T> Iterator for Iter<'a, T> {
type Item = (usize, &'a T);
fn next(&mut self) -> Option<Self::Item> {
for (key, entry) in &mut self.entries {
if let Entry::Occupied(ref v) = *entry {
self.len -= 1;
return Some((key, v));
}
}
debug_assert_eq!(self.len, 0);
None
}
fn size_hint(&self) -> (usize, Option<usize>) {
(self.len, Some(self.len))
}
}
impl<T> DoubleEndedIterator for Iter<'_, T> {
fn next_back(&mut self) -> Option<Self::Item> {
while let Some((key, entry)) = self.entries.next_back() {
if let Entry::Occupied(ref v) = *entry {
self.len -= 1;
return Some((key, v));
}
}
debug_assert_eq!(self.len, 0);
None
}
}
impl<T> ExactSizeIterator for Iter<'_, T> {
fn len(&self) -> usize {
self.len
}
}
impl<T> FusedIterator for Iter<'_, T> {}
impl<'a, T> Iterator for IterMut<'a, T> {
type Item = (usize, &'a mut T);
fn next(&mut self) -> Option<Self::Item> {
for (key, entry) in &mut self.entries {
if let Entry::Occupied(ref mut v) = *entry {
self.len -= 1;
return Some((key, v));
}
}
debug_assert_eq!(self.len, 0);
None
}
fn size_hint(&self) -> (usize, Option<usize>) {
(self.len, Some(self.len))
}
}
impl<T> DoubleEndedIterator for IterMut<'_, T> {
fn next_back(&mut self) -> Option<Self::Item> {
while let Some((key, entry)) = self.entries.next_back() {
if let Entry::Occupied(ref mut v) = *entry {
self.len -= 1;
return Some((key, v));
}
}
debug_assert_eq!(self.len, 0);
None
}
}
impl<T> ExactSizeIterator for IterMut<'_, T> {
fn len(&self) -> usize {
self.len
}
}
impl<T> FusedIterator for IterMut<'_, T> {}
impl<T> Iterator for Drain<'_, T> {
type Item = T;
fn next(&mut self) -> Option<Self::Item> {
for entry in &mut self.inner {
if let Entry::Occupied(v) = entry {
self.len -= 1;
return Some(v);
}
}
debug_assert_eq!(self.len, 0);
None
}
fn size_hint(&self) -> (usize, Option<usize>) {
(self.len, Some(self.len))
}
}
impl<T> DoubleEndedIterator for Drain<'_, T> {
fn next_back(&mut self) -> Option<Self::Item> {
while let Some(entry) = self.inner.next_back() {
if let Entry::Occupied(v) = entry {
self.len -= 1;
return Some(v);
}
}
debug_assert_eq!(self.len, 0);
None
}
}
impl<T> ExactSizeIterator for Drain<'_, T> {
fn len(&self) -> usize {
self.len
}
}
impl<T> FusedIterator for Drain<'_, T> {}