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}