Struct orx_imp_vec::ImpVec

source ·
pub struct ImpVec<T, P = SplitVec<T>>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: PinnedVecSimple<T>, T: NotSelfRefVecItem,

source

pub fn insert(&mut self, index: usize, element: T)

Inserts an element at position index within the vector, shifting all elements after it to the right.

Panics

Panics if index >= len.

Safety

insert operation for an ImpVec where the elements are T: NotSelfRefVecItem is safe; in this case, pinned vector shares the same safety requirements as std::vec::Vec which is readily provided by the borrow checker.

source

pub fn remove(&mut self, index: usize) -> T

Removes and returns the element at position index within the vector, shifting all elements after it to the left.

Panics

Panics if index is out of bounds.

Safety

remove operation for a ImpVec where the elements are T: NotSelfRefVecItem is safe; in this case, pinned vector shares the same safety requirements as std::vec::Vec which is readily provided by the borrow checker.

source

pub fn pop(&mut self) -> Option<T>

Removes the last element from a vector and returns it, or None if it is empty.

Safety

pop operation for a ImpVec where the elements are T: NotSelfRefVecItem is safe; in this case, pinned vector shares the same safety requirements as std::vec::Vec which is readily provided by the borrow checker.

source§

impl<T, P> ImpVec<T, P>where P: PinnedVec<T>,

source

pub fn iter(&self) -> Iter<'_, T, P>

Returns an iterator for the imp-vec.

source

pub fn iter_mut(&mut self) -> IterMut<'_, T, P>

Returns a mutable iterator for the imp-vec.

source§

impl<T, P> ImpVec<T, P>where P: PinnedVec<T>,

source

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,

source

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;
source§

impl<'a, T, P> ImpVec<T, P>where P: PinnedVec<T> + 'a, T: SelfRefVecItem<'a> + 'a,

source

pub fn set_prev(&mut self, idx: usize, prev_idx: Option<usize>)

Sets the prev reference of the element at the idx to the element at the prev_idx.

If prev_idx.is none() the prev reference will be set to None.

Panics

Panics if idx is out of bounds; or if prev_idx.is_some() and the underlying id is out of bounds.

Safety

The call is trivially safe when prev_idx.is_none() since the optional reference is just set to None.

Otherwise, the method call is safe due to the following reasons:

  • Due to bounds-checks both the main element and the target element that the main element will hold a reference of belong to the vector; in other words, the main element will be holding a reference to another element in the same vector.
  • Since ImpVec wraps a PinnedVec, memory location of the target element cannot be change while the vector is growing.
  • The methods which can possibly change the memory location of the target element such as remove, pop, swap, truncate or insert are unsafe for PinnedVecs, and hence, for ImpVecs.
  • The only safe method which could change the memory location of the target element is clear method. This is safe since it would drop the main element at the same time together with its reference and target element.

Due to these guarantees, the built up inter-elements reference is and will remain valid.

source

pub fn set_next(&mut self, idx: usize, next_idx: Option<usize>)

Sets the next reference of the element at the idx to the element at the next_idx.

If next_idx.is none() the prev reference will be set to None.

Panics

Panics if idx is out of bounds; or if prev_idx.is_some() and the underlying id is out of bounds.

Safety

The call is trivially safe when next_idx.is_none() since the optional reference is just set to None.

Otherwise, the method call is safe due to the following reasons:

  • Due to bounds-checks both the main element and the target element that the main element will hold a reference of belong to the vector; in other words, the main element will be holding a reference to another element in the same vector.
  • Since ImpVec wraps a PinnedVec, memory location of the target element cannot be change while the vector is growing.
  • The methods which can possibly change the memory location of the target element such as remove, pop, swap, truncate or insert are unsafe for PinnedVecs, and hence, for ImpVecs.
  • The only safe method which could change the memory location of the target element is clear method. This is safe since it would drop the main element at the same time together with its reference and target element.

Due to these guarantees, the built up inter-elements reference is and will remain valid.

Trait Implementations§

source§

impl<T, P> Debug for ImpVec<T, P>where P: PinnedVec<T>, T: Debug,

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl<T, P> Default for ImpVec<T, P>where P: PinnedVec<T> + Default,

source§

fn default() -> Self

Returns the “default value” for a type. Read more
source§

impl<T, P> Deref for ImpVec<T, P>where P: PinnedVec<T>,

§

type Target = P

The resulting type after dereferencing.
source§

fn deref(&self) -> &Self::Target

Dereferences the value.
source§

impl<T, P> DerefMut for ImpVec<T, P>where P: PinnedVec<T>,

source§

fn deref_mut(&mut self) -> &mut Self::Target

Mutably dereferences the value.
source§

impl<T> From<ImpVec<T, FixedVec<T>>> for FixedVec<T>

source§

fn from(value: ImpVec<T, FixedVec<T>>) -> Self

