Expand description
Heapless Vec implementation using only libcore
When developing for certain types of systems, especially embedded systems, it is desirable to avoid the non-determinism that can be introduced by using a heap. A commonly used data structure is a “buffer” - a preallocated chunk of memory, either in static memory or on the stack.
Thanks to the extensibility of Rust, it is possible to have a datatype
that performs almost like the libstd Vec
type, without requiring a
heap and while only using libcore.
§Differences from std::vec::Vec
For now, FixedVec
only works for types that implement Copy
. This
requirement will be lifted in the future, but for now it is the most
straightforward way to get to a minimum viable product.
Although every effort has been made to mimic the functionality of Vec
,
this is not a perfect clone. Specifically, functions that require memory
allocation are not included. There are also a few functions where the type
signatures are different - usually to add a Result
that indicates whether
or not adding an element was successful.
Note that the Vec
functionality of panicking when an invalid index is
accessed has been preserved. Note that this is true even if the index is
valid for the underlying memory. So, for example, if a FixedVec
were
allocated with 10 elements, and 3 new elements were pushed to it, accessing
index 5 would panic, even though accessing that memory would be safe.
§Functions with different signatures
The following functions have different signatures than their equivalents in
Vec
.
new
: Self-explanatory - instantiating a different objectpush
,push_all
,insert
: Functions that add elements return a Result indicating if the result was successful.map_in_place
: Similar toVec
map_in_place
, except there is no coercion of the types.
§Functions in FixedVec
not in Vec
available
: Convenience function for checking remaining space.iter
:FixedVec
cannot implementIntoIterator
because the type signature of that trait requires taking ownership of the underlying struct. SinceFixedVec
keeps a reference to its backing store, ownership is not its to give. It’s possible I’m just being dense and this is possible - I’d love to be proven wrong.
§Functions in Vec
excluded from FixedVec
The following Vec
functions do not exist in FixedVec
because they deal
with allocating or reserving memory - a step that is done up-front in
FixedVec
.
with_capacity
from_raw_parts
from_raw_buffer
reserve
reserve_exact
shrink_to_fit
into_boxed_slice
truncate
set_len
append
drain
split_off
§Example
Typical usage looks like the following:
// Pull in fixedvec
#[macro_use]
extern crate fixedvec;
use fixedvec::FixedVec;
fn main() {
let mut preallocated_space = alloc_stack!([u8; 10]);
let mut vec = FixedVec::new(&mut preallocated_space);
assert_eq!(vec.len(), 0);
vec.push_all(&[1, 2, 3]).unwrap();
assert_eq!(vec.len(), 3);
assert_eq!(vec[1], 2);
vec[1] = 5;
assert_eq!(vec[1], 5);
}
If you’re building for an embedded system, you will want to refer to the Rust book section “No stdlib” for instructions on building executables using only libcore.
Macros§
- alloc_
stack - Convenience macro for use with
FixedVec
. Allocates the specified number of elements of specified type on the stack.