shared/shadow_type.rs
1#[macro_export]
2macro_rules! generate_shadow_type {
3 ($proxy_name:ident, $real_type:ty) => {
4 /// Opaque shadow type generated for FFI pointer boundaries.
5 #[repr(C)]
6 pub struct $proxy_name {
7 _private: [u8; 0], // Zero-sized type to prevent C instantiation but safe for raw pointers
8 }
9
10 impl $proxy_name {
11 /// Converts a real allocated instance into an opaque raw pointer handle.
12 ///
13 /// Note: This moves the real object onto the heap via Box to ensure its
14 /// memory remains valid after this function returns.
15 pub const fn from_real(real: &mut $real_type) -> *mut Self {
16 real as *mut $real_type as *mut Self
17 }
18
19 /// Consumes the opaque raw pointer handle and returns the original real type,
20 /// reclaiming ownership and freeing the underlying heap allocation.
21 ///
22 /// # Safety
23 /// The pointer must be non-null and must have been created by `from_real`.
24 #[inline]
25 pub unsafe fn into_real(ptr: *mut Self) -> *mut $real_type {
26 ptr as *mut $real_type
27 }
28
29 /// Temporarily borrows the real type immutably from the opaque pointer.
30 ///
31 /// # Safety
32 /// The pointer must be valid and dereferenceable for the duration of life 'a.
33 #[inline]
34 pub unsafe fn as_real<'a>(ptr: *const Self) -> &'a $real_type {
35 unsafe { &*(ptr as *const $real_type) }
36 }
37
38 /// Temporarily borrows the real type mutably from the opaque pointer.
39 ///
40 /// # Safety
41 /// The pointer must be valid, dereferenceable, and unaliased for the duration of life 'a.
42 #[inline]
43 pub unsafe fn as_real_mut<'a>(ptr: *mut Self) -> &'a mut $real_type {
44 unsafe { &mut *(ptr as *mut $real_type) }
45 }
46 }
47
48 impl core::ops::Deref for $proxy_name {
49 type Target = $real_type;
50
51 #[inline]
52 fn deref(&self) -> &Self::Target {
53 unsafe { Self::as_real(self as *const Self) }
54 }
55 }
56
57 impl core::ops::DerefMut for $proxy_name {
58 #[inline]
59 fn deref_mut(&mut self) -> &mut Self::Target {
60 unsafe { Self::as_real_mut(self as *mut Self) }
61 }
62 }
63
64 impl AsRef<$real_type> for $proxy_name {
65 #[inline]
66 fn as_ref(&self) -> &$real_type {
67 unsafe { Self::as_real(self as *const Self) }
68 }
69 }
70
71 impl AsMut<$real_type> for $proxy_name {
72 #[inline]
73 fn as_mut(&mut self) -> &mut $real_type {
74 unsafe { Self::as_real_mut(self as *mut Self) }
75 }
76 }
77 };
78}