Struct orx_split_vec::SplitVec
source · pub struct SplitVec<T> {
pub growth: FragmentGrowth,
/* private fields */
}Expand description
A split vector; i.e., a vector of fragments.
Fields§
§growth: FragmentGrowthFragment growth strategy of the split vector.
Implementations§
source§impl<T> SplitVec<T>
impl<T> SplitVec<T>
sourcepub fn to_vec(self) -> Vec<T>
pub fn to_vec(self) -> Vec<T>
Converts the SplitVec into a standard Vec with a contagious memory layout.
Examples
use orx_split_vec::{FragmentGrowth, SplitVec};
let mut split_vec = SplitVec::with_growth(FragmentGrowth::constant(4));
split_vec.extend_from_slice(&['a', 'b', 'c']);
assert_eq!(1, split_vec.fragments().len());
let vec = split_vec.to_vec(); // no mem-copies
assert_eq!(vec, &['a', 'b', 'c']);
let mut split_vec = SplitVec::with_growth(FragmentGrowth::constant(4));
for i in 0..10 {
split_vec.push(i);
}
assert_eq!(&[0, 1, 2, 3], split_vec.fragments()[0].as_slice());
assert_eq!(&[4, 5, 6, 7], split_vec.fragments()[1].as_slice());
assert_eq!(&[8, 9], split_vec.fragments()[2].as_slice());
let vec = split_vec.to_vec();
assert_eq!(&[0, 1, 2, 3, 4, 5, 6, 7, 8, 9], vec.as_slice());source§impl<T: Clone> SplitVec<T>
impl<T: Clone> SplitVec<T>
sourcepub fn extend_from_slice(&mut self, other: &[T])
pub fn extend_from_slice(&mut self, other: &[T])
Clones and appends all elements in a slice to the vec.
Iterates over the slice other, clones each element, and then appends
it to this vector. The other slice is traversed in-order.
Examples
use orx_split_vec::SplitVec;
let mut vec = SplitVec::default();
vec.push(1);
vec.push(2);
vec.push(3);
assert_eq!(vec, [1, 2, 3]);
vec.extend_from_slice(&[4, 5, 6, 7]);
assert_eq!(vec, [1, 2, 3, 4, 5, 6, 7]);source§impl<T> SplitVec<T>
impl<T> SplitVec<T>
sourcepub fn push(&mut self, value: T)
pub fn push(&mut self, value: T)
Appends an element to the back of a collection.
Examples
use orx_split_vec::SplitVec;
let mut vec = SplitVec::default();
vec.push(1);
vec.push(2);
vec.push(3);
assert_eq!(vec, [1, 2, 3]);sourcepub fn insert(&mut self, index: usize, value: T)
pub fn insert(&mut self, index: usize, value: T)
Inserts an element at position index within the vector, shifting all
elements after it to the right.
Panics
Panics if index > len.
Examples
use orx_split_vec::SplitVec;
let mut vec = SplitVec::default();
vec.push(1);
vec.push(2);
vec.push(3);
vec.insert(1, 4);
assert_eq!(vec, [1, 4, 2, 3]);
vec.insert(4, 5);
assert_eq!(vec, [1, 4, 2, 3, 5]);sourcepub fn remove(&mut self, index: usize) -> T
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.
Note: Because this shifts over the remaining elements, it has a worst-case performance of O(n).
Panics
Panics if index is out of bounds.
Examples
use orx_split_vec::SplitVec;
let mut vec = SplitVec::default();
vec.push(1);
vec.push(2);
vec.push(3);
vec.push(4);
vec.push(5);
assert_eq!(vec.remove(1), 2);
assert_eq!(vec, [1, 3, 4, 5]);
assert_eq!(vec.remove(2), 4);
assert_eq!(vec, [1, 3, 5]);source§impl<T> SplitVec<T>
impl<T> SplitVec<T>
sourcepub fn try_get_slice(&self, range: Range<usize>) -> SplitVecSlice<'_, T>
pub fn try_get_slice(&self, range: Range<usize>) -> SplitVecSlice<'_, T>
Returns the result of trying to return the required range as a contagious slice of data.
It might return Ok of the slice if the range belongs to one fragment.
Otherwise, one of the two failure cases will be returned:
- OutOfBounds if the range does not fit in the range of the entire split vector, or
- Fragmented if the range belongs to at least two fragments, additionally returns the fragment indices of the range.
Examples
use orx_split_vec::{FragmentGrowth, SplitVec, SplitVecSlice};
let growth = FragmentGrowth::constant(4);
let mut vec = SplitVec::with_growth(growth);
vec.extend_from_slice(&[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]);
assert_eq!(4, vec.fragments()[0].capacity());
assert_eq!(4, vec.fragments()[1].capacity());
assert_eq!(4, vec.fragments()[2].capacity());
assert_eq!(4, vec.fragments()[0].len()); // [0, 1, 2, 3]
assert_eq!(4, vec.fragments()[1].len()); // [4, 5, 6, 7]
assert_eq!(2, vec.fragments()[2].len()); // [8, 9]
// Ok
assert_eq!(SplitVecSlice::Ok(&[0, 1, 2, 3]), vec.try_get_slice(0..4));
assert_eq!(SplitVecSlice::Ok(&[5, 6]), vec.try_get_slice(5..7));
assert_eq!(SplitVecSlice::Ok(&[8, 9]), vec.try_get_slice(8..10));
// Fragmented
assert_eq!(SplitVecSlice::Fragmented(0, 1), vec.try_get_slice(3..6));
assert_eq!(SplitVecSlice::Fragmented(0, 2), vec.try_get_slice(3..9));
assert_eq!(SplitVecSlice::Fragmented(1, 2), vec.try_get_slice(7..9));
// OutOfBounds
assert_eq!(SplitVecSlice::OutOfBounds, vec.try_get_slice(5..12));
assert_eq!(SplitVecSlice::OutOfBounds, vec.try_get_slice(10..11));sourcepub fn slice(&self, range: Range<usize>) -> Vec<&[T]>
pub fn slice(&self, range: Range<usize>) -> Vec<&[T]>
Returns the view on the required range as a vector of slices:
- returns an empty vector if the range is out of bounds;
- returns a vector with one slice if the range completely belongs to one fragment (in this case
try_get_slicewould return Ok), - returns an ordered vector of slices when chained forms the required range.
Examples
use orx_split_vec::{FragmentGrowth, SplitVec, SplitVecSlice};
let growth = FragmentGrowth::constant(4);
let mut vec = SplitVec::with_growth(growth);
vec.extend_from_slice(&[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]);
assert_eq!(4, vec.fragments()[0].capacity());
assert_eq!(4, vec.fragments()[1].capacity());
assert_eq!(4, vec.fragments()[2].capacity());
assert_eq!(4, vec.fragments()[0].len()); // [0, 1, 2, 3]
assert_eq!(4, vec.fragments()[1].len()); // [4, 5, 6, 7]
assert_eq!(2, vec.fragments()[2].len()); // [8, 9]
// single fragment
assert_eq!(vec![&[0, 1, 2, 3]], vec.slice(0..4));
assert_eq!(vec![&[5, 6]], vec.slice(5..7));
assert_eq!(vec![&[8, 9]], vec.slice(8..10));
// Fragmented
assert_eq!(vec![&vec![3], &vec![4, 5]], vec.slice(3..6));
assert_eq!(vec![&vec![3], &vec![4, 5, 6, 7], &vec![8]], vec.slice(3..9));
assert_eq!(vec![&vec![7], &vec![8]], vec.slice(7..9));
// OutOfBounds
assert!(vec.slice(5..12).is_empty());
assert!(vec.slice(10..11).is_empty());source§impl<T> SplitVec<T>
impl<T> SplitVec<T>
sourcepub fn with_growth(growth: FragmentGrowth) -> Self
pub fn with_growth(growth: FragmentGrowth) -> Self
Creates an empty split vector with the given growth strategy.
sourcepub unsafe fn fragments_mut(&mut self) -> &mut Vec<Fragment<T>>
pub unsafe fn fragments_mut(&mut self) -> &mut Vec<Fragment<T>>
Returns a mutable reference to the vector of fragments.
Safety
Fragments of the split vector maintain the following structure:
- the fragments vector is never empty, it has at least one fragment;
- all fragments have a positive capacity;
- capacity of fragment f is equal to
self.growth.get_capacity(f).
- capacity of fragment f is equal to
- if there exist F fragments in the vector:
- none of the fragments with indices
0..F-2has capacity; i.e., len==capacity, - the last fragment at position
F-1might or might not have capacity.
- none of the fragments with indices
Breaking this structure invalidates the SplitVec struct,
and its methods lead to UB.
sourcepub fn fragments(&self) -> &[Fragment<T>]
pub fn fragments(&self) -> &[Fragment<T>]
Returns the fragments of the split vector.
The fragments of the split vector satisfy the following structure:
- the fragments vector is never empty, it has at least one fragment;
- all fragments have a positive capacity;
- capacity of fragment f is equal to
self.growth.get_capacity(f).
- capacity of fragment f is equal to
- if there exist F fragments in the vector:
- none of the fragments with indices
0..F-2has capacity; i.e., len==capacity, - the last fragment at position
F-1might or might not have capacity.
- none of the fragments with indices
sourcepub fn last_fragment(&self) -> &Fragment<T>
pub fn last_fragment(&self) -> &Fragment<T>
Returns a reference to the last fragment of the split vector.
source§impl<T> SplitVec<T>
impl<T> SplitVec<T>
sourcepub fn len(&self) -> usize
pub fn len(&self) -> usize
Returns the number of elements in the vector, also referred to as its ‘length’.
Examples
use orx_split_vec::SplitVec;
let mut vec = SplitVec::default();
assert_eq!(0, vec.len());
vec.push(1);
vec.push(2);
vec.push(3);
assert_eq!(3, vec.len());sourcepub fn is_empty(&self) -> bool
pub fn is_empty(&self) -> bool
Returns true if the vector contains no elements.
Examples
use orx_split_vec::SplitVec;
let mut vec = SplitVec::default();
assert!(vec.is_empty());
vec.push(1);
assert!(!vec.is_empty());sourcepub fn capacity(&self) -> usize
pub fn capacity(&self) -> usize
Returns the total number of elements the split vector can hold without reallocating.
See FragmentGrowth for details of capacity growth policies.
Examples
use orx_split_vec::SplitVec;
// default growth starting with 4, and doubling at each new fragment.
let mut vec = SplitVec::<usize>::default();
assert_eq!(4, vec.capacity());
for i in 0..4 {
vec.push(i);
}
assert_eq!(4, vec.capacity());
vec.push(4);
assert_eq!(4 + 6, vec.capacity());
// second fragment will have capacity 4*1.5 by default growth
// see `FragmentGrowth` for different growth strategies.
sourcepub fn get(&self, index: usize) -> Option<&T>
pub fn get(&self, index: usize) -> Option<&T>
Returns a reference to the element with the given index;
None if index is out of bounds.
Examples
use orx_split_vec::SplitVec;
let mut vec = SplitVec::<usize>::default();
vec.extend_from_slice(&[10, 40, 30]);
assert_eq!(Some(&40), vec.get(1));
assert_eq!(None, vec.get(3));sourcepub fn get_mut(&mut self, index: usize) -> Option<&mut T>
pub fn get_mut(&mut self, index: usize) -> Option<&mut T>
Returns a mutable reference to the element with the given index;
None if index is out of bounds.
Examples
use orx_split_vec::SplitVec;
let mut vec = SplitVec::<usize>::default();
vec.extend_from_slice(&[0, 1, 2]);
if let Some(elem) = vec.get_mut(1) {
*elem = 42;
}
assert_eq!(vec, &[0, 42, 2]);sourcepub fn append<F>(&mut self, fragment: F)where
F: Into<Fragment<T>>,
pub fn append<F>(&mut self, fragment: F)where F: Into<Fragment<T>>,
Directly appends the fragment to the end of the split vector.
This operation does not require any copies or allocation; the fragment is moved into the split vector and added as a new fragment, without copying the underlying data.
Examples
use orx_split_vec::SplitVec;
let mut vec = SplitVec::<usize>::default();
// append to empty split vector
assert!(vec.is_empty());
let mut other = Vec::with_capacity(4);
other.extend_from_slice(&[0, 1, 2]);
vec.append(other);
assert_eq!(vec, &[0, 1, 2]);
assert_eq!(1, vec.fragments().len());
assert_eq!(4, vec.fragments()[0].capacity()); // SplitVec will make use of the appended vector's additional capacity
vec.push(3);
assert_eq!(vec, &[0, 1, 2, 3]);
assert_eq!(1, vec.fragments().len());
assert_eq!(vec.fragments()[0].as_slice(), &[0, 1, 2, 3]);
// next push will use SplitVec's growth
vec.extend_from_slice(&[4, 5, 6]);
assert_eq!(vec, &[0, 1, 2, 3, 4, 5, 6]);
assert_eq!(2, vec.fragments().len());
assert_eq!(vec.fragments()[0].as_slice(), &[0, 1, 2, 3]);
assert_eq!(vec.fragments()[1].as_slice(), &[4, 5, 6]);
// we can append another fragment directly
vec.append(vec![7, 8]);
assert_eq!(vec, &[0, 1, 2, 3, 4, 5, 6, 7, 8]);
assert_eq!(3, vec.fragments().len());
assert_eq!(vec.fragments()[0].as_slice(), &[0, 1, 2, 3]);
assert_eq!(vec.fragments()[1].as_slice(), &[4, 5, 6]);
assert_eq!(vec.fragments()[2].as_slice(), &[7, 8]);Trait Implementations§
source§impl<'a, T: Clone + 'a> Extend<&'a T> for SplitVec<T>
impl<'a, T: Clone + 'a> Extend<&'a T> for SplitVec<T>
source§fn extend<I: IntoIterator<Item = &'a T>>(&mut self, iter: I)
fn extend<I: IntoIterator<Item = &'a T>>(&mut self, iter: I)
Clones and appends all elements in the iterator to the vec.
Iterates over the iter, clones each element, and then appends
it to this vector.
Examples
use orx_split_vec::SplitVec;
let mut vec = SplitVec::default();
vec.push(1);
vec.push(2);
vec.push(3);
assert_eq!(vec, [1, 2, 3]);
vec.extend(&[4, 5, 6, 7]);
assert_eq!(vec, [1, 2, 3, 4, 5, 6, 7]);
let mut sec_vec = SplitVec::default();
sec_vec.extend(vec.into_iter());
assert_eq!(sec_vec, [1, 2, 3, 4, 5, 6, 7]);source§fn extend_one(&mut self, item: A)
fn extend_one(&mut self, item: A)
extend_one)source§fn extend_reserve(&mut self, additional: usize)
fn extend_reserve(&mut self, additional: usize)
extend_one)source§impl<T> Extend<T> for SplitVec<T>
impl<T> Extend<T> for SplitVec<T>
source§fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I)
fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I)
Extends a collection with the contents of an iterator.
Iterates over the iter, moves and appends each element
to this vector.
Examples
use orx_split_vec::SplitVec;
let mut vec = SplitVec::default();
vec.push(1);
vec.push(2);
vec.push(3);
assert_eq!(vec, [1, 2, 3]);
vec.extend(vec![4, 5, 6, 7].into_iter());
assert_eq!(vec, [1, 2, 3, 4, 5, 6, 7]);source§fn extend_one(&mut self, item: A)
fn extend_one(&mut self, item: A)
extend_one)source§fn extend_reserve(&mut self, additional: usize)
fn extend_reserve(&mut self, additional: usize)
extend_one)source§impl<'a, T> From<&'a SplitVec<T>> for SplitVecIterator<'a, T>
impl<'a, T> From<&'a SplitVec<T>> for SplitVecIterator<'a, T>
source§impl<T> From<SplitVec<T>> for Vec<T>
impl<T> From<SplitVec<T>> for Vec<T>
source§fn from(value: SplitVec<T>) -> Self
fn from(value: SplitVec<T>) -> Self
Converts the SplitVec into a standard Vec with a contagious memory layout.
Examples
use orx_split_vec::{FragmentGrowth, SplitVec};
let mut split_vec = SplitVec::with_growth(FragmentGrowth::constant(4));
split_vec.extend_from_slice(&['a', 'b', 'c']);
assert_eq!(1, split_vec.fragments().len());
let vec: Vec<_> = split_vec.into(); // no mem-copies
assert_eq!(vec, &['a', 'b', 'c']);
let mut split_vec = SplitVec::with_growth(FragmentGrowth::constant(4));
for i in 0..10 {
split_vec.push(i);
}
assert_eq!(&[0, 1, 2, 3], split_vec.fragments()[0].as_slice());
assert_eq!(&[4, 5, 6, 7], split_vec.fragments()[1].as_slice());
assert_eq!(&[8, 9], split_vec.fragments()[2].as_slice());
let vec: Vec<_> = split_vec.into();
assert_eq!(&[0, 1, 2, 3, 4, 5, 6, 7, 8, 9], vec.as_slice());source§impl<T> From<Vec<T, Global>> for SplitVec<T>
impl<T> From<Vec<T, Global>> for SplitVec<T>
source§fn from(value: Vec<T>) -> Self
fn from(value: Vec<T>) -> Self
Converts a Vec into a SplitVec by
moving the vector into the split vector as the first fragment,
without copying the data.
Examples
use orx_split_vec::SplitVec;
let vec = vec!['a', 'b', 'c'];
let vec_capacity = vec.capacity();
let split_vec: SplitVec<_> = vec.into();
assert_eq!(split_vec, &['a', 'b', 'c']);
assert_eq!(1, split_vec.fragments().len());
assert_eq!(vec_capacity, split_vec.fragments()[0].capacity());source§impl<T> Index<(usize, usize)> for SplitVec<T>
impl<T> Index<(usize, usize)> for SplitVec<T>
source§fn index(&self, fragment_and_inner_index: (usize, usize)) -> &Self::Output
fn index(&self, fragment_and_inner_index: (usize, usize)) -> &Self::Output
One can treat the split vector as a jagged array and access an item with (fragment_index, inner_fragment_index) if these numbers are known.
Panics
Panics if:
fragment_and_inner_index.0is not a valid fragment index; i.e., not within0..self.fragments().len(), orfragment_and_inner_index.1is not a valid index for the corresponding fragment; i.e., not within0..self.fragments()[fragment_and_inner_index.0].len().
Examples
Assume that we create a split vector with a constant growth of N elements. This means that each fraction will have a capacity and max-length of N.
Then, the fragment and inner index of the element with index i can be computed as
(i / N, i % N).
use orx_split_vec::{FragmentGrowth, SplitVec};
let growth = FragmentGrowth::constant(4);
let mut vec = SplitVec::with_growth(growth);
for i in 0..10 {
vec.push(i);
}
// layout of the data will be as follows:
// fragment-0: [0, 1, 2, 3]
// fragment-1: [4, 5, 6, 7]
// fragment-2: [8, 9]
assert_eq!(1, vec[(0, 1)]);
assert_eq!(7, vec[(1, 3)]);
assert_eq!(8, vec[(2, 0)]);
// since we know the layout, we can define the index transformer for direct access
fn fragment_and_inner_idx(index: usize) -> (usize, usize) {
(index / 4, index % 4)
}
for index in 0..vec.len() {
let split_access = &vec[index];
let direct_access = &vec[fragment_and_inner_idx(index)];
assert_eq!(split_access, direct_access);
}
source§impl<T> IndexMut<(usize, usize)> for SplitVec<T>
impl<T> IndexMut<(usize, usize)> for SplitVec<T>
source§fn index_mut(
&mut self,
fragment_and_inner_index: (usize, usize)
) -> &mut Self::Output
fn index_mut( &mut self, fragment_and_inner_index: (usize, usize) ) -> &mut Self::Output
One can treat the split vector as a jagged array and access an item with (fragment_index, inner_fragment_index) if these numbers are known.
Panics
Panics if:
fragment_and_inner_index.0is not a valid fragment index; i.e., not within0..self.fragments().len(), orfragment_and_inner_index.1is not a valid index for the corresponding fragment; i.e., not within0..self.fragments()[fragment_and_inner_index.0].len().
Examples
Assume that we create a split vector with a constant growth of N elements. This means that each fraction will have a capacity and max-length of N.
Then, the fragment and inner index of the element with index i can be computed as
(i / N, i % N).
use orx_split_vec::{FragmentGrowth, SplitVec};
let growth = FragmentGrowth::constant(4);
let mut vec = SplitVec::with_growth(growth);
for i in 0..10 {
vec.push(i);
}
// layout of the data will be as follows:
// fragment-0: [0, 1, 2, 3]
// fragment-1: [4, 5, 6, 7]
// fragment-2: [8, 9]
vec[(0, 1)] += 100; // 1 -> 101
vec[(1, 3)] += 100; // 7 -> 107
vec[(2, 0)] += 100; // 8 -> 108
assert_eq!(vec, &[0, 101, 2, 3, 4, 5, 6, 107, 108, 9]);
// since we know the layout, we can define the index transformer for direct access
fn fragment_and_inner_idx(index: usize) -> (usize, usize) {
(index / 4, index % 4)
}
for index in 0..vec.len() {
let direct_access = &mut vec[fragment_and_inner_idx(index)];
if *direct_access < 100 {
*direct_access += 100;
}
}
assert_eq!(vec, &[100, 101, 102, 103, 104, 105, 106, 107, 108, 109]);
source§impl<T> IndexMut<usize> for SplitVec<T>
impl<T> IndexMut<usize> for SplitVec<T>
source§fn index_mut(&mut self, index: usize) -> &mut Self::Output
fn index_mut(&mut self, index: usize) -> &mut Self::Output
Returns a mutable reference to the index-th item of the vector.
Panics
Panics if index is out of bounds.
Examples
use orx_split_vec::SplitVec;
let mut vec = SplitVec::default();
vec.extend_from_slice(&[0, 1, 2, 3]);
let item2 = &mut vec[2];
*item2 = 42;
assert_eq!(vec, &[0, 1, 42, 3]);
// let x = &mut vec[4]; // panics!