Crate vecstorage[][src]

VecStorage

Struct to re-use the storage of a vector for borrowing values with different lifetimes.

Examples

The following code does not compile:

let mut v = Vec::with_capacity(2);
{
    let x = 1; let y = 2;
    v.push(&x);
    v.push(&y);
    v.clear(); // We stop borrowing here, but the compiler doesn't know that.
}
{
    let a = 1; let b = 2;
    v.push(&a);
    v.push(&b);
    v.clear(); // We stop borrowing here, but the compiler doesn't know that.
}

You can use VecStorage to solve this problem:

use vecstorage::VecStorage;
let mut v = VecStorage::<&'static u32>::with_capacity(2);
{
    let x = 1; let y = 2;
    let mut guard = v.vec_guard();
    // `guard` behaves like a `Vec<&'_ u32>` that can be used to store `&x`.
    guard.push(&x); // No memory allocation here, we use the memory allocated in `v`.
    guard.push(&y);
    // If we were going to push more items on the guard, we would allocate memory.
    // When guard goes out of scope, it is cleared.
}
{
    let a = 1; let b = 2;
    let mut guard = v.vec_guard();
    // Now guard behaves like a vector.
    // The memory from the previous run has been cleared ...
    assert_eq!(guard.len(), 0);
    // ... but the memeroy has been reused.
    assert_eq!(guard.capacity(), 2);
    guard.push(&a);
    guard.push(&b);
}

The VecStorage re-uses the same memory each time:

use vecstorage::VecStorage;
let mut v = VecStorage::<&'static u32>::with_capacity(2);
let capacity;
{
    let x = 1; let y = 2; let z = 3;
    let mut guard = v.vec_guard();
    guard.push(&x); // No memory allocation here, we use the memory allocated in `v`.
    guard.push(&y);
    // Let's push some more items on the guard and allocate memory:
    guard.push(&z);
    capacity = guard.capacity();
    assert!(capacity > 2);
}
{
    let mut guard = v.vec_guard::<&u32>();
    // The memory from the previous run has been cleared ...
    assert_eq!(guard.len(), 0);
    // ... but the capacity is kept:
    assert_eq!(capacity, guard.capacity());
}

The following example illustrates the typical usage of VecStorage.

use vecstorage::VecStorage;

struct WithLifetime<'a> {
    reference: &'a ()
}

struct MyStruct {
    storage: VecStorage<WithLifetime<'static>>
}

impl MyStruct {
    fn with_capacity(capacity: usize) -> Self {
        Self {
            storage: VecStorage::with_capacity(capacity)
        }
    }
     
    fn apply_from_iterator<'a, I, F>(&mut self, iterator: I, f: F)
    where I: Iterator<Item = WithLifetime<'a>>, F: Fn(&[WithLifetime<'a>]) {
        let mut guard = self.storage.vec_guard();
        for item in iterator {
            guard.push(item)
        }
        f(guard.as_slice());
    }
}

VecStorage<T> allocates memory just like Vec<T>. Typically, T is chosen to have a 'static lifetime, but you actually want a a Vec<TGuard>, where TGuard is another data type that does not have a 'static lifetime. If the types T and TGuard have the same size and alignment, you can use the VecStorage<T> to create a VecGuard<TGuard> with the [vec_guard<'_, TGuard>()] method. The VecGuard uses the memory from the VecStorage and can temporarily be used just like a Vec<TGuard> (i.e.: it implements Deref<Target=Vec<TGuard>> and DerefMut<Target=Vec<TGuard>>).

When the VecGuard is dropped, the vector is cleared, but the memory “goes back to the VecStorage” and can be re-used later on to store references with a different lifetime.

Structs

VecGuard

This can be used as a vector of T (Vec<T>).

VecStorage

Re-usable memory for creating a vector of references.