uniffi_core/ffi/handle.rs
1/* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4
5use std::{fmt, sync::Arc};
6
7/// Object handle
8///
9/// Handles opaque `u64` values used to pass objects across the FFI, both for objects implemented in
10/// Rust and ones implemented in the foreign language.
11///
12/// Rust handles are generated by leaking a raw pointer
13/// Foreign handles are generated with a handle map that only generates odd values.
14/// For all currently supported architectures and hopefully any ones we add in the future:
15/// * 0 is an invalid value.
16/// * The lowest bit will always be set for foreign handles and never set for Rust ones (since the
17/// leaked pointer will be aligned to `size_of::<Arc<T>>()` == `size_of::<*const T>()`).
18///
19/// Rust handles are mainly managed is through the [crate::HandleAlloc] trait.
20#[derive(Clone, Default, PartialEq, Eq)]
21#[repr(transparent)]
22pub struct Handle(u64);
23
24impl Handle {
25 pub fn from_pointer<T>(ptr: *const T) -> Self {
26 Self(ptr as u64)
27 }
28
29 pub fn as_pointer<T>(&self) -> *const T {
30 self.0 as *const T
31 }
32
33 /// Was this handle generated by the foreign side of the FFI?
34 pub fn is_foreign(&self) -> bool {
35 // Foreign handles have the lowest bit set.
36 // We know that Rust handles will never have this set, since the pointers that they're cast from have alignment > 1;
37 // https://mozilla.github.io/uniffi-rs/latest/internals/object_references.html
38 (self.0 & 1) == 1
39 }
40
41 /// # Safety
42 /// The raw value must be a valid handle as described above.
43 pub unsafe fn from_raw(raw: u64) -> Option<Self> {
44 if raw == 0 {
45 None
46 } else {
47 Some(Self(raw))
48 }
49 }
50
51 pub fn from_raw_unchecked(raw: u64) -> Self {
52 Self(raw)
53 }
54
55 pub fn as_raw(&self) -> u64 {
56 self.0
57 }
58
59 /// Create a handle from an Arc
60 pub fn from_arc<T>(arc: Arc<T>) -> Self {
61 Self::from_pointer(Arc::into_raw(arc))
62 }
63
64 /// Re-create an Arc from a handle
65 ///
66 /// # Safety
67 ///
68 /// * The handle must have been created from `Handle::from_arc`.
69 /// * The handle must only be used once
70 pub unsafe fn into_arc<T>(self) -> Arc<T> {
71 Arc::from_raw(self.as_pointer())
72 }
73
74 /// Re-create an Arc from a borrowed handle
75 ///
76 /// "borrowed" means a handle sent from the other side of the FFI without cloning it first.
77 /// Be very careful with using this, since it's easy to introduce races.
78 /// The one scenario this is currently used for is futures, since we can guarantee that the
79 /// foreign side will not drop the future while in the middle of polling/cancelling it.
80 ///
81 /// # Safety
82 ///
83 /// * The handle must have been created from `Handle::from_arc`.
84 /// * There must be no possibility for the handle to be dropped before the function the
85 /// borrowed handle is passed to returns.
86 pub unsafe fn into_arc_borrowed<T>(self) -> Arc<T> {
87 self.clone_arc_handle::<T>();
88 Arc::from_raw(self.as_pointer())
89 }
90
91 /// Clone a handle for an Arc
92 ///
93 /// # Safety
94 ///
95 /// The handle must have been created from `Handle::from_arc`.
96 pub unsafe fn clone_arc_handle<T>(&self) -> Self {
97 Arc::increment_strong_count(self.as_pointer::<T>());
98 // This is safe because we just incremented the refcount.
99 Self(self.0)
100 }
101}
102
103impl fmt::Debug for Handle {
104 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
105 write!(f, "Handle(0x{:x})", self.0)
106 }
107}