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}