pinned_init_macro/
lib.rs

1mod pin_data;
2mod pinned_drop;
3mod zeroable;
4
5use proc_macro::TokenStream;
6
7/// Used to specify the pinning information of the fields of a struct.
8///
9/// This is somewhat similar in purpose as
10/// [pin-project-lite](https://crates.io/crates/pin-project-lite).
11/// Place this macro on a struct definition and then `#[pin]` in front of the attributes of each
12/// field you want to have structurally pinned.
13///
14/// This macro enables the use of the [`pin_init!`] macro. When pinned-initializing a `struct`,
15/// then `#[pin]` directs the type of intializer that is required.
16///
17/// If your `struct` implements `Drop`, then you need to add `PinnedDrop` as arguments to this
18/// macro, and change your `Drop` implementation to `PinnedDrop` annotated with
19/// `#[`[`macro@pinned_drop`]`]`, since dropping pinned values requires extra care.
20///
21/// # Examples
22///
23/// ```rust,ignore
24/// #[pin_data]
25/// struct DriverData {
26///     #[pin]
27///     queue: Mutex<Vec<Command>>,
28///     buf: Box<[u8; 1024 * 1024]>,
29/// }
30/// ```
31///
32/// ```rust,ignore
33/// #[pin_data(PinnedDrop)]
34/// struct DriverData {
35///     #[pin]
36///     queue: Mutex<Vec<Command>>,
37///     buf: Box<[u8; 1024 * 1024]>,
38///     raw_info: *mut Info,
39/// }
40///
41/// #[pinned_drop]
42/// impl PinnedDrop for DriverData {
43///     fn drop(self: Pin<&mut Self>) {
44///         unsafe { bindings::destroy_info(self.raw_info) };
45///     }
46/// }
47/// ```
48///
49/// [`pin_init!`]: ../pinned_init/macro.pin_init.html
50//  ^ cannot use direct link, since `kernel` is not a dependency of `macros`
51#[proc_macro_attribute]
52pub fn pin_data(inner: TokenStream, item: TokenStream) -> TokenStream {
53    pin_data::pin_data(inner, item)
54}
55
56/// Used to implement `PinnedDrop` safely.
57///
58/// Only works on structs that are annotated via `#[`[`macro@pin_data`]`]`.
59///
60/// # Examples
61///
62/// ```rust,ignore
63/// #[pin_data(PinnedDrop)]
64/// struct DriverData {
65///     #[pin]
66///     queue: Mutex<Vec<Command>>,
67///     buf: Box<[u8; 1024 * 1024]>,
68///     raw_info: *mut Info,
69/// }
70///
71/// #[pinned_drop]
72/// impl PinnedDrop for DriverData {
73///     fn drop(self: Pin<&mut Self>) {
74///         unsafe { bindings::destroy_info(self.raw_info) };
75///     }
76/// }
77/// ```
78#[proc_macro_attribute]
79pub fn pinned_drop(args: TokenStream, input: TokenStream) -> TokenStream {
80    pinned_drop::pinned_drop(args, input)
81}
82
83/// Derives the [`Zeroable`] trait for the given struct.
84///
85/// This can only be used for structs where every field implements the [`Zeroable`] trait.
86///
87/// # Examples
88///
89/// ```rust,ignore
90/// #[derive(Zeroable)]
91/// pub struct DriverData {
92///     id: i64,
93///     buf_ptr: *mut u8,
94///     len: usize,
95/// }
96/// ```
97#[proc_macro_derive(Zeroable)]
98pub fn derive_zeroable(input: TokenStream) -> TokenStream {
99    zeroable::derive(input.into()).into()
100}