pub struct RawParts<T> {
pub ptr: *mut T,
pub length: usize,
pub capacity: usize,
}
Expand description
A wrapper around the decomposed parts of a Vec<T>
.
This struct contains the Vec
’s internal pointer, length, and allocated
capacity.
RawParts
makes Vec::from_raw_parts
and Vec::into_raw_parts
easier
to use by giving names to the returned values. This prevents errors from
mixing up the two usize
values of length and capacity.
§Examples
use raw_parts::RawParts;
let v: Vec<i32> = vec![-1, 0, 1];
let RawParts { ptr, length, capacity } = RawParts::from_vec(v);
let rebuilt = unsafe {
// We can now make changes to the components, such as
// transmuting the raw pointer to a compatible type.
let ptr = ptr as *mut u32;
let raw_parts = RawParts { ptr, length, capacity };
raw_parts.into_vec()
};
assert_eq!(rebuilt, [4294967295, 0, 1]);
Fields§
§ptr: *mut T
A non-null pointer to a buffer of T
.
This pointer is the same as the value returned by Vec::as_mut_ptr
in
the source vector.
length: usize
The number of elements in the source vector, also referred to as its “length”.
This value is the same as the value returned by Vec::len
in the
source vector.
capacity: usize
The number of elements the source vector can hold without reallocating.
This value is the same as the value returned by Vec::capacity
in the
source vector.
Implementations§
Source§impl<T> RawParts<T>
impl<T> RawParts<T>
Sourcepub fn from_vec(vec: Vec<T>) -> Self
pub fn from_vec(vec: Vec<T>) -> Self
Construct the raw components of a Vec<T>
by decomposing it.
Returns a struct containing the raw pointer to the underlying data, the length of the vector (in elements), and the allocated capacity of the data (in elements).
After calling this function, the caller is responsible for the memory
previously managed by the Vec
. The only way to do this is to convert
the raw pointer, length, and capacity back into a Vec
with the
Vec::from_raw_parts
function or the into_vec
function, allowing
the destructor to perform the cleanup.
§Examples
use raw_parts::RawParts;
let v: Vec<i32> = vec![-1, 0, 1];
let RawParts { ptr, length, capacity } = RawParts::from_vec(v);
let rebuilt = unsafe {
// We can now make changes to the components, such as
// transmuting the raw pointer to a compatible type.
let ptr = ptr as *mut u32;
let raw_parts = RawParts { ptr, length, capacity };
raw_parts.into_vec()
};
assert_eq!(rebuilt, [4294967295, 0, 1]);
Sourcepub unsafe fn into_vec(self) -> Vec<T>
pub unsafe fn into_vec(self) -> Vec<T>
Creates a Vec<T>
directly from the raw components of another vector.
§Safety
This function has the same safety invariants as Vec::from_raw_parts
,
which are repeated in the following paragraphs.
This is highly unsafe, due to the number of invariants that aren’t checked:
ptr
must have been allocated using the global allocator, such as via thealloc::alloc
function.T
needs to have the same alignment as whatptr
was allocated with. (T
having a less strict alignment is not sufficient, the alignment really needs to be equal to satisfy thedealloc
requirement that memory must be allocated and deallocated with the same layout.)- The size of
T
times thecapacity
(ie. the allocated size in bytes) needs to be the same size as the pointer was allocated with. (Because similar to alignment,dealloc
must be called with the same layoutsize
.) length
needs to be less than or equal tocapacity
.- The first
length
values must be properly initialized values of typeT
. capacity
needs to be the capacity that the pointer was allocated with.- The allocated size in bytes must be no larger than
isize::MAX
. See the safety documentation ofpointer::offset
.
These requirements are always upheld by any ptr
that has been allocated
via Vec<T>
. Other allocation sources are allowed if the invariants are
upheld.
Violating these may cause problems like corrupting the allocator’s
internal data structures. For example it is normally not safe
to build a Vec<u8>
from a pointer to a C char
array with length
size_t
, doing so is only safe if the array was initially allocated by
a Vec
or String
.
It’s also not safe to build one from a Vec<u16>
and its length, because
the allocator cares about the alignment, and these two types have different
alignments. The buffer was allocated with alignment 2 (for u16
), but after
turning it into a Vec<u8>
it’ll be deallocated with alignment 1. To avoid
these issues, it is often preferable to do casting/transmuting using
slice::from_raw_parts
instead.
The ownership of ptr
is effectively transferred to the
Vec<T>
which may then deallocate, reallocate or change the
contents of memory pointed to by the pointer at will. Ensure
that nothing else uses the pointer after calling this
function.
§Examples
use core::ptr;
use core::mem;
use raw_parts::RawParts;
let v = vec![1, 2, 3];
// Pull out the various important pieces of information about `v`
let RawParts { ptr, length, capacity } = RawParts::from_vec(v);
unsafe {
// Overwrite memory with 4, 5, 6
for i in 0..length as isize {
ptr::write(ptr.offset(i), 4 + i);
}
// Put everything back together into a Vec
let raw_parts = RawParts { ptr, length, capacity };
let rebuilt = raw_parts.into_vec();
assert_eq!(rebuilt, [4, 5, 6]);
}