Skip to main content

rusteal_ffi/
handles.rs

1use std::ffi::c_void;
2
3// ---------------------------------------------------------------------------
4// Macro: define a pointer-based handle (opaque C++ side identifier).
5// ---------------------------------------------------------------------------
6
7macro_rules! define_ptr_handle {
8    ($(#[$meta:meta])* $name:ident) => {
9        $(#[$meta])*
10        #[repr(transparent)]
11        #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
12        pub struct $name(pub *mut c_void);
13
14        impl $name {
15            pub fn is_null(&self) -> bool {
16                self.0.is_null()
17            }
18
19            pub fn null() -> Self {
20                Self(std::ptr::null_mut())
21            }
22
23            /// Create from a raw u64 address (platform-agnostic byte-level construction).
24            pub fn from_addr(addr: u64) -> Self {
25                Self(addr as usize as *mut c_void)
26            }
27
28            /// Convert to a raw u64 address (platform-agnostic byte-level extraction).
29            pub fn to_addr(&self) -> u64 {
30                self.0 as usize as u64
31            }
32        }
33    };
34}
35
36define_ptr_handle! {
37    /// Opaque handle to a UObject. Rust never dereferences — it is a C++ side identifier.
38    UObjectHandle
39}
40
41define_ptr_handle! {
42    /// Opaque handle to a UClass.
43    UClassHandle
44}
45
46define_ptr_handle! {
47    /// Opaque handle to an FProperty.
48    FPropertyHandle
49}
50
51define_ptr_handle! {
52    /// Opaque handle to a UFunction. Only used for reify (Phase 9);
53    /// normal function calls go through func_table.
54    UFunctionHandle
55}
56
57define_ptr_handle! {
58    /// Opaque handle to a UScriptStruct.
59    UStructHandle
60}
61
62/// FName stored as a raw 64-bit value (ComparisonIndex + Number).
63#[repr(transparent)]
64#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, Default)]
65pub struct FNameHandle(pub u64);
66
67/// Weak object pointer: ObjectIndex + ObjectSerialNumber (matches UE FWeakObjectPtr layout).
68#[repr(C)]
69#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
70pub struct FWeakObjectHandle {
71    pub object_index: i32,
72    pub object_serial_number: i32,
73}
74
75impl Default for FWeakObjectHandle {
76    fn default() -> Self {
77        FWeakObjectHandle {
78            object_index: -1,
79            object_serial_number: 0,
80        }
81    }
82}
83
84// Handles are raw FFI identifiers. They can be sent across threads
85// (but must only be *used* on the game thread).
86// Sync is needed for OnceLock caching in generated code.
87unsafe impl Send for UObjectHandle {}
88unsafe impl Sync for UObjectHandle {}
89unsafe impl Send for UClassHandle {}
90unsafe impl Sync for UClassHandle {}
91unsafe impl Send for FPropertyHandle {}
92unsafe impl Sync for FPropertyHandle {}
93unsafe impl Send for UFunctionHandle {}
94unsafe impl Sync for UFunctionHandle {}
95unsafe impl Send for UStructHandle {}
96unsafe impl Sync for UStructHandle {}
97unsafe impl Send for FWeakObjectHandle {}
98unsafe impl Sync for FWeakObjectHandle {}