Add safer bindings for refcounted types across ffi

This commit is contained in:
Manish Goregaokar 2016-08-14 00:06:58 +05:30
parent 8fd74e026c
commit 0d4d1b539e
10 changed files with 248 additions and 180 deletions

View file

@ -6,10 +6,23 @@
//! Ideally, it would be in geckolib itself, but coherence
//! forces us to keep the traits and implementations here
#![allow(unsafe_code)]
use app_units::Au;
use gecko_bindings::bindings::{RawServoStyleSheet, ServoComputedValues};
use gecko_bindings::structs::nsStyleCoord_CalcValue;
use gecko_bindings::sugar::refptr::HasArcFFI;
use properties::ComputedValues;
use stylesheets::Stylesheet;
use values::computed::{CalcLengthOrPercentage, LengthOrPercentage};
unsafe impl HasArcFFI for Stylesheet {
type FFIType = RawServoStyleSheet;
}
unsafe impl HasArcFFI for ComputedValues {
type FFIType = ServoComputedValues;
}
impl From<CalcLengthOrPercentage> for nsStyleCoord_CalcValue {
fn from(other: CalcLengthOrPercentage) -> nsStyleCoord_CalcValue {
let has_percentage = other.percentage.is_some();

View file

@ -1,65 +0,0 @@
/* 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/. */
#![allow(unsafe_code)]
use std::marker::PhantomData;
use std::mem::{forget, transmute};
use std::sync::Arc;
pub struct ArcHelpers<GeckoType, ServoType> {
phantom1: PhantomData<GeckoType>,
phantom2: PhantomData<ServoType>,
}
impl<GeckoType, ServoType> ArcHelpers<GeckoType, ServoType> {
pub fn with<F, Output>(raw: *mut GeckoType, cb: F) -> Output
where F: FnOnce(&Arc<ServoType>) -> Output {
debug_assert!(!raw.is_null());
let owned = unsafe { Self::into(raw) };
let result = cb(&owned);
forget(owned);
result
}
pub fn maybe_with<F, Output>(maybe_raw: *mut GeckoType, cb: F) -> Output
where F: FnOnce(Option<&Arc<ServoType>>) -> Output {
let owned = if maybe_raw.is_null() {
None
} else {
Some(unsafe { Self::into(maybe_raw) })
};
let result = cb(owned.as_ref());
forget(owned);
result
}
pub unsafe fn into(ptr: *mut GeckoType) -> Arc<ServoType> {
transmute(ptr)
}
pub fn from(owned: Arc<ServoType>) -> *mut GeckoType {
unsafe { transmute(owned) }
}
pub fn borrow<F, Output>(borrowed: &Arc<ServoType>, cb: F) -> Output
where F: FnOnce(&mut GeckoType) -> Output
{
let borrowed_gecko_type: *const &mut GeckoType =
unsafe { transmute(borrowed) };
unsafe { cb(*borrowed_gecko_type) }
}
pub unsafe fn addref(ptr: *mut GeckoType) {
Self::with(ptr, |arc| forget(arc.clone()));
}
pub unsafe fn release(ptr: *mut GeckoType) {
let _ = Self::into(ptr);
}
}

View file

@ -83,7 +83,6 @@ pub mod element_state;
pub mod error_reporting;
pub mod font_face;
#[cfg(feature = "gecko")] pub mod gecko_conversions;
#[cfg(feature = "gecko")] pub mod gecko_glue;
#[cfg(feature = "gecko")] pub mod gecko_selector_impl;
#[cfg(feature = "gecko")] pub mod gecko_values;
pub mod keyframes;

View file

@ -24,10 +24,10 @@ use gecko_bindings::bindings::{Gecko_EnsureImageLayersLength, Gecko_CreateGradie
use gecko_bindings::bindings::{Gecko_CopyImageValueFrom, Gecko_CopyFontFamilyFrom};
use gecko_bindings::bindings::{Gecko_FontFamilyList_AppendGeneric, Gecko_FontFamilyList_AppendNamed};
use gecko_bindings::bindings::{Gecko_FontFamilyList_Clear, Gecko_InitializeImageLayer};
use gecko_bindings::bindings;
use gecko_bindings::bindings::ServoComputedValuesBorrowed;
use gecko_bindings::structs;
use gecko_bindings::sugar::ns_style_coord::{CoordDataValue, CoordData, CoordDataMut};
use gecko_glue::ArcHelpers;
use gecko_bindings::sugar::refptr::HasArcFFI;
use gecko_values::{StyleCoordHelpers, GeckoStyleCoordConvertible, convert_nscolor_to_rgba};
use gecko_values::convert_rgba_to_nscolor;
use gecko_values::round_border_to_device_pixels;
@ -1358,10 +1358,9 @@ fn static_assert() {
<%def name="define_ffi_struct_accessor(style_struct)">
#[no_mangle]
#[allow(non_snake_case, unused_variables)]
pub extern "C" fn Servo_GetStyle${style_struct.gecko_name}(computed_values: *mut bindings::ServoComputedValues)
pub extern "C" fn Servo_GetStyle${style_struct.gecko_name}(computed_values: ServoComputedValuesBorrowed)
-> *const ${style_struct.gecko_ffi_name} {
type Helpers = ArcHelpers<bindings::ServoComputedValues, ComputedValues>;
Helpers::with(computed_values, |values| values.get_${style_struct.name_lower}().get_gecko()
ComputedValues::with(computed_values, |values| values.get_${style_struct.name_lower}().get_gecko()
as *const ${style_struct.gecko_ffi_name})
}
</%def>