diff --git a/components/style/gecko_bindings/sugar/ownership.rs b/components/style/gecko_bindings/sugar/ownership.rs index edd8394f31c..abcf5c65a8a 100644 --- a/components/style/gecko_bindings/sugar/ownership.rs +++ b/components/style/gecko_bindings/sugar/ownership.rs @@ -2,50 +2,52 @@ * 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/. */ +//! Helpers for different FFI pointer kinds that Gecko's FFI layer uses. + use std::marker::PhantomData; use std::mem::{forget, transmute}; use std::ops::{Deref, DerefMut}; use std::ptr; use std::sync::Arc; -/// Indicates that a given Servo type has a corresponding -/// Gecko FFI type -/// The correspondence is not defined at this stage, -/// use HasArcFFI or similar traits to define it +/// Indicates that a given Servo type has a corresponding Gecko FFI type. pub unsafe trait HasFFI : Sized { + /// The corresponding Gecko type that this rust type represents. + /// + /// See the examples in `components/style/gecko/conversions.rs`. type FFIType: Sized; } -/// Indicates that a given Servo type has the same layout -/// as the corresponding HasFFI::FFIType type +/// Indicates that a given Servo type has the same layout as the corresponding +/// `HasFFI::FFIType` type. pub unsafe trait HasSimpleFFI : HasFFI { #[inline] - /// Given a Servo-side reference, converts it to an - /// FFI-safe reference which can be passed to Gecko + /// Given a Servo-side reference, converts it to an FFI-safe reference which + /// can be passed to Gecko. /// /// &ServoType -> &GeckoType fn as_ffi(&self) -> &Self::FFIType { unsafe { transmute(self) } } #[inline] - /// Given a Servo-side mutable reference, converts it to an - /// FFI-safe mutable reference which can be passed to Gecko + /// Given a Servo-side mutable reference, converts it to an FFI-safe mutable + /// reference which can be passed to Gecko. /// /// &mut ServoType -> &mut GeckoType fn as_ffi_mut(&mut self) -> &mut Self::FFIType { unsafe { transmute(self) } } #[inline] - /// Given an FFI-safe reference obtained from Gecko - /// converts it to a Servo-side reference + /// Given an FFI-safe reference obtained from Gecko converts it to a + /// Servo-side reference. /// /// &GeckoType -> &ServoType fn from_ffi(ffi: &Self::FFIType) -> &Self { unsafe { transmute(ffi) } } #[inline] - /// Given an FFI-safe mutable reference obtained from Gecko - /// converts it to a Servo-side mutable reference + /// Given an FFI-safe mutable reference obtained from Gecko converts it to a + /// Servo-side mutable reference. /// /// &mut GeckoType -> &mut ServoType fn from_ffi_mut(ffi: &mut Self::FFIType) -> &mut Self { @@ -57,6 +59,9 @@ pub unsafe trait HasSimpleFFI : HasFFI { /// as a Box pub unsafe trait HasBoxFFI : HasSimpleFFI { #[inline] + /// Converts a borrowed Arc to a borrowed FFI reference. + /// + /// &Arc -> &GeckoType fn into_ffi(self: Box) -> Owned { unsafe { transmute(self) } } @@ -64,14 +69,15 @@ pub unsafe trait HasBoxFFI : HasSimpleFFI { /// Helper trait for conversions between FFI Strong/Borrowed types and Arcs /// -/// Should be implemented by types which are passed over FFI as Arcs -/// via Strong and Borrowed +/// Should be implemented by types which are passed over FFI as Arcs via Strong +/// and Borrowed. /// -/// In this case, the FFIType is the rough equivalent of ArcInner +/// In this case, the FFIType is the rough equivalent of ArcInner. pub unsafe trait HasArcFFI : HasFFI { // these methods can't be on Borrowed because it leads to an unspecified // impl parameter - /// Artificially increments the refcount of a (possibly null) borrowed Arc over FFI. + /// Artificially increments the refcount of a (possibly null) borrowed Arc + /// over FFI. unsafe fn addref_opt(ptr: Option<&Self::FFIType>) { forget(Self::arc_from_borrowed(&ptr).clone()) } @@ -109,6 +115,10 @@ pub unsafe trait HasArcFFI : HasFFI { } } + #[inline] + /// Converts a borrowed Arc to a borrowed FFI reference. + /// + /// &Arc -> &GeckoType fn arc_as_borrowed<'a>(arc: &'a Arc) -> &'a &Self::FFIType { unsafe { transmute::<&Arc, &&Self::FFIType>(arc) @@ -116,6 +126,9 @@ pub unsafe trait HasArcFFI : HasFFI { } #[inline] + /// Converts a borrowed nullable FFI reference to a borrowed Arc. + /// + /// &GeckoType -> &Arc fn arc_from_borrowed<'a>(ptr: &'a Option<&Self::FFIType>) -> Option<&'a Arc> { unsafe { if let Some(ref reference) = *ptr { @@ -129,27 +142,32 @@ pub unsafe trait HasArcFFI : HasFFI { #[repr(C)] /// Gecko-FFI-safe Arc (T is an ArcInner). +/// /// This can be null. +/// /// Leaks on drop. Please don't drop this. -/// TODO: Add destructor bomb once drop flags are gone -pub struct Strong { - ptr: *const T, - _marker: PhantomData, +pub struct Strong { + ptr: *const GeckoType, + _marker: PhantomData, } -impl Strong { +impl Strong { #[inline] + /// Returns whether this reference is null. pub fn is_null(&self) -> bool { - self.ptr == ptr::null() + self.ptr.is_null() } #[inline] - /// Given a non-null strong FFI reference, - /// converts it into a servo-side Arc + /// Given a non-null strong FFI reference, converts it into a servo-side + /// Arc. + /// /// Panics on null. /// /// Strong -> Arc - pub fn into_arc(self) -> Arc where U: HasArcFFI { + pub fn into_arc(self) -> Arc + where ServoType: HasArcFFI, + { self.into_arc_opt().unwrap() } @@ -159,7 +177,9 @@ impl Strong { /// Returns None on null. /// /// Strong -> Arc - pub fn into_arc_opt(self) -> Option> where U: HasArcFFI { + pub fn into_arc_opt(self) -> Option> + where ServoType: HasArcFFI, + { if self.is_null() { None } else { @@ -168,12 +188,15 @@ impl Strong { } #[inline] - /// Given a reference to a strong FFI reference, - /// converts it to a reference to a servo-side Arc + /// Given a reference to a strong FFI reference, converts it to a reference + /// to a servo-side Arc. + /// /// Returns None on null. /// /// Strong -> Arc - pub fn as_arc_opt(&self) -> Option<&Arc> where U: HasArcFFI { + pub fn as_arc_opt(&self) -> Option<&Arc> + where ServoType: HasArcFFI, + { if self.is_null() { None } else { @@ -182,30 +205,42 @@ impl Strong { } #[inline] - /// Produces a null strong FFI reference + /// Produces a null strong FFI reference. pub fn null() -> Self { - unsafe { transmute(ptr::null::()) } + unsafe { transmute(ptr::null::()) } } } +/// A few helpers implemented on top of Arc to make it more +/// comfortable to use and write safe code with. pub unsafe trait FFIArcHelpers { + /// The Rust FFI type that we're implementing methods for. type Inner: HasArcFFI; + /// Converts an Arc into a strong FFI reference. /// /// Arc -> Strong fn into_strong(self) -> Strong<::FFIType>; + /// Produces a (nullable) borrowed FFI reference by borrowing an Arc. /// /// &Arc -> Option<&GeckoType> + /// + /// FIXME(emilio): What's the point of the nullability? Arc should be + /// non-null, right? + /// + /// Then the `arc_as_borrowed` method can go away. fn as_borrowed_opt(&self) -> Option<&::FFIType>; } unsafe impl FFIArcHelpers for Arc { type Inner = T; + #[inline] fn into_strong(self) -> Strong { unsafe { transmute(self) } } + #[inline] fn as_borrowed_opt(&self) -> Option<&T::FFIType> { let borrowedptr = self as *const Arc as *const Option<&T::FFIType>; @@ -215,51 +250,62 @@ unsafe impl FFIArcHelpers for Arc { #[repr(C)] #[derive(Debug)] -/// Gecko-FFI-safe owned pointer -/// Cannot be null -/// Leaks on drop. Please don't drop this. -pub struct Owned { - ptr: *mut T, - _marker: PhantomData, +/// Gecko-FFI-safe owned pointer. +/// +/// Cannot be null, and leaks on drop, so needs to be converted into a rust-side +/// `Box` before. +pub struct Owned { + ptr: *mut GeckoType, + _marker: PhantomData, } -impl Owned { - /// Owned -> Box - pub fn into_box(self) -> Box where U: HasBoxFFI { +impl Owned { + /// Gets this `Owned` type as a `Box`. + pub fn into_box(self) -> Box + where ServoType: HasBoxFFI, + { unsafe { transmute(self) } } - pub fn maybe(self) -> OwnedOrNull { + + /// Converts this instance to a (non-null) instance of `OwnedOrNull`. + pub fn maybe(self) -> OwnedOrNull { unsafe { transmute(self) } } } -impl Deref for Owned { - type Target = T; - fn deref(&self) -> &T { +impl Deref for Owned { + type Target = GeckoType; + fn deref(&self) -> &GeckoType { unsafe { &*self.ptr } } } -impl DerefMut for Owned { - fn deref_mut(&mut self) -> &mut T { +impl DerefMut for Owned { + fn deref_mut(&mut self) -> &mut GeckoType { unsafe { &mut *self.ptr } } } #[repr(C)] -/// Gecko-FFI-safe owned pointer -/// Can be null -pub struct OwnedOrNull { - ptr: *mut T, - _marker: PhantomData, +/// Gecko-FFI-safe owned pointer. +/// +/// Can be null, and just as `Owned` leaks on `Drop`. +pub struct OwnedOrNull { + ptr: *mut GeckoType, + _marker: PhantomData, } -impl OwnedOrNull { +impl OwnedOrNull { + /// Returns whether this pointer is null. + #[inline] pub fn is_null(&self) -> bool { - self.ptr == ptr::null_mut() + self.ptr.is_null() } - /// OwnedOrNull -> Option> - pub fn into_box_opt(self) -> Option> where U: HasBoxFFI { + + /// Returns an owned pointer if this is non-null, and `None` otherwise. + pub fn into_box_opt(self) -> Option> + where ServoType: HasBoxFFI, + { if self.is_null() { None } else { @@ -267,8 +313,8 @@ impl OwnedOrNull { } } - /// OwnedOrNull -> Option> - pub fn into_owned_opt(self) -> Option> { + /// Returns an `Owned` if non-null, `None` otherwise. + pub fn into_owned_opt(self) -> Option> { if self.is_null() { None } else { @@ -276,11 +322,15 @@ impl OwnedOrNull { } } - pub fn borrow(&self) -> Option<&T> { + /// Gets a immutable reference to the underlying Gecko type, or `None` if + /// null. + pub fn borrow(&self) -> Option<&GeckoType> { unsafe { transmute(self) } } - pub fn borrow_mut(&self) -> Option<&mut T> { + /// Gets a mutable reference to the underlying Gecko type, or `None` if + /// null. + pub fn borrow_mut(&self) -> Option<&mut GeckoType> { unsafe { transmute(self) } } }