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 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
|
||||
//!
|
||||
|
@ -115,6 +115,7 @@
|
|||
//! ```
|
||||
//!
|
||||
//! [`Vec<T: ?Sized>`]: Vec
|
||||
//! [`dyn_vec::Vec`]: Vec
|
||||
//! [`Vec::push_unsize`]: Vec::push_unsize
|
||||
//! [`Vec::unsize`]: Vec::unsize
|
||||
//! [`Vec::extend_unsize`]: Vec::extend_unsize
|
||||
|
@ -149,10 +150,10 @@ pub mod prelude {
|
|||
|
||||
use core::panic;
|
||||
use std::{
|
||||
alloc::{alloc, dealloc, Layout},
|
||||
alloc::{alloc, dealloc, handle_alloc_error, Layout},
|
||||
any::Any,
|
||||
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},
|
||||
ptr::{drop_in_place, NonNull},
|
||||
slice,
|
||||
|
@ -238,6 +239,52 @@ impl<T: ?Sized> Vec<T> {
|
|||
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.
|
||||
///
|
||||
/// Only avaliable if `T: Sized`.
|
||||
|
@ -245,8 +292,7 @@ impl<T: ?Sized> Vec<T> {
|
|||
where
|
||||
T: Sized,
|
||||
{
|
||||
unsafe { self.push_raw(&v) }
|
||||
mem::forget(v);
|
||||
unsafe { self.push_raw(&*ManuallyDrop::new(v)) }
|
||||
}
|
||||
|
||||
/// 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) {
|
||||
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 {
|
||||
// will panic if OOM
|
||||
self.ptr = NonNull::new(alloc(layout)).unwrap();
|
||||
self.ptr = new_alloc;
|
||||
|
||||
self.end_ptr = self.ptr;
|
||||
} else {
|
||||
// cannot use mem::realloc here
|
||||
|
||||
let new_alloc = NonNull::new(alloc(layout)).unwrap();
|
||||
|
||||
// data
|
||||
let mut ptr = new_alloc.as_ptr();
|
||||
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.
|
||||
///
|
||||
/// 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 {
|
||||
self.capacity
|
||||
}
|
||||
|
@ -460,6 +505,23 @@ impl<T: ?Sized> Vec<T> {
|
|||
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.
|
||||
pub fn iter(&self) -> Iter<T> {
|
||||
Iter::new(self)
|
||||
|
@ -644,14 +706,14 @@ impl<T> Vec<[T]> {
|
|||
impl Vec<dyn Any> {
|
||||
/// 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> {
|
||||
self.get(index)?.downcast_ref()
|
||||
}
|
||||
|
||||
/// 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> {
|
||||
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.
|
||||
///
|
||||
/// 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> {
|
||||
unsafe {
|
||||
let el = self.get_unchecked_mut(self.len.checked_sub(1)?);
|
||||
|
|
|
@ -223,7 +223,7 @@ fn stress_test() {
|
|||
|
||||
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 {
|
||||
if len == 0 || rng.gen_bool(0.7) {
|
||||
|
|
Loading…
Reference in a new issue