Library to safely and fallibly initialize pinned structs using in-place constructors.
It also allows in-place initialization of big structs that would otherwise produce a stack overflow.
Pinning is Rust's way of ensuring data does not move.
To initialize a struct with an in-place constructor you will need two things:
- an in-place constructor,
- a memory location that can hold your struct (this can be the stack, an Arc<T>
,
Box<T>
or any other smart pointer [^1]).
To get an in-place constructor there are generally two options: - directly creating an in-place constructor, - a function/macro returning an in-place constructor.
If you want to use PinInit
, then you will have to annotate your struct with #[pin_project]
.
It is a macro that uses #[pin]
as a marker for [structurally pinned fields].
```rust
struct Foo {
#[pin]
a: Mutex
let foo = pin_init!(Foo { a: Mutex::new(42), b: 24, }); ```
foo
now is of the type impl PinInit<Foo>
. We can now use any smart pointer that we like
(or just the stack) to actually initialize a Foo
:
rust
let foo: Result<Pin<Box<Foo>>, _> = Box::pin_init::<core::convert::Infallible>(foo);
Many types using this library supply a function/macro that returns an initializer, because the above method only works for types where you can access the fields.
rust
let mtx: Result<Pin<Arc<Mutex<usize>>>, _> = Arc::pin_init(Mutex::new(42));
To declare an init macro/function you just return an impl PinInit<T, E>
:
```rust
struct DriverData {
#[pin]
status: Mutex
impl DriverData {
fn new() -> impl PinInit