cap_vec
A heap-backed vector with fixed maximum capacity for no_std environments.
CapVec<T, N> stores up to N values of type T contiguously in its backing
buffer. Non-zero-sized buffers use heap storage. Unlike Vec<T>, its maximum
capacity is fixed at compile time and never grows after construction. Its
logical length can still change dynamically from 0 to N.
This is useful when a fixed upper bound is part of the program design, but a
stack-allocated [T; N] would be too large or too inflexible.
Features
- Fixed maximum capacity encoded in the const generic parameter
N. - Heap-backed storage for non-zero-sized buffers, avoiding large stack arrays for large capacities.
#![no_std]compatible on targets that providealloc.- Lazy buffer creation for
CapVec::new; non-zero-sized buffers allocate on the first successfulpush,insert, orextend. - No reallocations or growth after the fixed backing buffer exists.
- Common vector operations:
push,pop,insert,remove,clear,truncate,swap_remove,shrink_to_fit,extend, anddrain. - Capacity inspection through
capacity,max_capacity, andspare_capacity. - Slice access through
as_slice,as_mut_slice, andDeref<Target = [T]>. - Front, back, drain, and consuming iteration, including double-ended iterators and remaining-item slice access where applicable.
Allocation Model
CapVec::new creates an empty vector without allocating. The backing buffer is
created on the first successful push, insert, or extend, or when
constructing from a full array with CapVec::from([..]).
For non-zero-sized buffers, the allocation is for exactly N elements.
Zero-sized buffers use a dangling non-null sentinel and do not allocate heap
storage. Operations such as clear remove the initialized elements but keep the
buffer available for later reuse. Calling shrink_to_fit on an empty vector
drops the backing buffer and makes capacity() return 0 again.
Use max_capacity() to get the fixed upper bound N. Use capacity() to get
the currently-created backing buffer size, and spare_capacity() to get the
remaining room in that buffer.
CapVec<T, 0> is valid and can never hold an element.
Example
use CapVec;
let mut values = new;
assert!;
assert_eq!;
assert_eq!;
values.push.unwrap;
values.push.unwrap;
values.push.unwrap;
assert_eq!;
assert_eq!;
assert_eq!;
values.insert.unwrap;
assert_eq!;
assert_eq!;
assert_eq!;
assert_eq!;
assert_eq!;
Draining
drain accepts standard range bounds such as .., start.., ..end,
start..end, and inclusive end bounds. It removes the selected elements and
returns them by value. The source vector is updated when the iterator is
dropped, even if the iterator is only partially consumed.
use CapVec;
let mut values = from;
let removed: = values.drain.collect;
assert_eq!;
assert_eq!;
Drain and the consuming iterator expose their remaining items as slices.
use CapVec;
let values = from;
let mut iter = values.into_iter;
assert_eq!;
assert_eq!;
Installation
Add cap_vec to your Cargo.toml:
or edit Cargo.toml manually:
[]
= "0.3"
Safety and Verification
This crate uses a small amount of unsafe code to manage partially initialized backing storage.
The test suite covers regular operations, zero-sized types, zero capacity, iterator behavior, and panic-safety paths for clone, clear, drain, and consuming iteration. Useful verification commands are:
The CI also runs tests under Miri.
Benchmarks
The benchmark suite compares common CapVec operations with std::vec::Vec
using the same fixed capacity:
License
This crate is licensed under the MIT License. See LICENSE for details.