Skip to main content

ImpVec

Struct ImpVec 

Source
pub struct ImpVec<T, P, S>
where P: PinnedVec<T>, S: SoM<P>,
{ /* private fields */ }
Expand description

ImpVec, stands for immutable push vector 👿, is a data structure which allows appending elements with a shared reference.

Specifically, it extends vector capabilities with the following three methods:

  • fn imp_push(&self, value: T)
  • fn imp_extend_from_slice(&self, slice: &[T])
  • fn imp_push_get_ref(&self, value: T) -> &T

Note that both of these methods can be called with &self rather than &mut self. This is safe since growth does not cause memory locations of existing elements of pinned vectors.

§Examples

A common use case is when we want to iterate over existing elements, and add new elements to the same vector.

The following code does not compile:

ⓘ
fn add_doubles_of_evens(vec: &mut Vec<u32>) {
    for i in vec.iter().copied() {
        if i.is_multiple_of(2) {
            let doubled = 2 * i;
            vec.push(doubled); // cannot borrow `*vec` as mutable because it is also borrowed as immutable
        }
    }
}

let mut vec = vec![9, 10, 11];

add_doubles_of_evens(&mut vec);

assert_eq!(&vec, &[9, 10, 11, 20]);

However, this would safely work with a pinned vector. SplitVec is one pinned vector implementation, see orx-split-vec crate for details.

ⓘ
use orx_pinned_vec::*;

fn add_doubles_of_evens(vec: &mut SplitVec<u32>) {
    let vec = vec.as_imp_vec();
    for i in vec.iter().copied() {
        if i.is_multiple_of(2) {
            let doubled = 2 * i;
            vec.imp_push(doubled);
        }
    }
}

let mut vec = SplitVec::new();
vec.extend_from_slice(&[9, 10, 11]);

add_doubles_of_evens(&mut vec);

assert_eq!(&vec, &[9, 10, 11, 20]);

Implementations§

Source§

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

Source

pub fn into_inner(self) -> S

Returns back the inner pinned vector that this ImpVec is created from.

Source

pub fn imp_push(&self, value: T)

Pushes the value to the vector. This method differs from the push method with the required reference. Unlike push, imp_push allows to push the element with a shared reference.

§Example
ⓘ
use pinned_vec::*;

let mut split_vec = SplitVec::new();

let mut vec = split_vec.as_imp_vec();

// regular push with &mut self
vec.push(42);

// hold on to a reference to the first element
let ref_to_first = &vec[0];
assert_eq!(ref_to_first, &42);

// imp_push with &self
vec.imp_push(7);

// due to `PinnedVec` guarantees, this push will never invalidate prior references
assert_eq!(ref_to_first, &42);
Source

pub fn imp_push_get_ref(&self, value: T) -> &T

Pushes the value to the vector and returns a reference to it.

It is the composition of vec.imp_push(value) call followed by &vec[vec.len() - 1].

§Examples

This method provides a shorthand for the following common use case.

ⓘ
use pinned_vec::*;

let mut split_vec = SplitVec::new();

let mut vec = split_vec.as_imp_vec();

vec.imp_push('a');
let a = &vec[vec.len() - 1];
assert_eq!(a, &'a');

// or with imp_push_get_ref

let b = vec.imp_push_get_ref('b');
assert_eq!(b, &'b');
Source

pub fn imp_extend_from_slice(&self, slice: &[T])
where T: Clone,

Extends the vector with the given slice. This method differs from the extend_from_slice method with the required reference. Unlike extend_from_slice, imp_extend_from_slice allows to push the element with a shared reference.

§Example
ⓘ
use pinned_vec::*;

let mut split_vec = SplitVec::new();

// regular extend_from_slice with &mut self
vec.extend_from_slice(&[42]);

// hold on to a reference to the first element
let ref_to_first = &vec[0];
assert_eq!(ref_to_first, &42);

// imp_extend_from_slice with &self
vec.imp_extend_from_slice(&[0, 1, 2, 3]);
assert_eq!(vec.len(), 5);

// due to `PinnedVec` guarantees, this extend will never invalidate prior references
assert_eq!(ref_to_first, &42);

Trait Implementations§

Source§

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

Source§

type Target = P

The resulting type after dereferencing.
Source§

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

Dereferences the value.
Source§

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

Source§

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

Mutably dereferences the value.

Auto Trait Implementations§

§

impl<T, P, S> !Freeze for ImpVec<T, P, S>

§

impl<T, P, S> !RefUnwindSafe for ImpVec<T, P, S>

§

impl<T, P, S> !Sync for ImpVec<T, P, S>

§

impl<T, P, S> Send for ImpVec<T, P, S>

§

impl<T, P, S> Unpin for ImpVec<T, P, S>

§

impl<T, P, S> UnsafeUnpin for ImpVec<T, P, S>

§

impl<T, P, S> UnwindSafe for ImpVec<T, P, S>

Blanket Implementations§

Source§

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

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

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

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

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

Source§

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

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where 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<P, T> Receiver for P
where P: Deref<Target = T> + ?Sized, T: ?Sized,

Source§

type Target = T

🔬This is a nightly-only experimental API. (arbitrary_self_types)
The target type on which the method may be called.
Source§

impl<T> SoM<T> for T

Source§

fn get_ref(&self) -> &T

Returns a reference to self.
Source§

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

Returns a mutable reference to self.
Source§

impl<T> SoR<T> for T

Source§

fn get_ref(&self) -> &T

Returns a reference to self.
Source§

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

Source§

type Error = !

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

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

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

Source§

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.