Struct orx_imp_vec::ImpVec
source · pub struct ImpVec<T, P>where
P: PinnedVec<T>,{ /* private fields */ }Expand description
ImpVec stands for ‘immutable-push-vec’.
It may orx_split_vec::SplitVec as the underlying data structure providing
flexible growth strategies, or orx_fixed_vec::FixedVec with a preset strict capacity
while providing standard vector complexity in common operations.
In addition, it allows to push/extend the vector with an immutable reference.
This allows to hold on the references of already pushed elements while building the collection.
Implementations§
source§impl<T, P> ImpVec<T, P>where
P: PinnedVec<T>,
impl<T, P> ImpVec<T, P>where P: PinnedVec<T>,
sourcepub fn iter(&self) -> ImpVecIter<'_, T, P> ⓘ
pub fn iter(&self) -> ImpVecIter<'_, T, P> ⓘ
Returns an iterator for the imp-vec.
sourcepub fn iter_mut(&mut self) -> ImpVecIterMut<'_, T, P> ⓘ
pub fn iter_mut(&mut self) -> ImpVecIterMut<'_, T, P> ⓘ
Returns a mutable iterator for the imp-vec.
source§impl<T, P> ImpVec<T, P>where
P: PinnedVec<T>,
impl<T, P> ImpVec<T, P>where P: PinnedVec<T>,
sourcepub fn push(&self, value: T)
pub fn push(&self, value: T)
Appends an element to the back of a collection.
Unlike std::vec::Vec or orx_split_vec::SplitVec;
push operation for ImpVec does not require a mutable reference.
Examples
use orx_imp_vec::prelude::*;
let vec: ImpVec<_, _> = FixedVec::new(10).into();
vec.push(1);
vec.push(2);
// since push does not require a mut reference,
// it is legal to hold on to other immutable references
// while pushing elements.
let ref_elem = &vec[1];
let ref_elem_addr = ref_elem as *const i32;
assert_eq!(2, *ref_elem);
vec.push(3);
vec.push(4);
vec.push(5);
assert_eq!(2, *ref_elem);
assert_eq!(vec, [1, 2, 3, 4, 5]);
let ref_elem_addr_after_growth = &vec[1] as *const i32;
assert_eq!(ref_elem_addr, ref_elem_addr_after_growth);source§impl<'a, T, P> ImpVec<T, P>where
P: PinnedVec<T> + 'a,
impl<'a, T, P> ImpVec<T, P>where P: PinnedVec<T> + 'a,
sourcepub fn push_get_ref<'b>(&'b self, value: T) -> &'a Twhere
'a: 'b,
pub fn push_get_ref<'b>(&'b self, value: T) -> &'a Twhere 'a: 'b,
Appends an element to the back of a collection and returns a reference to it.
The reference will always be valid unless the collection is mutated;
note that methods that grows the vector do not require a mutable reference,
such as, push, push_get_ref, extend or extend_from_slice methods.
Examples
Hold on to valid references while pushing new items,
as long as the collection is not mutated with methods such as insert, remove or pop.
use orx_imp_vec::prelude::*;
let vec: ImpVec<_, _> = FixedVec::new(10).into();
let ref1 = vec.push_get_ref(1);
let ref_elem_addr = ref1 as *const i32;
vec.push(2);
vec.push(3);
let ref4 = vec.push_get_ref(4);
// capacity is expaneded here from 4 to 8; however, in chunks;
// therefore, data is not moved around and the references remain valid.
let ref5 = vec.push_get_ref(5);
assert_eq!(ref1, &1);
assert_eq!(ref4, &4);
assert_eq!(ref5, &5);
assert_eq!(vec, [1, 2, 3, 4, 5]);
let ref_elem_addr_after_growth = &vec[0] as *const i32;
assert_eq!(ref_elem_addr, ref_elem_addr_after_growth);As you may see below, any mutable method that can possibly invalidate the references are not allowed.
use orx_imp_vec::prelude::*;
let mut vec: ImpVec<_, _> = SplitVec::with_linear_growth(10).into(); // mut required for the `insert`
let ref1 = vec.push_get_ref(1);
vec.push(2);
vec.push(3);
assert_eq!(ref1, &1);
assert_eq!(vec, [1, 2, 3]);
vec.insert(0, 42);
assert_eq!(vec, [42, 1, 2, 3]);
// below line does not compile as the 'insert' call breaks reference 'ref1'
// let value1 = *ref1;