Expand description

Library to safely and fallibly initialize pinned structs in-place.

It also allows in-place initialization of big structs that would otherwise produce a stack overflow.

The problem

When writing self referential data structures in Rust, one runs into the issue of initializing them. For example we will create an intrusive, doubly linked, circular list in Rust:

pub struct ListHead {
    next: NonNull<Self>,
    prev: NonNull<Self>,
    // ListHead is `!Unpin` because `next.prev = self`
    _pin: PhantomPinned,
}

But now, how would one go about creating a ListHead? A valid initial state of a singular ListHead is, with next and prev pointing to self. But in Rust we cannot get a hold of self until we have selected a value for next!

This library

This library provides the means to achieve this safely:

use simple_safe_init::*;

pub struct ListHead {
    next: NonNull<Self>,
    prev: NonNull<Self>,
    // ListHead is `!Unpin` because `next.prev = self`
    _pin: PhantomPinned,
}

impl ListHead {
    pub fn new_in_place() -> impl PinInit<Self> {
        pin_init!(&this in Self {
            next: this,
            prev: this,
            _pin: PhantomPinned,
        })
    }
}

Insead of writing new() -> Self we write new_in_place() -> impl PinInit<Self>. This function now returns an in-place initializer. The pin_init! macro used to create this initializer has the same syntax as a struct initializer. You will need to specify every field and can use arbitrary expressions. When an expression evaluates to an in-place initializer from this library, it is used to initialize the value in-place.

Macros

Construct an in-place initializer for structs.
Construct an in-place initializer for structs.
Initialize a type on the stack. It will be pinned:

Structs

A closure initializer.
A closure initializer for pinned data.

Enums

Either an allocation error, or an initialization error.

Traits

Smart pointer that can initialize memory in place.
An initializer for T.
An initializer for T.
Marker trait for types that can be initialized by writing just zeroes.

Functions

An initializer that leaves the memory uninitialized.
Create a new zeroed T