//! This crate provides a pin-safe, append-only vector which guarantees never //! to move the storage for an element once it has been allocated.
use std::{
ops::{Index, IndexMut},
slice,
};
struct Chunk<T> { /// The elements of this chunk.
elements: Vec<T>,
}
impl<T> Chunk<T> { fn with_capacity(capacity: usize) -> Self { let elements = Vec::with_capacity(capacity);
assert_eq!(elements.capacity(), capacity); Self { elements }
}
fn len(&self) -> usize { self.elements.len()
}
/// Returns the number of available empty elements. fn available(&self) -> usize { self.elements.capacity() - self.elements.len()
}
/// Returns a shared reference to the element at the given index. /// /// # Panics /// /// Panics if the index is out of bounds. pubfn get(&self, index: usize) -> Option<&T> { self.elements.get(index)
}
/// Returns an exclusive reference to the element at the given index. /// /// # Panics /// /// Panics if the index is out of bounds. pubfn get_mut(&mutself, index: usize) -> Option<&mut T> { self.elements.get_mut(index)
}
/// Pushes a new value into the fixed capacity entry. /// /// # Panics /// /// If the entry is already at its capacity. /// Note that this panic should never happen since the entry is only ever /// accessed by its outer chunk vector that checks before pushing. pubfn push(&mutself, new_value: T) { ifself.available() == 0 {
panic!("No available elements.")
} self.elements.push(new_value);
}
pubfn push_get(&mutself, new_value: T) -> &>mut T { self.push(new_value); unsafe { let last = self.elements.len() - 1; self.elements.get_unchecked_mut(last)
}
}
/// Returns an iterator over the elements of the chunk. pubfn iter(&self) -> slice::Iter<T> { self.elements.iter()
}
/// Returns an iterator over the elements of the chunk. pubfn iter_mut(&mutself) -> slice::IterMut<T> { self.elements.iter_mut()
}
}
impl<T> Index<usize> for Chunk<T> { type Output = T;
fn index(&self, index: usize) -> &Self::Output { self.get(index).expect("index out of bounds")
}
}
impl<T> IndexMut<usize> for Chunk<T> { fn index_mut(&mutself, index: usize) -> &mutSelf::Output { self.get_mut(index).expect("index out of bounds")
}
}
/// Pin safe vector /// /// An append only vector that never moves the backing store for each element. pubstruct ChunkyVec<T> { /// The chunks holding elements
chunks: Vec<Chunk<T>>,
}
pubfn len(&self) -> usize { ifself.chunks.is_empty() { 0
} else { // # Safety - There is at least one chunk here.
(self.chunks.len() - 1) * Self::DEFAULT_CAPACITY + self.chunks.last().unwrap().len()
}
}
pubfn is_empty(&self) -> bool { // # Safety - Since it's impossible to pop, at least one chunk means we're not empty. self.chunks.is_empty()
}
/// Returns an iterator that yields shared references to the elements of the bucket vector. pubfn iter(&self) -> Iter<T> {
Iter::new(self)
}
/// Returns an iterator that yields exclusive reference to the elements of the bucket vector. pubfn iter_mut(&mutself) -> IterMut<T> {
IterMut::new(self)
}
/// Returns a shared reference to the element at the given index if any. pubfn get(&self, index: usize) -> Option<&T> { let (x, y) = (
index / Self::DEFAULT_CAPACITY,
index % Self::DEFAULT_CAPACITY,
); self.chunks.get(x).and_then(|chunk| chunk.get(y))
}
/// Returns an exclusive reference to the element at the given index if any. pubfn get_mut(&mutself, index: usize) -> Option<&mut T> { let (x, y) = (
index / Self::DEFAULT_CAPACITY,
index % Self::DEFAULT_CAPACITY,
); self.chunks.get_mut(x).and_then(|chunk| chunk.get_mut(y))
}
/// Pushes a new element onto the bucket vector. /// /// # Note /// /// This operation will never move other elements, reallocates or otherwise /// invalidate pointers of elements contained by the bucket vector. pubfn push(&mutself, new_value: T) { self.push_get(new_value);
}
pubfn push_get(&mutself, new_value: T) -> &>mut T { ifself.chunks.last().map(Chunk::available).unwrap_or_default() == 0 { self.chunks.push(Chunk::with_capacity(Self::DEFAULT_CAPACITY));
} // Safety: Guaranteed to have a chunk with available elements unsafe { let last = self.chunks.len() - 1; self.chunks.get_unchecked_mut(last).push_get(new_value)
}
}
}
impl<T> Index<usize> for ChunkyVec<T> { type Output = T;
fn index(&self, index: usize) -> &Self::Output { self.get(index).expect("index out of bounds")
}
}
impl<T> IndexMut<usize> for ChunkyVec<T> { fn index_mut(&mutself, index: usize) -> &mutSelf::Output { self.get_mut(index).expect("index out of bounds")
}
}
/// An iterator yielding shared references to the elements of a ChunkyVec. #[derive(Clone)] pubstruct Iter<'a, T> { /// Chunks iterator.
chunks: slice::Iter<'a, Chunk<T>>, /// Forward iterator for `next`.
iter: Option<slice::Iter<'a, T>>, /// Number of elements that are to be yielded by the iterator.
len: usize,
}
impl<'a, T> Iter<'a, T> { /// Creates a new iterator over the ChunkyVec pub(crate) fn new(vec: &'a ChunkyVec<T>) -> Self { let len = vec.len(); Self {
chunks: vec.chunks.iter(),
iter: None,
len,
}
}
}
impl<'a, T> Iterator for Iter<'a, T> { type Item = &'a T;
/// An iterator yielding exclusive references to the elements of a ChunkVec. pubstruct IterMut<'a, T> { /// Chunks iterator.
chunks: slice::IterMut<'a, Chunk<T>>, /// Forward iterator for `next`.
iter: Option<slice::IterMut<'a, T>>, /// Number of elements that are to be yielded by the iterator.
len: usize,
}
impl<'a, T> IterMut<'a, T> { /// Creates a new iterator over the bucket vector. pub(crate) fn new(vec: &'a mut ChunkyVec<T>) -> Self { let len = vec.len(); Self {
chunks: vec.chunks.iter_mut(),
iter: None,
len,
}
}
}
impl<'a, T> Iterator for IterMut<'a, T> { type Item = &'a mut T;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.