[][src]Trait thin::Thinnable

pub unsafe trait Thinnable {
    type Head: Sized;
    type SliceItem: Sized;
    fn get_length(head: &Self::Head) -> usize;
fn make_fat(ptr: *mut [Erased]) -> *mut Self; fn make_thin(fat: NonNull<Self>) -> NonNull<Erased> { ... }
unsafe fn make_fat_const(thin: NonNull<Erased>) -> NonNull<Self> { ... }
unsafe fn make_fat_mut(thin: NonNull<Erased>) -> NonNull<Self> { ... } }

Types that hold an inline slice and the length of that slice in the same allocation.

Example

Consider an Arc-tree node:

struct Node {
    data: Data,
    children: Vec<Arc<Node>>
}

This incurs a double indirection: once to the node and once to the children, even though Node may always only be exposed behind an Arc.

Instead, you can store the children slice inline with the data allocation:

#[repr(C)]
struct Node {
    data: Data, // MUST include length of the following slice!
    children: [Arc<Node>],
}

unsafe impl Thinnable for Node {
    type Head = Data;
    type SliceItem = Arc<Node>;

    make_fat!();
    fn get_length(head: &Data) -> usize {
        head.children_len
    }
}

&Node and Arc<Node> will be like &[_] and Arc<[_]>; a fat (pointer, length) pair. You can also use thin::Box and thin::Arc to get owned thin pointers. These types are also how you allocate a type defined like this.

The type MUST be #[repr(C)] and composed of just a head the slice tail, otherwise arbitrary functionality of this crate may cause undefined behavior.

Associated Types

type Head: Sized

The sized part of the allocation.

type SliceItem: Sized

The item type of the slice part of the allocation.

Loading content...

Required methods

fn get_length(head: &Self::Head) -> usize

Extract the slice length from the head.

fn make_fat(ptr: *mut [Erased]) -> *mut Self

Make a fat pointer from an erased one.

This is implemented by calling make_fat!().

Note that the input erased pointer is not actually a thin pointer; make_fat_const and make_fat_mut take a thin erased pointer.

Loading content...

Provided methods

fn make_thin(fat: NonNull<Self>) -> NonNull<Erased>

Make an erased thin pointer from a fat one.

unsafe fn make_fat_const(thin: NonNull<Erased>) -> NonNull<Self>

Make a fat pointer from an erased one, using *const functions.

Safety

thin must be a valid erased pointer to Self.

This materializes a &-reference on stable, thus unique mutation after using this function is not necessarily allowed. Use make_fat_mut instead if you have unique access.

unsafe fn make_fat_mut(thin: NonNull<Erased>) -> NonNull<Self>

Make a fat pointer from an erased one, using *mut functions.

Safety

thin must be a valid erased pointer to Self.

This materializes a &mut-reference on stable, thus should only be used when the thin pointer is sourced from a unique borrow. Use make_fat_const instead if you have shared access.

Loading content...

Implementors

impl<T> Thinnable for ThinSlice<T>[src]

type Head = usize

type SliceItem = T

Loading content...