Skip to main content

zr/
pin_init.rs

1// Copyright 2026 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5/// A helper macro to initialize a pinned object in-place using a raw FFI constructor.
6///
7/// This generates a `PinInit` block that passes a type-cast pointer of the allocated
8/// slot to the FFI function, returning `Ok(())`.
9#[macro_export]
10macro_rules! pin_init_ffi {
11    ($ffi_fn:expr) => {
12        unsafe {
13            pin_init::pin_init_from_closure(|slot| {
14                let ptr = slot as *mut _ as *mut core::ffi::c_void;
15                $ffi_fn(ptr);
16                Ok(())
17            })
18        }
19    };
20    ($ffi_fn:expr, $($args:expr),+ $(,)?) => {
21        unsafe {
22            pin_init::pin_init_from_closure(move |slot| {
23                let ptr = slot as *mut _ as *mut core::ffi::c_void;
24                $ffi_fn(ptr, $($args),*);
25                Ok(())
26            })
27        }
28    };
29}
30
31/// A helper macro to implement `PinnedDrop` using a raw FFI destructor.
32///
33/// This generates a `PinnedDrop` implementation that calls the FFI function
34/// with a type-cast pointer of the object.
35///
36/// # Safety
37///
38/// The FFI function must take a pointer to the object and correctly clean it up.
39#[macro_export]
40macro_rules! unsafe_pinned_drop_ffi {
41    ($type:ty, $ffi_fn:expr) => {
42        #[pin_init::pinned_drop]
43        impl pin_init::PinnedDrop for $type {
44            fn drop(self: core::pin::Pin<&mut Self>) {
45                unsafe {
46                    let me = self.get_unchecked_mut();
47                    $ffi_fn(me.as_mut_ptr());
48                }
49            }
50        }
51    };
52}