[][src]Crate slots

This crate provides a heapless slab allocator with strict access control.

Slots implements a "heapless", fixed size, unordered data structure, inspired by SlotMap.

Store data

When a piece of data is stored in the collection, a Key object is returned. This key represents the owner of the stored data: it is required to modify or remove (take out) the stored data.

To ensure the stored data is always valid as long as the key exists, the key can't be cloned.

use slots::Slots;
use slots::consts::U2;

let mut slots: Slots<_, U2> = Slots::new(); // Capacity of 2 elements

// Store elements
let k1 = slots.store(2).unwrap();
let k2 = slots.store(4).unwrap();

// Now that the collection is full, the next store will fail and
// return an Err object that holds the original value we wanted to store.
let k3 = slots.store(8);
assert_eq!(k3, Err(8));

// Storage statistics
assert_eq!(2, slots.capacity()); // this instance can hold at most 2 elements
assert_eq!(2, slots.count()); // there are currently 2 elements stored

Remove data

Removing data from a Slots collection invalidates its key. Because of this, the take method consumes the key.

// initially we have 2 elements in the collection
assert_eq!(2, slots.count());

// remove an element
slots.take(k);

// removing also decreases the count of stored elements
assert_eq!(1, slots.count());
This example deliberately fails to compile
let k1 = slots.store(2).unwrap();

slots.take(k1); // k1 is consumed and can no longer be used
slots.take(k1); // trying to use it again will cause a compile error

Access stored data

The key can be used to read or modify the stored data. This is done by passing a FnOnce closure to the read and modify methods. Whatever the closures return, will be returned by the methods.

let k2 = slots.store(4).unwrap();
// Read element without modification
// closure can be used to transform element
assert_eq!(3, slots.read(&k2, |&e| e - 1));

// Modify a stored element and return a derivative
assert_eq!(3, slots.modify(&k2, |e| {
    *e = 2 + *e;
    3
}));
// The value behind k2 has changed
assert_eq!(6, slots.read(&k2, |&e| e));

Read using a numerical index

It's possible to extract the index of the allocated slot from the Key object, using the index method. Because this returns a number with the usize type, it is not guaranteed to refer to valid data.

let k1 = slots.store(2).unwrap();
let idx = k1.index();
slots.take(k1); // idx no longer points to valid data

assert_eq!(None, slots.try_read(idx, |&e| e*2)); // reading from a freed slot fails by returning None

Passing around Slots

When you need to work with arbitrarily sized Slots objects, you need to specify that the Size trait is implemented for the parameter N.

use slots::{Slots, Size, Key};

fn examine<IT, N>(slots: &Slots<IT, N>, keys: &[Key<IT, N>])
    where N: Size<IT>,
{
    unimplemented!();
}

Modules

consts

Type aliases for many constants.

Structs

Key
Slots

Traits

Size