pub struct SegVec<T, C: MemConfig = Exponential<1>> { /* private fields */ }
Expand description
A data structure similar to Vec
, but that does not copy on re-size and can
release memory when it is truncated.
Capacity is allocated in “segments”. A empty SegVec
of capacity 0 does not allocate.
Allocating new segments is controlled by a MemConfig
policy. Segvec comes with three
predefined implementations. These implementations take an non-zero parameter which defines
the minimum number of elements in a segment, all segments are multiples of this ‘FACTOR’.
This FACTOR
should ideally be a power of two as this optimizes to much more efficient code.
Linear<FACTOR>
All segments have the same size. This is the fastest whenFACTOR
is big enough. Consequently there is some memory overhead when only very few elements are stored. When aSegVec
grows it will have the least memory overhead. When not given thenFACTOR
defaults to 1024.Proportional<FACTOR>
Segments grow proportionally to their segment number[FACTOR, 2*FACTOR, 3*FACTOR, ..]
. Unfortunately the math is somewhat expensive which makes this slow.Exponential<FACTOR>
Segments grow exponentially to their segment number, each subsequent segment is as large as the size of all preceeding segments[FACTOR, FACTOR, 2*FACTOR, 4*FACTOR, 8*FACTOR, ..]
.Exponential
is slightly wasteful with memory (up to 50% might be unused in the worst case). When not given thenFACTOR
defaults to 16.
The default MemConfig
is Exponential<1>
which should work for most cases, especially when
very few elements are frequently expected.
Altogether you get these three defaults:
SegVec<T>
Use it when very few elements (less than 10) are frequently expected.SegVec<T, Exponential>
Good compromise when the expected number of elements can vary widely.SegVec<T, Linear>
The fastest. But wastes memory when only few elements are expected (<500).
Implementations§
source§impl<T, C: MemConfig> SegVec<T, C>
impl<T, C: MemConfig> SegVec<T, C>
sourcepub fn new() -> Self
pub fn new() -> Self
Create a new SegVec
with a length and capacity of 0.
let mut v: SegVec<i32> = SegVec::new();
assert_eq!(v.capacity(), 0);
v.reserve(1);
assert_eq!(v.capacity(), 1);
sourcepub fn with_capacity(capacity_hint: usize) -> Self
pub fn with_capacity(capacity_hint: usize) -> Self
sourcepub fn len(&self) -> usize
pub fn len(&self) -> usize
The number of elements in the SegVec
let mut v: SegVec<i32> = SegVec::new();
v.push(1);
v.push(2);
assert_eq!(v.len(), 2);
sourcepub fn is_empty(&self) -> bool
pub fn is_empty(&self) -> bool
Returns true
if the SegVec
contains no elements.
let mut v: SegVec<i32> = SegVec::with_capacity(10);
assert!(v.is_empty());
v.push(1);
assert!(!v.is_empty());
sourcepub fn capacity(&self) -> usize
pub fn capacity(&self) -> usize
The capacity of the SegVec
let mut v: SegVec<i32> = SegVec::with_capacity(3);
assert_eq!(v.capacity(), 4);
sourcepub fn reserve(&mut self, additional: usize)
pub fn reserve(&mut self, additional: usize)
Reserve enough capacity to insert the given number of elements into the
SegVec
without allocating. If the capacity is already sufficient,
nothing happens.
let mut v: SegVec<i32> = SegVec::new();
assert_eq!(v.capacity(), 0);
v.reserve(3);
assert_eq!(v.capacity(), 4);
Panics
- If the required capacity overflows
usize
sourcepub fn get(&self, index: usize) -> Option<&T>
pub fn get(&self, index: usize) -> Option<&T>
Returns a reference to the data at the given index in the SegVec
, if it
exists.
let mut v: SegVec<i32> = SegVec::new();
assert_eq!(v.get(0), None);
v.push(1);
assert_eq!(*v.get(0).unwrap(), 1);
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 data at the given index in the SegVec
,
if it exists.
let mut v: SegVec<i32> = SegVec::new();
assert_eq!(v.get_mut(0), None);
v.push(1);
assert_eq!(*v.get_mut(0).unwrap(), 1);
sourcepub fn pop(&mut self) -> Option<T>
pub fn pop(&mut self) -> Option<T>
Removes the last value from the SegVec
and returns it, or returns None
if it is empty.
let mut v: SegVec<i32> = SegVec::new();
v.push(1);
assert_eq!(v.pop().unwrap(), 1);
sourcepub fn truncate(&mut self, len: usize)
pub fn truncate(&mut self, len: usize)
Truncates the SegVec
to the given length.
If the given length is larger than the current length, this is a no-op.
Otherwise, the capacity is reduced and any excess elements are dropped.
let mut v: SegVec<i32> = SegVec::new();
v.push(1);
v.push(2);
v.push(3);
assert_eq!(v.len(), 3);
assert!(v.capacity() >= 3);
v.truncate(1);
assert_eq!(v.len(), 1);
sourcepub fn resize_with<F>(&mut self, new_len: usize, f: F)where
F: FnMut() -> T,
pub fn resize_with<F>(&mut self, new_len: usize, f: F)where F: FnMut() -> T,
Resizes the SegVec
so that the length is equal to new_len
.
If new_len
is greater than len
, the SegVec
is extended by the difference, with
each additional slot filled with the result of calling the closure f
. The return
values from f
will end up in the SegVec
in the order they have been generated. If
new_len
is less than len
, the SegVec
is simply truncated. If new_len
is equal
to len
, this is a no-op.
let mut v: SegVec<i32> = SegVec::new();
let mut counter = 0i32;
v.resize_with(4, || { counter += 1; counter });
assert_eq!(counter, 4);
assert_eq!(v.len(), 4);
assert_eq!(v.pop().unwrap(), 4);
sourcepub fn resize(&mut self, new_len: usize, val: T)where
T: Clone,
pub fn resize(&mut self, new_len: usize, val: T)where T: Clone,
Resizes the SegVec
so that the length is equal to new_len
.
If new_len
is greater than len
, the SegVec
is extended by the difference, with each additional slot filled with the result of calling the clone
on val
.
The cloned values will end up in the SegVec
in the order they have been generated.
If new_len
is less than len
, the SegVec
is simply truncated.
If new_len
is equal to len
, this is a no-op.
let mut v: SegVec<i32> = SegVec::new();
v.resize(4, 100);
assert_eq!(v.len(), 4);
assert_eq!(v.pop().unwrap(), 100);
sourcepub fn iter(&self) -> Iter<'_, T> ⓘ
pub fn iter(&self) -> Iter<'_, T> ⓘ
Returns an iterator over immutable references to the elements in the
SegVec
.
let mut v: SegVec<i32> = SegVec::new();
v.push(1);
v.push(2);
v.push(3);
let mut i = v.iter();
assert_eq!(*i.next().unwrap(), 1);
assert_eq!(*i.next().unwrap(), 2);
assert_eq!(*i.next().unwrap(), 3);
assert_eq!(i.next(), None);
sourcepub fn insert(&mut self, index: usize, val: T)
pub fn insert(&mut self, index: usize, val: T)
Insert the given value at the given index in the SegVec
.
This operation requires O(N)
time due to the fact that the data is segmented -
the new element is pushed onto the end and then shifted backwards into position.
let mut v: SegVec<i32> = SegVec::new();
v.push(1);
v.push(2);
v.insert(0, 100);
assert_eq!(v[0], 100);
Panics
- If the given index is greater than
self.len()
- If the required capacity overflows
usize
sourcepub fn remove(&mut self, index: usize) -> T
pub fn remove(&mut self, index: usize) -> T
Removes the value at the given index in the SegVec
and returns it.
This operation requires O(N)
time due to the fact that the data is segmented -
the element is shifted to the end and then popped.
let mut v: SegVec<i32> = SegVec::new();
v.push(1);
v.push(2);
assert_eq!(v.remove(1), 2);
assert_eq!(v.len(), 1);
Panics
- If the given index is greater than or equal to
self.len()
sourcepub fn drain<R>(&mut self, range: R) -> Drain<'_, T, C> ⓘwhere
R: RangeBounds<usize>,
pub fn drain<R>(&mut self, range: R) -> Drain<'_, T, C> ⓘwhere R: RangeBounds<usize>,
Returns an iterator that removes and returns values from within the given range of the
SegVec
. See Drain
for more information.
let mut v: SegVec<i32> = SegVec::new();
v.push(1);
v.push(2);
v.drain(..).for_each(|v| println!("{}", v));
assert_eq!(v.len(), 0);
Panics
- If the end index is greater than
self.len()
- If the start index is greater than the end index.
sourcepub fn slice<R>(&self, range: R) -> Slice<'_, T>where
R: RangeBounds<usize>,
pub fn slice<R>(&self, range: R) -> Slice<'_, T>where R: RangeBounds<usize>,
sourcepub fn slice_mut<R>(&mut self, range: R) -> SliceMut<'_, T>where
R: RangeBounds<usize>,
pub fn slice_mut<R>(&mut self, range: R) -> SliceMut<'_, T>where R: RangeBounds<usize>,
sourcepub fn reverse(&mut self)
pub fn reverse(&mut self)
Reverses the elements in the SegVec
.
let mut v: SegVec<i32> = SegVec::new();
v.push(1);
v.push(2);
v.push(3);
v.push(4);
v.push(5);
v.push(6);
v.reverse();
assert_eq!(v.into_iter().collect::<Vec<_>>(), vec![6, 5, 4, 3, 2, 1]);
sourcepub fn sort_unstable(&mut self)where
T: Ord,
pub fn sort_unstable(&mut self)where T: Ord,
Sort the SegVec
in ascending order (unstable)
Trait Implementations§
source§impl<'a, T: Copy + 'a, C: MemConfig> Extend<&'a T> for SegVec<T, C>
impl<'a, T: Copy + 'a, C: MemConfig> Extend<&'a T> for SegVec<T, C>
source§fn extend<I: IntoIterator<Item = &'a T>>(&mut self, iter: I)
fn extend<I: IntoIterator<Item = &'a T>>(&mut self, iter: I)
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, C: MemConfig> Extend<T> for SegVec<T, C>
impl<T, C: MemConfig> Extend<T> for SegVec<T, C>
source§fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I)
fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I)
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
)