cap_vec 0.3.0

A no_std heap-backed vector with fixed compile-time maximum capacity.
Documentation
  • Coverage
  • 100%
    27 out of 27 items documented17 out of 27 items with examples
  • Size
  • Source code size: 123.23 kB This is the summed size of all the files inside the crates.io package for this release.
  • Documentation size: 1.51 MB This is the summed size of all files generated by rustdoc for all configured targets
  • Ø build duration
  • this release: 9s Average build duration of successful builds.
  • all releases: 12s Average build duration of successful builds in releases after 2024-10-23.
  • Links
  • Homepage
  • daddinuz/cap_vec
    1 0 0
  • crates.io
  • Dependencies
  • Versions
  • Owners
  • daddinuz

cap_vec

Crates.io Docs.rs 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

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.

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.

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:

cargo add cap_vec

or edit Cargo.toml manually:

[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:

cargo test
cargo +nightly miri test

The CI also runs tests under Miri.

Benchmarks

The benchmark suite compares common CapVec operations with std::vec::Vec using the same fixed capacity:

cargo bench --bench bench

License

This crate is licensed under the MIT License. See LICENSE for details.