1[![Crates.io](https://img.shields.io/crates/v/pin-init.svg)](https://crates.io/crates/pin-init)
2[![Documentation](https://docs.rs/pin-init/badge.svg)](https://docs.rs/pin-init/)
3[![Dependency status](https://deps.rs/repo/github/Rust-for-Linux/pin-init/status.svg)](https://deps.rs/repo/github/Rust-for-Linux/pin-init)
4![License](https://img.shields.io/crates/l/pin-init)
5[![Toolchain](https://img.shields.io/badge/toolchain-nightly-red)](#nightly-only)
6![GitHub Workflow Status](https://img.shields.io/github/actions/workflow/status/Rust-for-Linux/pin-init/test.yml)
7# `pin-init`
8
9<!-- cargo-rdme start -->
10
11Library to safely and fallibly initialize pinned `struct`s using in-place constructors.
12
13[Pinning][pinning] is Rust's way of ensuring data does not move.
14
15It also allows in-place initialization of big `struct`s that would otherwise produce a stack
16overflow.
17
18This library's main use-case is in [Rust-for-Linux]. Although this version can be used
19standalone.
20
21There are cases when you want to in-place initialize a struct. For example when it is very big
22and moving it from the stack is not an option, because it is bigger than the stack itself.
23Another reason would be that you need the address of the object to initialize it. This stands
24in direct conflict with Rust's normal process of first initializing an object and then moving
25it into it's final memory location. For more information, see
26<https://rust-for-linux.com/the-safe-pinned-initialization-problem>.
27
28This library allows you to do in-place initialization safely.
29
30### Nightly Needed for `alloc` feature
31
32This library requires the [`allocator_api` unstable feature] when the `alloc` feature is
33enabled and thus this feature can only be used with a nightly compiler. When enabling the
34`alloc` feature, the user will be required to activate `allocator_api` as well.
35
36[`allocator_api` unstable feature]: https://doc.rust-lang.org/nightly/unstable-book/library-features/allocator-api.html
37
38The feature is enabled by default, thus by default `pin-init` will require a nightly compiler.
39However, using the crate on stable compilers is possible by disabling `alloc`. In practice this
40will require the `std` feature, because stable compilers have neither `Box` nor `Arc` in no-std
41mode.
42
43## Overview
44
45To initialize a `struct` with an in-place constructor you will need two things:
46- an in-place constructor,
47- a memory location that can hold your `struct` (this can be the [stack], an [`Arc<T>`],
48  [`Box<T>`] or any other smart pointer that supports this library).
49
50To get an in-place constructor there are generally three options:
51- directly creating an in-place constructor using the [`pin_init!`] macro,
52- a custom function/macro returning an in-place constructor provided by someone else,
53- using the unsafe function [`pin_init_from_closure()`] to manually create an initializer.
54
55Aside from pinned initialization, this library also supports in-place construction without
56pinning, the macros/types/functions are generally named like the pinned variants without the
57`pin_` prefix.
58
59## Examples
60
61Throughout the examples we will often make use of the `CMutex` type which can be found in
62`../examples/mutex.rs`. It is essentially a userland rebuild of the `struct mutex` type from
63the Linux kernel. It also uses a wait list and a basic spinlock. Importantly the wait list
64requires it to be pinned to be locked and thus is a prime candidate for using this library.
65
66### Using the [`pin_init!`] macro
67
68If you want to use [`PinInit`], then you will have to annotate your `struct` with
69`#[`[`pin_data`]`]`. It is a macro that uses `#[pin]` as a marker for
70[structurally pinned fields]. After doing this, you can then create an in-place constructor via
71[`pin_init!`]. The syntax is almost the same as normal `struct` initializers. The difference is
72that you need to write `<-` instead of `:` for fields that you want to initialize in-place.
73
74```rust
75use pin_init::{pin_data, pin_init, InPlaceInit};
76
77#[pin_data]
78struct Foo {
79    #[pin]
80    a: CMutex<usize>,
81    b: u32,
82}
83
84let foo = pin_init!(Foo {
85    a <- CMutex::new(42),
86    b: 24,
87});
88```
89
90`foo` now is of the type [`impl PinInit<Foo>`]. We can now use any smart pointer that we like
91(or just the stack) to actually initialize a `Foo`:
92
93```rust
94let foo: Result<Pin<Box<Foo>>, AllocError> = Box::pin_init(foo);
95```
96
97For more information see the [`pin_init!`] macro.
98
99### Using a custom function/macro that returns an initializer
100
101Many types that use this library supply a function/macro that returns an initializer, because
102the above method only works for types where you can access the fields.
103
104```rust
105let mtx: Result<Pin<Arc<CMutex<usize>>>, _> = Arc::pin_init(CMutex::new(42));
106```
107
108To declare an init macro/function you just return an [`impl PinInit<T, E>`]:
109
110```rust
111#[pin_data]
112struct DriverData {
113    #[pin]
114    status: CMutex<i32>,
115    buffer: Box<[u8; 1_000_000]>,
116}
117
118impl DriverData {
119    fn new() -> impl PinInit<Self, Error> {
120        try_pin_init!(Self {
121            status <- CMutex::new(0),
122            buffer: Box::init(pin_init::zeroed())?,
123        }? Error)
124    }
125}
126```
127
128### Manual creation of an initializer
129
130Often when working with primitives the previous approaches are not sufficient. That is where
131[`pin_init_from_closure()`] comes in. This `unsafe` function allows you to create a
132[`impl PinInit<T, E>`] directly from a closure. Of course you have to ensure that the closure
133actually does the initialization in the correct way. Here are the things to look out for
134(we are calling the parameter to the closure `slot`):
135- when the closure returns `Ok(())`, then it has completed the initialization successfully, so
136  `slot` now contains a valid bit pattern for the type `T`,
137- when the closure returns `Err(e)`, then the caller may deallocate the memory at `slot`, so
138  you need to take care to clean up anything if your initialization fails mid-way,
139- you may assume that `slot` will stay pinned even after the closure returns until `drop` of
140  `slot` gets called.
141
142```rust
143use pin_init::{pin_data, pinned_drop, PinInit, PinnedDrop, pin_init_from_closure};
144use core::{
145    ptr::addr_of_mut,
146    marker::PhantomPinned,
147    cell::UnsafeCell,
148    pin::Pin,
149    mem::MaybeUninit,
150};
151mod bindings {
152    #[repr(C)]
153    pub struct foo {
154        /* fields from C ... */
155    }
156    extern "C" {
157        pub fn init_foo(ptr: *mut foo);
158        pub fn destroy_foo(ptr: *mut foo);
159        #[must_use = "you must check the error return code"]
160        pub fn enable_foo(ptr: *mut foo, flags: u32) -> i32;
161    }
162}
163
164/// # Invariants
165///
166/// `foo` is always initialized
167#[pin_data(PinnedDrop)]
168pub struct RawFoo {
169    #[pin]
170    _p: PhantomPinned,
171    #[pin]
172    foo: UnsafeCell<MaybeUninit<bindings::foo>>,
173}
174
175impl RawFoo {
176    pub fn new(flags: u32) -> impl PinInit<Self, i32> {
177        // SAFETY:
178        // - when the closure returns `Ok(())`, then it has successfully initialized and
179        //   enabled `foo`,
180        // - when it returns `Err(e)`, then it has cleaned up before
181        unsafe {
182            pin_init_from_closure(move |slot: *mut Self| {
183                // `slot` contains uninit memory, avoid creating a reference.
184                let foo = addr_of_mut!((*slot).foo);
185                let foo = UnsafeCell::raw_get(foo).cast::<bindings::foo>();
186
187                // Initialize the `foo`
188                bindings::init_foo(foo);
189
190                // Try to enable it.
191                let err = bindings::enable_foo(foo, flags);
192                if err != 0 {
193                    // Enabling has failed, first clean up the foo and then return the error.
194                    bindings::destroy_foo(foo);
195                    Err(err)
196                } else {
197                    // All fields of `RawFoo` have been initialized, since `_p` is a ZST.
198                    Ok(())
199                }
200            })
201        }
202    }
203}
204
205#[pinned_drop]
206impl PinnedDrop for RawFoo {
207    fn drop(self: Pin<&mut Self>) {
208        // SAFETY: Since `foo` is initialized, destroying is safe.
209        unsafe { bindings::destroy_foo(self.foo.get().cast::<bindings::foo>()) };
210    }
211}
212```
213
214For more information on how to use [`pin_init_from_closure()`], take a look at the uses inside
215the `kernel` crate. The [`sync`] module is a good starting point.
216
217[`sync`]: https://rust.docs.kernel.org/kernel/sync/index.html
218[pinning]: https://doc.rust-lang.org/std/pin/index.html
219[structurally pinned fields]: https://doc.rust-lang.org/std/pin/index.html#pinning-is-structural-for-field
220[stack]: https://docs.rs/pin-init/latest/pin_init/macro.stack_pin_init.html
221[`Arc<T>`]: https://doc.rust-lang.org/stable/alloc/sync/struct.Arc.html
222[`Box<T>`]: https://doc.rust-lang.org/stable/alloc/boxed/struct.Box.html
223[`impl PinInit<Foo>`]: https://docs.rs/pin-init/latest/pin_init/trait.PinInit.html
224[`impl PinInit<T, E>`]: https://docs.rs/pin-init/latest/pin_init/trait.PinInit.html
225[`impl Init<T, E>`]: https://docs.rs/pin-init/latest/pin_init/trait.Init.html
226[Rust-for-Linux]: https://rust-for-linux.com/
227
228<!-- cargo-rdme end -->
229