Converts to this type from the input type.
source§

impl<T, P> From<ImpVec<T, P>> for RefCell<P>where P: PinnedVec<T>,

source§

fn from(value: ImpVec<T, P>) -> Self

Converts to this type from the input type.
source§

impl<T, G> From<ImpVec<T, SplitVec<T, G>>> for SplitVec<T, G>where G: Growth,

source§

fn from(value: ImpVec<T, SplitVec<T, G>>) -> Self

Converts to this type from the input type.
source§

impl<T, P> From<P> for ImpVec<T, P>where P: PinnedVec<T>,

source§

fn from(value: P) -> Self

Converts to this type from the input type.
source§

impl<T, P> Index<usize> for ImpVec<T, P>where P: PinnedVec<T>,

§

type Output = T

The returned type after indexing.
source§

fn index(&self, index: usize) -> &Self::Output

Performs the indexing (container[index]) operation. Read more
source§

impl<T, P> IndexMut<usize> for ImpVec<T, P>where P: PinnedVec<T>,

source§

fn index_mut(&mut self, index: usize) -> &mut Self::Output

Performs the mutable indexing (container[index]) operation. Read more
source§

impl<'a, T, P> IntoIterator for &'a ImpVec<T, P>where P: PinnedVec<T>,

§

type Item = &'a T

The type of the elements being iterated over.
§

type IntoIter = Iter<'a, T, P>

Which kind of iterator are we turning this into?
source§

fn into_iter(self) -> Self::IntoIter

Creates an iterator from a value. Read more
source§

impl<'a, T, P> IntoIterator for &'a mut ImpVec<T, P>where P: PinnedVec<T>,

§

type Item = &'a mut T

The type of the elements being iterated over.
§

type IntoIter = IterMut<'a, T, P>

Which kind of iterator are we turning this into?
source§

fn into_iter(self) -> Self::IntoIter

Creates an iterator from a value. Read more
source§

impl<T, P, const N: usize> PartialEq<ImpVec<T, P>> for [T; N]where P: PinnedVec<T>, T: PartialEq,

source§

fn eq(&self, other: &ImpVec<T, P>) -> bool

This method tests for self and other values to be equal, and is used by ==.
1.0.0 · source§

fn ne(&self, other: &Rhs) -> bool

This method tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
source§

impl<T, P, G> PartialEq<ImpVec<T, P>> for SplitVec<T, G>where P: PinnedVec<T>, T: PartialEq, G: Growth,

source§

fn eq(&self, other: &ImpVec<T, P>) -> bool

This method tests for self and other values to be equal, and is used by ==.
1.0.0 · source§

fn ne(&self, other: &Rhs) -> bool

This method tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
source§

impl<T, P> PartialEq<ImpVec<T, P>> for Vec<T>where P: PinnedVec<T>, T: PartialEq,

source§

fn eq(&self, other: &ImpVec<T, P>) -> bool

This method tests for self and other values to be equal, and is used by ==.
1.0.0 · source§

fn ne(&self, other: &Rhs) -> bool

This method tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
source§

impl<T, P1, P2> PartialEq<ImpVec<T, P2>> for ImpVec<T, P1>where P1: PinnedVec<T>, P2: PinnedVec<T>, T: PartialEq,

source§

fn eq(&self, other: &ImpVec<T, P2>) -> bool

This method tests for self and other values to be equal, and is used by ==.
1.0.0 · source§

fn ne(&self, other: &Rhs) -> bool

This method tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
source§

impl<T, P, S> PartialEq<S> for ImpVec<T, P>where P: PinnedVec<T>, S: AsRef<[T]>, T: PartialEq,

source§

fn eq(&self, other: &S) -> bool

This method tests for self and other values to be equal, and is used by ==.
1.0.0 · source§

fn ne(&self, other: &Rhs) -> bool

This method tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
source§

impl<T, P> Eq for ImpVec<T, P>where P: PinnedVec<T>, T: PartialEq,

Auto Trait Implementations§

§

impl<T, P = SplitVec<T, Doubling>> !RefUnwindSafe for ImpVec<T, P>

§

impl<T, P> Send for ImpVec<T, P>where P: Send, T: Send,

§

impl<T, P = SplitVec<T, Doubling>> !Sync for ImpVec<T, P>

§

impl<T, P> Unpin for ImpVec<T, P>where P: Unpin, T: Unpin,

§

impl<T, P> UnwindSafe for ImpVec<T, P>where P: UnwindSafe, T: UnwindSafe,

Blanket Implementations§

source§

impl<T> Any for Twhere T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for Twhere T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for Twhere T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<!> for T

source§

fn from(t: !) -> T

Converts to this type from the input type.
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

source§

impl<T, U> Into<U> for Twhere U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

source§

impl<T, U> TryFrom<U> for Twhere U: Into<T>,

§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for Twhere U: TryFrom<T>,

§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.