#![doc(html_root_url = "https://docs.rs/slab/0.4.2")]
#![deny(warnings, missing_docs, missing_debug_implementations)]
#![cfg_attr(test, deny(warnings, unreachable_pub))]
use std::iter::IntoIterator;
use std::ops;
use std::vec;
use std::{fmt, mem};
#[derive(Clone)]
pub struct Slab<T> {
entries: Vec<Entry<T>>,
len: usize,
next: usize,
}
impl<T> Default for Slab<T> {
fn default() -> Self {
Slab::new()
}
}
#[derive(Debug)]
pub struct VacantEntry<'a, T: 'a> {
slab: &'a mut Slab<T>,
key: usize,
}
pub struct Iter<'a, T: 'a> {
entries: std::slice::Iter<'a, Entry<T>>,
curr: usize,
}
pub struct IterMut<'a, T: 'a> {
entries: std::slice::IterMut<'a, Entry<T>>,
curr: usize,
}
pub struct Drain<'a, T: 'a>(vec::Drain<'a, Entry<T>>);
#[derive(Clone)]
enum Entry<T> {
Vacant(usize),
Occupied(T),
}
impl<T> Slab<T> {
pub fn new() -> Slab<T> {
Slab::with_capacity(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 = self.len + additional - self.entries.len();
self.entries.reserve(need_add);
}
pub fn reserve_exact(&mut self, additional: usize) {
if self.capacity() - self.len >= additional {
return;
}
let need_add = self.len + additional - self.entries.len();
self.entries.reserve_exact(need_add);
}
pub fn shrink_to_fit(&mut self) {
self.entries.shrink_to_fit();
}
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(),
curr: 0,
}
}
pub fn iter_mut(&mut self) -> IterMut<T> {
IterMut {
entries: self.entries.iter_mut(),
curr: 0,
}
}
pub fn get(&self, key: usize) -> Option<&T> {
match self.entries.get(key) {
Some(&Entry::Occupied(ref 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 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 fn insert(&mut self, val: T) -> usize {
let key = self.next;
self.insert_at(key, val);
key
}
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 {
let prev = mem::replace(&mut self.entries[key], Entry::Occupied(val));
match prev {
Entry::Vacant(next) => {
self.next = next;
}
_ => unreachable!(),
}
}
}
pub fn remove(&mut self, key: usize) -> T {
let prev = mem::replace(&mut self.entries[key], Entry::Vacant(self.next));
match prev {
Entry::Occupied(val) => {
self.len -= 1;
self.next = key;
val
}
_ => {
self.entries[key] = prev;
panic!("invalid key");
}
}
}
pub fn contains(&self, key: usize) -> bool {
self.entries
.get(key)
.map(|e| match *e {
Entry::Occupied(_) => true,
_ => false,
})
.unwrap_or(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> {
self.len = 0;
self.next = 0;
Drain(self.entries.drain(..))
}
}
impl<T> ops::Index<usize> for Slab<T> {
type Output = T;
fn index(&self, key: usize) -> &T {
match self.entries[key] {
Entry::Occupied(ref v) => v,
_ => panic!("invalid key"),
}
}
}
impl<T> ops::IndexMut<usize> for Slab<T> {
fn index_mut(&mut self, key: usize) -> &mut T {
match self.entries[key] {
Entry::Occupied(ref mut v) => v,
_ => panic!("invalid key"),
}
}
}
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> fmt::Debug for Slab<T>
where
T: fmt::Debug,
{
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
write!(
fmt,
"Slab {{ len: {}, cap: {} }}",
self.len,
self.capacity()
)
}
}
impl<'a, T: 'a> fmt::Debug for Iter<'a, T>
where
T: fmt::Debug,
{
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
fmt.debug_struct("Iter")
.field("curr", &self.curr)
.field("remaining", &self.entries.len())
.finish()
}
}
impl<'a, T: 'a> fmt::Debug for IterMut<'a, T>
where
T: fmt::Debug,
{
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
fmt.debug_struct("IterMut")
.field("curr", &self.curr)
.field("remaining", &self.entries.len())
.finish()
}
}
impl<'a, T: 'a> fmt::Debug for Drain<'a, 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[self.key] {
Entry::Occupied(ref mut v) => v,
_ => unreachable!(),
}
}
pub fn key(&self) -> usize {
self.key
}
}
impl<'a, T> Iterator for Iter<'a, T> {
type Item = (usize, &'a T);
fn next(&mut self) -> Option<(usize, &'a T)> {
while let Some(entry) = self.entries.next() {
let curr = self.curr;
self.curr += 1;
if let Entry::Occupied(ref v) = *entry {
return Some((curr, v));
}
}
None
}
}
impl<'a, T> Iterator for IterMut<'a, T> {
type Item = (usize, &'a mut T);
fn next(&mut self) -> Option<(usize, &'a mut T)> {
while let Some(entry) = self.entries.next() {
let curr = self.curr;
self.curr += 1;
if let Entry::Occupied(ref mut v) = *entry {
return Some((curr, v));
}
}
None
}
}
impl<'a, T> Iterator for Drain<'a, T> {
type Item = T;
fn next(&mut self) -> Option<T> {
while let Some(entry) = self.0.next() {
if let Entry::Occupied(v) = entry {
return Some(v);
}
}
None
}
}