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 |
VecStorage | Re-usable memory for creating a vector of references. |