Document public vector accessors
This commit is contained in:
+21
-1
@@ -2,7 +2,9 @@ use crate::TypeErasedVec;
|
||||
use std::marker::PhantomData;
|
||||
use std::mem::ManuallyDrop;
|
||||
|
||||
/// Provides access to a `TypeErasedVec` with a temporarily fixed type `T`
|
||||
/// Provides typed access to a [`TypeErasedVec`] allocation.
|
||||
///
|
||||
/// Dropping the guard retains its initialized elements in the erased vector.
|
||||
pub struct ContentGuard<'vec, T> {
|
||||
erased: &'vec mut TypeErasedVec,
|
||||
reerase: fn(Vec<T>) -> TypeErasedVec,
|
||||
@@ -19,6 +21,9 @@ impl<'vec, T> ContentGuard<'vec, T> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Removes all elements and the allocation from the guard.
|
||||
///
|
||||
/// The guard remains usable with an empty, zero-capacity vector.
|
||||
pub fn take(&mut self) -> Vec<T> {
|
||||
let erased = std::mem::replace(self.erased, (self.reerase)(Vec::new()));
|
||||
let erased = ManuallyDrop::new(erased);
|
||||
@@ -27,6 +32,9 @@ impl<'vec, T> ContentGuard<'vec, T> {
|
||||
unsafe { erased.parts.into_vec() }
|
||||
}
|
||||
|
||||
/// Calls `function` with the underlying vector and then type-erases it again.
|
||||
///
|
||||
/// Mutations made by `function` are retained on normal return.
|
||||
pub fn with<R>(&mut self, f: impl FnOnce(&mut Vec<T>) -> R) -> R {
|
||||
let mut vec = self.take();
|
||||
// This is unwind-safe. If the closure panics, the inner `Vec<T>` drops normally.
|
||||
@@ -37,51 +45,63 @@ impl<'vec, T> ContentGuard<'vec, T> {
|
||||
res
|
||||
}
|
||||
|
||||
/// Removes and drops all initialized elements.
|
||||
pub fn clear(&mut self) {
|
||||
self.with(Vec::clear);
|
||||
}
|
||||
|
||||
/// Reserves capacity for at least `additional` more elements.
|
||||
pub fn reserve(&mut self, additional: usize) {
|
||||
self.with(|vec| vec.reserve(additional));
|
||||
}
|
||||
|
||||
/// Returns the allocation's capacity in elements.
|
||||
#[must_use]
|
||||
pub fn capacity(&self) -> usize {
|
||||
self.erased.capacity()
|
||||
}
|
||||
|
||||
/// Appends an element.
|
||||
pub fn push(&mut self, value: T) {
|
||||
self.with(|vec| vec.push(value));
|
||||
}
|
||||
|
||||
/// Returns the number of initialized elements.
|
||||
#[must_use]
|
||||
pub fn length(&self) -> usize {
|
||||
self.erased.length()
|
||||
}
|
||||
|
||||
/// Returns `true` when there are no initialized elements.
|
||||
#[must_use]
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.erased.is_empty()
|
||||
}
|
||||
|
||||
/// Borrows the initialized elements as a slice.
|
||||
#[must_use]
|
||||
pub fn as_slice(&self) -> &[T] {
|
||||
// SAFETY: The pointer and length correctly represent the currently initialized elements.
|
||||
unsafe { self.erased.parts.as_slice() }
|
||||
}
|
||||
|
||||
/// Mutably borrows the initialized elements as a slice.
|
||||
#[must_use]
|
||||
pub fn as_slice_mut(&mut self) -> &mut [T] {
|
||||
// SAFETY: The pointer and length correctly represent the currently initialized elements.
|
||||
unsafe { self.erased.parts.as_slice_mut() }
|
||||
}
|
||||
|
||||
/// Consumes the guard and borrows the initialized elements for the erased
|
||||
/// vector's lifetime.
|
||||
#[must_use]
|
||||
pub fn into_slice(self) -> &'vec [T] {
|
||||
// SAFETY: The pointer and length correctly represent the currently initialized elements.
|
||||
unsafe { self.erased.parts.as_slice() }
|
||||
}
|
||||
|
||||
/// Consumes the guard and mutably borrows the initialized elements for the
|
||||
/// erased vector's lifetime.
|
||||
#[must_use]
|
||||
pub fn into_slice_mut(self) -> &'vec mut [T] {
|
||||
// SAFETY: The pointer and length correctly represent the currently initialized elements.
|
||||
|
||||
@@ -87,26 +87,34 @@ impl TypeErasedVec {
|
||||
unsafe { (self.vtable.reserve)(&mut self.parts, additional) };
|
||||
}
|
||||
|
||||
/// Returns the element layout associated with the allocation.
|
||||
#[must_use]
|
||||
pub fn layout(&self) -> Layout {
|
||||
self.layout
|
||||
}
|
||||
|
||||
/// Returns the allocation's capacity in elements.
|
||||
#[must_use]
|
||||
pub fn capacity(&self) -> usize {
|
||||
self.parts.cap
|
||||
}
|
||||
|
||||
/// Returns the number of initialized elements.
|
||||
#[must_use]
|
||||
pub fn length(&self) -> usize {
|
||||
self.parts.len
|
||||
}
|
||||
|
||||
/// Returns `true` when there are no initialized elements.
|
||||
#[must_use]
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.parts.len == 0
|
||||
}
|
||||
|
||||
/// Returns the allocation's capacity in bytes.
|
||||
///
|
||||
/// Zero-sized elements always report zero bytes, regardless of their
|
||||
/// logical capacity.
|
||||
#[must_use]
|
||||
pub fn capacity_bytes(&self) -> usize {
|
||||
self.parts.cap * self.layout.size()
|
||||
|
||||
@@ -30,26 +30,31 @@ macro_rules! define_thread_safe_erased_vec {
|
||||
self.0.reserve(additional);
|
||||
}
|
||||
|
||||
/// Returns the element layout associated with the allocation.
|
||||
#[must_use]
|
||||
pub fn layout(&self) -> Layout {
|
||||
self.0.layout()
|
||||
}
|
||||
|
||||
/// Returns the allocation's capacity in elements.
|
||||
#[must_use]
|
||||
pub fn capacity(&self) -> usize {
|
||||
self.0.capacity()
|
||||
}
|
||||
|
||||
/// Returns the number of initialized elements.
|
||||
#[must_use]
|
||||
pub fn length(&self) -> usize {
|
||||
self.0.length()
|
||||
}
|
||||
|
||||
/// Returns `true` when there are no initialized elements.
|
||||
#[must_use]
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.0.is_empty()
|
||||
}
|
||||
|
||||
/// Returns the allocation's capacity in bytes.
|
||||
#[must_use]
|
||||
pub fn capacity_bytes(&self) -> usize {
|
||||
self.0.capacity_bytes()
|
||||
|
||||
Reference in New Issue
Block a user