spinoso_string

Struct RawParts

Source
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>

Source

pub fn from_vec(vec: Vec<T>) -> RawParts<T>

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]);
Source

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 the alloc::alloc function.
  • T needs to have the same alignment as what ptr was allocated with. (T having a less strict alignment is not sufficient, the alignment really needs to be equal to satisfy the dealloc requirement that memory must be allocated and deallocated with the same layout.)
  • The size of T times the capacity (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 layout size.)
  • length needs to be less than or equal to capacity.
  • The first length values must be properly initialized values of type T.
  • 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 of pointer::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]);
}

Trait Implementations§

Source§

impl<T> Debug for RawParts<T>

Source§

fn fmt(&self, fmt: &mut Formatter<'_>) -> Result<(), Error>

Formats the value using the given formatter. Read more
Source§

impl<T> From<Vec<T>> for RawParts<T>

Source§

fn from(vec: Vec<T>) -> RawParts<T>

Decompose a Vec<T> into its raw components.

Source§

impl<T> Hash for RawParts<T>

Source§

fn hash<H>(&self, state: &mut H)
where H: Hasher,

Feeds this value into the given Hasher. Read more
1.3.0 · Source§

fn hash_slice<H>(data: &[Self], state: &mut H)
where H: Hasher, Self: Sized,

Feeds a slice of this type into the given Hasher. Read more
Source§

impl<T> PartialEq for RawParts<T>

Source§

fn eq(&self, other: &RawParts<T>) -> bool

Tests for self and other values to be equal, and is used by ==.
1.0.0 · Source§

fn ne(&self, other: &Rhs) -> bool

Tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
Source§

impl<T> Eq for RawParts<T>

Auto Trait Implementations§

§

impl<T> Freeze for RawParts<T>

§

impl<T> RefUnwindSafe for RawParts<T>
where T: RefUnwindSafe,

§

impl<T> !Send for RawParts<T>

§

impl<T> !Sync for RawParts<T>

§

impl<T> Unpin for RawParts<T>

§

impl<T> UnwindSafe for RawParts<T>
where T: RefUnwindSafe,

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.