once_vec
once_vec provides a safe grow-only vector backed by OnceCell.
It is designed for cases where you want to append values without taking &mut self,
but do not need in-place mutation or removal after insertion. The crate is no_std
and only depends on alloc.
Features
- Append-only storage
- Push without a mutable reference
- Immutable once inserted
- Chunked allocation in powers of two
- Efficient access and insertion:
getis O(1);pushis amortized O(1) (occasional chunk allocation/initialization cost). The accesses are not as fast as aVec<T>because of the chunked layout (extra index computation), but are still O(1). - Safe implementation
no_stdcompatible
Behavior
OnceVec<T, N> stores elements in chunks of size 1, 2, 4, ...,
up to a maximum length of 2^N - 1.
pushappends a value and returns its index (does not require a mutable reference).getreturns a shared reference to a value by index.iteryields elements in insertion order.clearremoves all elements and allows reuse of the same container.
Once a value has been pushed, it cannot be replaced or removed individually. If you need interior mutation, store a type with its own interior mutability.
Example
use Vec;
use OnceVec;
let values = default;
let a = values.push;
let b = values.push;
assert_eq!;
assert_eq!;
assert_eq!;
assert_eq!;
let collected: = values.iter.copied.collect;
assert_eq!;
Capacity
The default chunk count is 32, which gives a theoretical maximum length of 2^32 - 1
elements on 32-bit and larger targets, subject to available memory.
You can choose a smaller N when constructing the type if you want a lower maximum capacity.
Comparison
vs elsa::FrozenVec
FrozenVecusesstable_deref_trait::StableDereffor the API that returns stable references to inserted items (&T::Target), which typically means storing values behind indirection (for exampleBox<T>,Arc<T>, etc.).- Implementation includes
unsafeinternally (for example viaUnsafeCellaccess patterns insrc/vec.rs). once_vecis fully safe Rust and stores plainTdirectly.
vs append-only-vec
- Similar high-level approach (chunked growth with O(1) indexing and
amortized O(1) append), including non-
&mutappend semantics. - Implementation relies on
unsafe(raw pointers,UnsafeCell, manual allocation/deallocation) insrc/lib.rs. once_vecaims for the same usage style withoutunsafe.
vs appendlist
- Uses a
Vec<Vec<T>>chunk layout and explicitly documents an unsafe-internal implementation strategy (for example withUnsafeCell<Vec<Vec<T>>>). - Also provides O(1) indexing and append behavior with chunked growth.
once_vecprovides a similar append-only ergonomics with a fully safe,OnceCell-based implementation.