diff --git a/ports/geckolib/gecko_bindings/lib.rs b/ports/geckolib/gecko_bindings/lib.rs index b6d684b5891..d1bfb30985d 100644 --- a/ports/geckolib/gecko_bindings/lib.rs +++ b/ports/geckolib/gecko_bindings/lib.rs @@ -2,9 +2,13 @@ * 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/. */ +#![feature(concat_idents)] +#![feature(type_macros)] + extern crate heapsize; #[allow(dead_code, non_camel_case_types)] pub mod bindings; +pub mod ptr; #[allow(dead_code, non_camel_case_types, non_snake_case, non_upper_case_globals)] pub mod structs; diff --git a/ports/geckolib/gecko_bindings/ptr.rs b/ports/geckolib/gecko_bindings/ptr.rs new file mode 100644 index 00000000000..089df6f70b1 --- /dev/null +++ b/ports/geckolib/gecko_bindings/ptr.rs @@ -0,0 +1,59 @@ +/* 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 bindings::*; +use heapsize::HeapSizeOf; +use std::fmt::{self, Debug}; + +// Defines an Arc-like type that manages a refcounted Gecko object stored +// in a ThreadSafeFooHolder smart pointer. Used in tandem with the +// NS_DECL_HOLDER_FFI_REFCOUNTING-defined types and functions in Gecko. +macro_rules! define_holder_arc { + ($arc_type:ident, $name:ident, $holder_type:ident) => ( + #[derive(PartialEq)] + pub struct $arc_type { + ptr: *mut $holder_type, + } + + impl $arc_type { + pub fn new(data: *mut $holder_type) -> $arc_type { + debug_assert!(!data.is_null()); + unsafe { concat_idents!(Gecko_AddRef, $name, ArbitraryThread)(data); } + $arc_type { + ptr: data + } + } + + pub fn as_raw(&self) -> *mut $holder_type { self.ptr } + } + + unsafe impl Send for $arc_type {} + unsafe impl Sync for $arc_type {} + + impl Clone for $arc_type { + fn clone(&self) -> $arc_type { + $arc_type::new(self.ptr) + } + } + + impl Drop for $arc_type { + fn drop(&mut self) { + unsafe { concat_idents!(Gecko_Release, $name, ArbitraryThread)(self.ptr); } + } + } + + impl HeapSizeOf for $arc_type { + fn heap_size_of_children(&self) -> usize { 0 } + } + + impl Debug for $arc_type { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, stringify!($name)) + } + } + ) +} + +define_holder_arc!(GeckoArcPrincipal, Principal, ThreadSafePrincipalHolder); +define_holder_arc!(GeckoArcURI, URI, ThreadSafeURIHolder);