# `BumpVec`
[`BumpVec`] is a collection that uses bump allocation inside. [`BumpVec`] mostly
implements a subset of [`Vec`]'s API, but it also have some own features and
specific behaviors.
[`BumpVec`]: crate::vec::BumpVec
[`Vec`]: https://doc.rust-lang.org/std/vec/struct.Vec.html
## Populating
In order to populate a new vector, use different [`From`] trait implementations:
```rust
use bumpish::BumpVec;
let _ = BumpVec::<_, 3>::from([1, 2, 3]);
```
Also, as expected, [`BumpVec`] allows to add new elements by pushing them to the
vector.
```rust
use bumpish::BumpVec;
let vec = BumpVec::<_, 0>::new();
assert_eq!(vec.push(1), &1);
assert_eq!(vec.push(2), &2);
assert_eq!(vec.push(3), &3);
```
Note, that, in contrast to [`Vec`], we push new elements using immutable
reference (more about that read in the [Allocation](#allocation) part). Also
[`push`] returns a reference to the just pushed element.
[`From`]: https://doc.rust-lang.org/std/convert/trait.From.html
[`push`]: crate::vec::BumpVec::push
## Removing elements
Remove an element is possible by calling [`pop`] method.
```rust
use bumpish::BumpVec;
let mut vec = BumpVec::<_, 0>::from([1, 2, 3]);
assert_eq!(vec.pop(), Some(3));
assert_eq!(vec.pop(), Some(2));
assert_eq!(vec.pop(), Some(1));
```
[`pop`]: crate::vec::BumpVec::pop
Also, [`swap_remove`] can remove an element by swapping it with the last one and
then popping it out.
```rust
use bumpish::BumpVec;
let mut v = BumpVec::<_, 0>::from(["foo", "bar", "baz", "qux"]);
assert_eq!(v.swap_remove(1), "bar");
assert_eq!(v, ["foo", "qux", "baz"]);
```
[`swap_remove`]: crate::vec::BumpVec::swap_remove
## Iteration
Pushing new elements by immutable reference allows to do that during iteration.
To avoid infinite loop, iteration runs over elements that have already existed
at the moment of creating the iterator.
```rust
use bumpish::BumpVec;
let vec = BumpVec::<_, 0>::from([1, 2, 4]);
for elem in vec.iter() {
vec.push(*elem);
}
assert_eq!(vec.len(), 6);
assert_eq!(vec, [1, 2, 4, 1, 2, 4]);
```
# Allocation
[`BumpVec`] uses a linked list of memory chunks that contain elements of the
type `T`. If the current memory chunk is full, the stack allocates another one
from the global allocator (usually two times bigger than the previous chunk),
and keeps pushing new elements to this new chunk. So, in contrast to [`Vec`],
[`BumpVec`] doesn't move old elements from the smaller chunk into the bigger
one. Exactly this property allows to push new elements by immutable reference,
because adding an element never causes moving old elements, and reference
invalidation doesn't happen.
When we pop elements from the vector, if the current chunk becomes empty, then
there is possible one of the following steps:
1. If the chunk is the last chunk in the list, it is not deallocated, but kept
for future use as a cache.
2. If the chunk is not the last one, and we already have another chunk as a
cache, the smallest from both is deallocated, and the biggest is kept as a
new cache.
[`rev`]: https://doc.rust-lang.org/std/iter/trait.Iterator.html#method.rev