Trait UnsizedCopy

Source
pub unsafe trait UnsizedCopy {
    type Alignment: Sized;

    // Required method
    fn ptr_with_addr(&self, addr: *const ()) -> *const Self;

    // Provided methods
    fn unsized_copy_into<T: UnsizedCopyFrom<Source = Self>>(&self) -> T { ... }
    fn copy(&self) -> Self
       where Self: Sized { ... }
}
Expand description

An extension of Copy to dynamically sized types.

This is a generalization of Copy. It is intended to simplify working with DSTs that support zero-copy parsing techniques (as these are built from byte sequences, they are inherently trivial to copy).

§Usage

To copy a type, call UnsizedCopy::unsized_copy_into() on the DST being copied, or call UnsizedCopyFrom::unsized_copy_from() on the container type to copy into. The two function identically.

§Safety

A type T can implement UnsizedCopy if all of the following hold:

  • It is an aggregate type (struct, enum, or union) and every field implements UnsizedCopy.

  • T::Alignment has exactly the same alignment as T.

  • T::ptr_with_addr() satisfies the documented invariants.

Required Associated Types§

Source

type Alignment: Sized

A type with the same alignment as Self.

At the moment, Rust does not provide a way to determine the alignment of a dynamically sized type at compile-time. This restriction exists because trait objects (which count as DSTs, but are not supported by UnsizedCopy) have an alignment determined by their implementation (which can vary at runtime).

This associated type papers over this limitation, by simply requiring every implementation of UnsizedCopy to specify a type with the same alignment here. This is used by internal plumbing code to know the alignment of Self at compile-time.

§Invariants

The alignment of Self::Alignment must be the same as that of Self.

Required Methods§

Source

fn ptr_with_addr(&self, addr: *const ()) -> *const Self

Change the address of a pointer to Self.

Self may be a DST, which means that references (and pointers) to it store metadata alongside the usual memory address. For example, the metadata for a slice type is its length. In order to construct a new instance of Self (as is done by copying), a new pointer must be created, and the appropriate metadata must be inserted.

At the moment, Rust does not provide a way to examine this metadata for an arbitrary type. This method papers over this limitation, and provides a way to copy the metadata from an existing pointer while changing the pointer address.

§Implementing

Most users will derive UnsizedCopy and so don’t need to worry about this. In any case, when Rust builds in support for extracting metadata, this function will gain a default implementation, and will eventually be deprecated.

For manual implementations for unsized types:

pub struct Foo {
    a: i32,
    b: [u8],
}

unsafe impl UnsizedCopy for Foo {
    // We would like to write 'Alignment = Self' here, but we can't
    // because 'Self' is not 'Sized'.  However, 'Self' is a 'struct'
    // using 'repr(Rust)'; the following tuple (which implicitly also
    // uses 'repr(Rust)') has the same alignment as it.
    type Alignment = (i32, u8);

    fn ptr_with_addr(&self, addr: *const ()) -> *const Self {
        // Delegate to the same function on the last field.
        //
        // Rust knows that 'Self' has the same metadata as '[u8]',
        // and so permits casting pointers between those types.
        self.b.ptr_with_addr(addr) as *const Self
    }
}

For manual implementations for sized types:

pub struct Foo {
    a: i32,
    b: Option<f64>,
}

unsafe impl UnsizedCopy for Foo {
    // Because 'Foo' is a sized type, we can use it here directly.
    type Alignment = Self;

    fn ptr_with_addr(&self, addr: *const ()) -> *const Self {
        // Since 'Self' is 'Sized', there is no metadata.
        addr.cast::<Self>()
    }
}
§Invariants

For the statement let result = Self::ptr_with_addr(ptr, addr);, the following always hold:

  • result as usize == addr as usize.
  • core::ptr::metadata(result) == core::ptr::metadata(ptr).

It is undefined behaviour for an implementation of UnsizedCopy to break these invariants.

Provided Methods§

Source

fn unsized_copy_into<T: UnsizedCopyFrom<Source = Self>>(&self) -> T

Copy self into a new container.

A new container of the specified type (which is usually inferred) is allocated, and the contents of self are copied into it. This is a convenience method that calls unsized_copy_from().

Source

fn copy(&self) -> Self
where Self: Sized,

Copy self and return it by value.

This offers equivalent functionality to the regular Copy trait, which is also why it has the same Sized bound.

Dyn Compatibility§

This trait is not dyn compatible.

In older versions of Rust, dyn compatibility was called "object safety", so this trait is not object safe.

Implementations on Foreign Types§

Source§

impl UnsizedCopy for bool

Source§

impl UnsizedCopy for char

Source§

impl UnsizedCopy for f32

Source§

impl UnsizedCopy for f64

Source§

impl UnsizedCopy for i8

Source§

impl UnsizedCopy for i16

Source§

impl UnsizedCopy for i32

Source§

impl UnsizedCopy for i64

Source§

impl UnsizedCopy for i128

Source§

impl UnsizedCopy for isize

