raw_parts
This commit is contained in:
parent
672ea5b0bc
commit
1c6d8cdfa3
86
src/lib.rs
86
src/lib.rs
|
@ -1,6 +1,6 @@
|
||||||
//! # A [`Vec<T: ?Sized>`]
|
//! # A [`Vec<T: ?Sized>`]
|
||||||
//!
|
//!
|
||||||
//! A dynamic length collection of unsized elements, akin to [`std::vec::Vec`].
|
//! [`dyn_vec::Vec`], a dynamic length collection of unsized elements, akin to [`std::vec::Vec`].
|
||||||
//!
|
//!
|
||||||
//! # Examples
|
//! # Examples
|
||||||
//!
|
//!
|
||||||
|
@ -115,6 +115,7 @@
|
||||||
//! ```
|
//! ```
|
||||||
//!
|
//!
|
||||||
//! [`Vec<T: ?Sized>`]: Vec
|
//! [`Vec<T: ?Sized>`]: Vec
|
||||||
|
//! [`dyn_vec::Vec`]: Vec
|
||||||
//! [`Vec::push_unsize`]: Vec::push_unsize
|
//! [`Vec::push_unsize`]: Vec::push_unsize
|
||||||
//! [`Vec::unsize`]: Vec::unsize
|
//! [`Vec::unsize`]: Vec::unsize
|
||||||
//! [`Vec::extend_unsize`]: Vec::extend_unsize
|
//! [`Vec::extend_unsize`]: Vec::extend_unsize
|
||||||
|
@ -149,10 +150,10 @@ pub mod prelude {
|
||||||
|
|
||||||
use core::panic;
|
use core::panic;
|
||||||
use std::{
|
use std::{
|
||||||
alloc::{alloc, dealloc, Layout},
|
alloc::{alloc, dealloc, handle_alloc_error, Layout},
|
||||||
any::Any,
|
any::Any,
|
||||||
marker::PhantomData,
|
marker::PhantomData,
|
||||||
mem::{self, align_of, align_of_val, size_of, size_of_val},
|
mem::{self, align_of, align_of_val, size_of, size_of_val, ManuallyDrop},
|
||||||
ops::{Index, IndexMut},
|
ops::{Index, IndexMut},
|
||||||
ptr::{drop_in_place, NonNull},
|
ptr::{drop_in_place, NonNull},
|
||||||
slice,
|
slice,
|
||||||
|
@ -238,6 +239,52 @@ impl<T: ?Sized> Vec<T> {
|
||||||
Self::with_capacity_bytes(cap * (size_of::<U>() + size_of::<Extra<U>>()))
|
Self::with_capacity_bytes(cap * (size_of::<U>() + size_of::<Extra<U>>()))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Decomposes the vector into its raw components.
|
||||||
|
///
|
||||||
|
/// Returns the pointer to the underlying alloctaion, the number of elements,
|
||||||
|
/// the size of the allocation in bytes, and the total size of all of the
|
||||||
|
/// vector's elements.
|
||||||
|
pub fn into_raw_parts(self) -> (*mut u8, usize, usize, usize) {
|
||||||
|
let mut this = ManuallyDrop::new(self);
|
||||||
|
(
|
||||||
|
this.as_mut_ptr(),
|
||||||
|
this.len(),
|
||||||
|
this.capacity(),
|
||||||
|
this.data_size(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Reconstructs a vector from its raw components.
|
||||||
|
///
|
||||||
|
/// # Safety
|
||||||
|
/// - `ptr` must be non-null and point to an allocation with the proper
|
||||||
|
/// data layout, as documented in the crate-level docs.
|
||||||
|
/// - `len` must be less than or equal to the number of initialized
|
||||||
|
/// elements in the allocation.
|
||||||
|
/// - `capacity` must be equal to the size of the allocation in bytes.
|
||||||
|
/// - `data_size` must be equal to the number of bytes taken up by the
|
||||||
|
/// first `len` elements of the vector, including leading (but not trailing)
|
||||||
|
/// padding.
|
||||||
|
/// - The allocation must have been allocated with alignment equal to
|
||||||
|
/// `align_of::<*const T>()`
|
||||||
|
///
|
||||||
|
/// All of these conditions are upheld by the values returned from
|
||||||
|
/// `into_raw_parts`.
|
||||||
|
pub const unsafe fn from_raw_parts(
|
||||||
|
ptr: *mut u8,
|
||||||
|
len: usize,
|
||||||
|
capacity: usize,
|
||||||
|
data_size: usize,
|
||||||
|
) -> Self {
|
||||||
|
Self {
|
||||||
|
ptr: NonNull::new_unchecked(ptr),
|
||||||
|
len,
|
||||||
|
capacity,
|
||||||
|
end_ptr: NonNull::new_unchecked(ptr.add(data_size)),
|
||||||
|
_phantom: PhantomData,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Appends an element to the end of the vector.
|
/// Appends an element to the end of the vector.
|
||||||
///
|
///
|
||||||
/// Only avaliable if `T: Sized`.
|
/// Only avaliable if `T: Sized`.
|
||||||
|
@ -245,8 +292,7 @@ impl<T: ?Sized> Vec<T> {
|
||||||
where
|
where
|
||||||
T: Sized,
|
T: Sized,
|
||||||
{
|
{
|
||||||
unsafe { self.push_raw(&v) }
|
unsafe { self.push_raw(&*ManuallyDrop::new(v)) }
|
||||||
mem::forget(v);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Appends an (possibly unsized) boxed element to the end of the vector.
|
/// Appends an (possibly unsized) boxed element to the end of the vector.
|
||||||
|
@ -323,16 +369,15 @@ impl<T: ?Sized> Vec<T> {
|
||||||
|
|
||||||
unsafe fn realloc(&mut self, size: usize) {
|
unsafe fn realloc(&mut self, size: usize) {
|
||||||
let layout = Layout::from_size_align_unchecked(size, align_of::<Extra<T>>()).pad_to_align();
|
let layout = Layout::from_size_align_unchecked(size, align_of::<Extra<T>>()).pad_to_align();
|
||||||
|
let new_alloc = NonNull::new(alloc(layout)).unwrap_or_else(|| handle_alloc_error(layout));
|
||||||
if self.capacity == 0 {
|
if self.capacity == 0 {
|
||||||
// will panic if OOM
|
// will panic if OOM
|
||||||
self.ptr = NonNull::new(alloc(layout)).unwrap();
|
self.ptr = new_alloc;
|
||||||
|
|
||||||
self.end_ptr = self.ptr;
|
self.end_ptr = self.ptr;
|
||||||
} else {
|
} else {
|
||||||
// cannot use mem::realloc here
|
// cannot use mem::realloc here
|
||||||
|
|
||||||
let new_alloc = NonNull::new(alloc(layout)).unwrap();
|
|
||||||
|
|
||||||
// data
|
// data
|
||||||
let mut ptr = new_alloc.as_ptr();
|
let mut ptr = new_alloc.as_ptr();
|
||||||
for i in 0..self.len {
|
for i in 0..self.len {
|
||||||
|
@ -445,7 +490,7 @@ impl<T: ?Sized> Vec<T> {
|
||||||
|
|
||||||
/// Returns the capacity, which is the size of the allocation in bytes.
|
/// Returns the capacity, which is the size of the allocation in bytes.
|
||||||
///
|
///
|
||||||
/// Note the distinction from [`std::vec::Vec`], which returns how many elements it can hold.
|
/// Note the distinction from [`std::vec::Vec::capacity`], which returns how many *elements* it can hold.
|
||||||
pub const fn capacity(&self) -> usize {
|
pub const fn capacity(&self) -> usize {
|
||||||
self.capacity
|
self.capacity
|
||||||
}
|
}
|
||||||
|
@ -460,6 +505,23 @@ impl<T: ?Sized> Vec<T> {
|
||||||
self.ptr.as_ptr()
|
self.ptr.as_ptr()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns a pointer to the end of the last element of the vector.
|
||||||
|
pub const fn as_end_ptr(&self) -> *const u8 {
|
||||||
|
self.end_ptr.as_ptr()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns a mutable pointer to the end of the last element of the vector.
|
||||||
|
pub fn as_end_ptr_mut(&mut self) -> *const u8 {
|
||||||
|
self.end_ptr.as_ptr()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the size (in bytes) of the elements (and padding) of the vector.
|
||||||
|
///
|
||||||
|
/// Same as `self.as_end_ptr() as usize - self.as_ptr() as usize`.
|
||||||
|
pub fn data_size(&self) -> usize {
|
||||||
|
self.as_end_ptr() as usize - self.as_ptr() as usize
|
||||||
|
}
|
||||||
|
|
||||||
/// Iterates over the vector by-ref.
|
/// Iterates over the vector by-ref.
|
||||||
pub fn iter(&self) -> Iter<T> {
|
pub fn iter(&self) -> Iter<T> {
|
||||||
Iter::new(self)
|
Iter::new(self)
|
||||||
|
@ -644,14 +706,14 @@ impl<T> Vec<[T]> {
|
||||||
impl Vec<dyn Any> {
|
impl Vec<dyn Any> {
|
||||||
/// Gets a reference to the element at then specified index, downcasting it to the specified type.
|
/// Gets a reference to the element at then specified index, downcasting it to the specified type.
|
||||||
///
|
///
|
||||||
/// Same as `.get().map(|v| v.downcast()).flatten()`.
|
/// Same as `self.get(index).map(|v| v.downcast()).flatten()`.
|
||||||
pub fn downcast_get<T: Any>(&self, index: usize) -> Option<&T> {
|
pub fn downcast_get<T: Any>(&self, index: usize) -> Option<&T> {
|
||||||
self.get(index)?.downcast_ref()
|
self.get(index)?.downcast_ref()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Gets a mutable reference to the element at then specified index, downcasting it to the specified type.
|
/// Gets a mutable reference to the element at then specified index, downcasting it to the specified type.
|
||||||
///
|
///
|
||||||
/// Same as `.get_mut().map(|v| v.downcast_mut()).flatten()`.
|
/// Same as `self.get_mut(index).map(|v| v.downcast_mut()).flatten()`.
|
||||||
pub fn downcast_get_mut<T: Any>(&mut self, index: usize) -> Option<&mut T> {
|
pub fn downcast_get_mut<T: Any>(&mut self, index: usize) -> Option<&mut T> {
|
||||||
self.get_mut(index)?.downcast_mut()
|
self.get_mut(index)?.downcast_mut()
|
||||||
}
|
}
|
||||||
|
@ -660,7 +722,7 @@ impl Vec<dyn Any> {
|
||||||
///
|
///
|
||||||
/// If the element is not of type `T`, the element will not be popped.
|
/// If the element is not of type `T`, the element will not be popped.
|
||||||
///
|
///
|
||||||
/// Similiar to `.pop().map(|v| v.downcast()).flatten()`, but without an intermediate allocation.
|
/// Same as `self.pop().map(|v| v.downcast()).flatten()`, but without an intermediate allocation.
|
||||||
pub fn downcast_pop<T: Any>(&mut self) -> Option<T> {
|
pub fn downcast_pop<T: Any>(&mut self) -> Option<T> {
|
||||||
unsafe {
|
unsafe {
|
||||||
let el = self.get_unchecked_mut(self.len.checked_sub(1)?);
|
let el = self.get_unchecked_mut(self.len.checked_sub(1)?);
|
||||||
|
|
|
@ -223,7 +223,7 @@ fn stress_test() {
|
||||||
|
|
||||||
let mut len = 0;
|
let mut len = 0;
|
||||||
|
|
||||||
let iterations = if cfg!(miri) { 1_000 } else { 1_000_000 };
|
let iterations = if cfg!(miri) { 100 } else { 1_000_000 };
|
||||||
|
|
||||||
for _ in 0..iterations {
|
for _ in 0..iterations {
|
||||||
if len == 0 || rng.gen_bool(0.7) {
|
if len == 0 || rng.gen_bool(0.7) {
|
||||||
|
|
Loading…
Reference in a new issue