uniffi_core 0.32.1

a multi-language bindings generator for rust (runtime support code)
Documentation
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use std::{fmt, sync::Arc};

/// Object handle
///
/// Handles opaque `u64` values used to pass objects across the FFI, both for objects implemented in
/// Rust and ones implemented in the foreign language.
///
/// Rust handles are generated by leaking a raw pointer
/// Foreign handles are generated with a handle map that only generates odd values.
/// For all currently supported architectures and hopefully any ones we add in the future:
/// * 0 is an invalid value.
/// * The lowest bit will always be set for foreign handles and never set for Rust ones (since the
///   leaked pointer will be aligned to `size_of::<Arc<T>>()` == `size_of::<*const T>()`).
///
/// Rust handles are mainly managed is through the [crate::HandleAlloc] trait.
#[derive(Clone, Default, PartialEq, Eq)]
#[repr(transparent)]
pub struct Handle(u64);

impl Handle {
    pub fn from_pointer<T>(ptr: *const T) -> Self {
        Self(ptr as u64)
    }

    pub fn as_pointer<T>(&self) -> *const T {
        self.0 as *const T
    }

    /// Was this handle generated by the foreign side of the FFI?
    pub fn is_foreign(&self) -> bool {
        // Foreign handles have the lowest bit set.
        // We know that Rust handles will never have this set, since the pointers that they're cast from have alignment > 1;
        // https://mozilla.github.io/uniffi-rs/latest/internals/object_references.html
        (self.0 & 1) == 1
    }

    /// # Safety
    /// The raw value must be a valid handle as described above.
    pub unsafe fn from_raw(raw: u64) -> Option<Self> {
        if raw == 0 {
            None
        } else {
            Some(Self(raw))
        }
    }

    pub fn from_raw_unchecked(raw: u64) -> Self {
        Self(raw)
    }

    pub fn as_raw(&self) -> u64 {
        self.0
    }

    /// Create a handle from an Arc
    pub fn from_arc<T>(arc: Arc<T>) -> Self {
        Self::from_pointer(Arc::into_raw(arc))
    }

    /// Re-create an Arc from a handle
    ///
    /// # Safety
    ///
    /// * The handle must have been created from `Handle::from_arc`.
    /// * The handle must only be used once
    pub unsafe fn into_arc<T>(self) -> Arc<T> {
        Arc::from_raw(self.as_pointer())
    }

    /// Re-create an Arc from a borrowed handle
    ///
    /// "borrowed" means a handle sent from the other side of the FFI without cloning it first.
    /// Be very careful with using this, since it's easy to introduce races.
    /// The one scenario this is currently used for is futures, since we can guarantee that the
    /// foreign side will not drop the future while in the middle of polling/cancelling it.
    ///
    /// # Safety
    ///
    /// * The handle must have been created from `Handle::from_arc`.
    /// * There must be no possibility for the handle to be dropped before the function the
    ///   borrowed handle is passed to returns.
    pub unsafe fn into_arc_borrowed<T>(self) -> Arc<T> {
        self.clone_arc_handle::<T>();
        Arc::from_raw(self.as_pointer())
    }

    /// Clone a handle for an Arc
    ///
    /// # Safety
    ///
    /// The handle must have been created from `Handle::from_arc`.
    pub unsafe fn clone_arc_handle<T>(&self) -> Self {
        Arc::increment_strong_count(self.as_pointer::<T>());
        // This is safe because we just incremented the refcount.
        Self(self.0)
    }
}

impl fmt::Debug for Handle {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "Handle(0x{:x})", self.0)
    }
}