# cap_vec
[](https://crates.io/crates/cap_vec)
[](https://docs.rs/cap_vec)
[](https://github.com/daddinuz/cap_vec/blob/main/LICENSE)
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 provide `alloc`.
- Lazy buffer creation for `CapVec::new`; non-zero-sized buffers allocate on
the first successful `push`, `insert`, or `extend`.
- 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`, and `drain`.
- Capacity inspection through `capacity`, `max_capacity`, and
`spare_capacity`.
- Slice access through `as_slice`, `as_mut_slice`, and `Deref<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
```rust
use cap_vec::CapVec;
let mut values = CapVec::<i32, 4>::new();
assert!(values.is_empty());
assert_eq!(values.capacity(), 0);
assert_eq!(values.max_capacity(), 4);
values.push(10).unwrap();
values.push(20).unwrap();
values.push(30).unwrap();
assert_eq!(values.as_slice(), &[10, 20, 30]);
assert_eq!(values.capacity(), 4);
assert_eq!(values.spare_capacity(), 1);
values.insert(1, 15).unwrap();
assert_eq!(values.as_slice(), &[10, 15, 20, 30]);
assert_eq!(values.push(40), Err(40));
assert_eq!(values.remove(2), Some(20));
assert_eq!(values.pop(), Some(30));
assert_eq!(values.as_slice(), &[10, 15]);
```
## 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.
```rust
use cap_vec::CapVec;
let mut values = CapVec::from([1, 2, 3, 4]);
let removed: Vec<_> = values.drain(1..).collect();
assert_eq!(removed, [2, 3, 4]);
assert_eq!(values.as_slice(), &[1]);
```
`Drain` and the consuming iterator expose their remaining items as slices.
```rust
use cap_vec::CapVec;
let values = CapVec::from([1, 2, 3, 4]);
let mut iter = values.into_iter();
assert_eq!(iter.next(), Some(1));
assert_eq!(iter.as_slice(), &[2, 3, 4]);
```
## Installation
Add `cap_vec` to your `Cargo.toml`:
```bash
cargo add cap_vec
```
or edit `Cargo.toml` manually:
```toml
[dependencies]
cap_vec = "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:
```bash
cargo test
cargo +nightly miri test
```
The CI also runs tests under [Miri](https://github.com/rust-lang/miri).
## Benchmarks
The benchmark suite compares common `CapVec` operations with `std::vec::Vec`
using the same fixed capacity:
```bash
cargo bench --bench bench
```
## License
This crate is licensed under the MIT License. See [LICENSE](LICENSE) for details.