Source§

impl UnsizedCopy for str

Source§

impl UnsizedCopy for u8

Source§

impl UnsizedCopy for u16

Source§

impl UnsizedCopy for u32

Source§

impl UnsizedCopy for u64

Source§

impl UnsizedCopy for u128

Source§

impl UnsizedCopy for ()

Source§

impl UnsizedCopy for usize

Source§

impl<A: Copy, B: Copy, C: Copy, D: Copy, E: Copy, F: Copy, G: Copy, H: Copy, I: Copy, J: Copy, K: Copy, L: ?Sized + UnsizedCopy> UnsizedCopy for (A, B, C, D, E, F, G, H, I, J, K, L)

Source§

type Alignment = (A, B, C, D, E, F, G, H, I, J, K, <L as UnsizedCopy>::Alignment)

Source§

fn ptr_with_addr(&self, addr: *const ()) -> *const Self

Source§

impl<A: Copy, B: Copy, C: Copy, D: Copy, E: Copy, F: Copy, G: Copy, H: Copy, I: Copy, J: Copy, K: ?Sized + UnsizedCopy> UnsizedCopy for (A, B, C, D, E, F, G, H, I, J, K)

Source§

type Alignment = (A, B, C, D, E, F, G, H, I, J, <K as UnsizedCopy>::Alignment)

Source§

fn ptr_with_addr(&self, addr: *const ()) -> *const Self

Source§

impl<A: Copy, B: Copy, C: Copy, D: Copy, E: Copy, F: Copy, G: Copy, H: Copy, I: Copy, J: ?Sized + UnsizedCopy> UnsizedCopy for (A, B, C, D, E, F, G, H, I, J)

Source§

type Alignment = (A, B, C, D, E, F, G, H, I, <J as UnsizedCopy>::Alignment)

Source§

fn ptr_with_addr(&self, addr: *const ()) -> *const Self

Source§

impl<A: Copy, B: Copy, C: Copy, D: Copy, E: Copy, F: Copy, G: Copy, H: Copy, I: ?Sized + UnsizedCopy> UnsizedCopy for (A, B, C, D, E, F, G, H, I)

Source§

type Alignment = (A, B, C, D, E, F, G, H, <I as UnsizedCopy>::Alignment)

Source§

fn ptr_with_addr(&self, addr: *const ()) -> *const Self

Source§

impl<A: Copy, B: Copy, C: Copy, D: Copy, E: Copy, F: Copy, G: Copy, H: ?Sized + UnsizedCopy> UnsizedCopy for (A, B, C, D, E, F, G, H)

Source§

type Alignment = (A, B, C, D, E, F, G, <H as UnsizedCopy>::Alignment)

Source§

fn ptr_with_addr(&self, addr: *const ()) -> *const Self

Source§

impl<A: Copy, B: Copy, C: Copy, D: Copy, E: Copy, F: Copy, G: ?Sized + UnsizedCopy> UnsizedCopy for (A, B, C, D, E, F, G)

Source§

type Alignment = (A, B, C, D, E, F, <G as UnsizedCopy>::Alignment)

Source§

fn ptr_with_addr(&self, addr: *const ()) -> *const Self

Source§

impl<A: Copy, B: Copy, C: Copy, D: Copy, E: Copy, F: ?Sized + UnsizedCopy> UnsizedCopy for (A, B, C, D, E, F)

Source§

type Alignment = (A, B, C, D, E, <F as UnsizedCopy>::Alignment)

Source§

fn ptr_with_addr(&self, addr: *const ()) -> *const Self

Source§

impl<A: Copy, B: Copy, C: Copy, D: Copy, E: ?Sized + UnsizedCopy> UnsizedCopy for (A, B, C, D, E)

Source§

type Alignment = (A, B, C, D, <E as UnsizedCopy>::Alignment)

Source§

fn ptr_with_addr(&self, addr: *const ()) -> *const Self

Source§

impl<A: Copy, B: Copy, C: Copy, D: ?Sized + UnsizedCopy> UnsizedCopy for (A, B, C, D)

Source§

type Alignment = (A, B, C, <D as UnsizedCopy>::Alignment)

Source§

fn ptr_with_addr(&self, addr: *const ()) -> *const Self

Source§

impl<A: Copy, B: Copy, C: ?Sized + UnsizedCopy> UnsizedCopy for (A, B, C)

Source§

type Alignment = (A, B, <C as UnsizedCopy>::Alignment)

Source§

fn ptr_with_addr(&self, addr: *const ()) -> *const Self

Source§

impl<A: Copy, B: ?Sized + UnsizedCopy> UnsizedCopy for (A, B)

Source§

impl<A: ?Sized + UnsizedCopy> UnsizedCopy for (A,)

Source§

impl<T: UnsizedCopy> UnsizedCopy for [T]

Source§

impl<T: UnsizedCopy, const N: usize> UnsizedCopy for [T; N]

Source§

impl<T: ?Sized> UnsizedCopy for &T

Implementors§