mirror of
https://github.com/servo/servo.git
synced 2025-08-26 07:38:21 +01:00
Move gecko_bindings and gecko_string_cache into the style crate
This commit is contained in:
parent
0dd005eacc
commit
c6787458d9
33 changed files with 2629 additions and 2688 deletions
1035
components/style/gecko_bindings/bindings.rs
Normal file
1035
components/style/gecko_bindings/bindings.rs
Normal file
File diff suppressed because it is too large
Load diff
18
components/style/gecko_bindings/mod.rs
Normal file
18
components/style/gecko_bindings/mod.rs
Normal file
|
@ -0,0 +1,18 @@
|
|||
/* 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(dead_code, non_camel_case_types)]
|
||||
pub mod bindings;
|
||||
pub mod ptr;
|
||||
#[cfg(debug_assertions)]
|
||||
#[allow(dead_code, non_camel_case_types, non_snake_case, non_upper_case_globals)]
|
||||
pub mod structs {
|
||||
include!("structs_debug.rs");
|
||||
}
|
||||
#[cfg(not(debug_assertions))]
|
||||
#[allow(dead_code, non_camel_case_types, non_snake_case, non_upper_case_globals)]
|
||||
pub mod structs {
|
||||
include!("structs_release.rs");
|
||||
}
|
||||
pub mod sugar;
|
64
components/style/gecko_bindings/ptr.rs
Normal file
64
components/style/gecko_bindings/ptr.rs
Normal file
|
@ -0,0 +1,64 @@
|
|||
/* 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 gecko_bindings::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 (for those Gecko classes that
|
||||
// do not have thread-safe refcounting support) or as raw pointers (for
|
||||
// those that do have thread-safe refcounting support). Used in tandem
|
||||
// with the NS_DECL_(HOLDER|THREADSAFE)_FFI_REFCOUNTING-defined types and
|
||||
// functions in Gecko.
|
||||
macro_rules! define_arc {
|
||||
($arc_type:ident, $name:ident, $gecko_type:ident, $addref: ident, $release: ident) => (
|
||||
#[derive(PartialEq)]
|
||||
pub struct $arc_type {
|
||||
ptr: *mut $gecko_type,
|
||||
}
|
||||
|
||||
impl $arc_type {
|
||||
pub fn new(data: *mut $gecko_type) -> $arc_type {
|
||||
debug_assert!(!data.is_null());
|
||||
unsafe { $addref(data); }
|
||||
$arc_type {
|
||||
ptr: data
|
||||
}
|
||||
}
|
||||
|
||||
pub fn as_raw(&self) -> *mut $gecko_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 { $release(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_arc!(GeckoArcPrincipal, Principal, ThreadSafePrincipalHolder,
|
||||
Gecko_AddRefPrincipalArbitraryThread, Gecko_ReleasePrincipalArbitraryThread);
|
||||
define_arc!(GeckoArcURI, URI, ThreadSafeURIHolder,
|
||||
Gecko_AddRefURIArbitraryThread, Gecko_ReleaseURIArbitraryThread);
|
10960
components/style/gecko_bindings/structs_debug.rs
Normal file
10960
components/style/gecko_bindings/structs_debug.rs
Normal file
File diff suppressed because it is too large
Load diff
10904
components/style/gecko_bindings/structs_release.rs
Normal file
10904
components/style/gecko_bindings/structs_release.rs
Normal file
File diff suppressed because it is too large
Load diff
9
components/style/gecko_bindings/sugar/mod.rs
Normal file
9
components/style/gecko_bindings/sugar/mod.rs
Normal file
|
@ -0,0 +1,9 @@
|
|||
/* 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/. */
|
||||
|
||||
mod ns_css_shadow_array;
|
||||
mod ns_style_auto_array;
|
||||
pub mod ns_style_coord;
|
||||
mod ns_t_array;
|
||||
pub mod ownership;
|
65
components/style/gecko_bindings/sugar/ns_css_shadow_array.rs
Normal file
65
components/style/gecko_bindings/sugar/ns_css_shadow_array.rs
Normal file
|
@ -0,0 +1,65 @@
|
|||
/* 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 gecko_bindings::bindings::Gecko_AddRefCSSShadowArrayArbitraryThread;
|
||||
use gecko_bindings::bindings::Gecko_NewCSSShadowArray;
|
||||
use gecko_bindings::bindings::Gecko_ReleaseCSSShadowArrayArbitraryThread;
|
||||
use std::{ptr, slice};
|
||||
use std::ops::{Deref, DerefMut};
|
||||
use gecko_bindings::structs::{RefPtr, nsCSSShadowArray, nsCSSShadowItem};
|
||||
|
||||
impl RefPtr<nsCSSShadowArray> {
|
||||
pub fn replace_with_new(&mut self, len: u32) {
|
||||
unsafe {
|
||||
if !self.mRawPtr.is_null() {
|
||||
Gecko_ReleaseCSSShadowArrayArbitraryThread(self.mRawPtr);
|
||||
}
|
||||
|
||||
self.mRawPtr = if len == 0 {
|
||||
ptr::null_mut()
|
||||
} else {
|
||||
Gecko_NewCSSShadowArray(len)
|
||||
}
|
||||
}
|
||||
}
|
||||
pub fn copy_from(&mut self, other: &Self) {
|
||||
unsafe {
|
||||
if !self.mRawPtr.is_null() {
|
||||
Gecko_ReleaseCSSShadowArrayArbitraryThread(self.mRawPtr);
|
||||
}
|
||||
if !other.mRawPtr.is_null() {
|
||||
Gecko_AddRefCSSShadowArrayArbitraryThread(other.mRawPtr);
|
||||
}
|
||||
|
||||
self.mRawPtr = other.mRawPtr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Deref for RefPtr<nsCSSShadowArray> {
|
||||
type Target = [nsCSSShadowItem];
|
||||
fn deref(&self) -> &[nsCSSShadowItem] {
|
||||
if self.mRawPtr.is_null() {
|
||||
&[]
|
||||
} else {
|
||||
unsafe {
|
||||
slice::from_raw_parts((*self.mRawPtr).mArray.as_ptr(),
|
||||
(*self.mRawPtr).mLength as usize)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl DerefMut for RefPtr<nsCSSShadowArray> {
|
||||
fn deref_mut(&mut self) -> &mut [nsCSSShadowItem] {
|
||||
if self.mRawPtr.is_null() {
|
||||
&mut []
|
||||
} else {
|
||||
unsafe {
|
||||
slice::from_raw_parts_mut((*self.mRawPtr).mArray.as_mut_ptr(),
|
||||
(*self.mRawPtr).mLength as usize)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
31
components/style/gecko_bindings/sugar/ns_style_auto_array.rs
Normal file
31
components/style/gecko_bindings/sugar/ns_style_auto_array.rs
Normal file
|
@ -0,0 +1,31 @@
|
|||
/* 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::iter::{once, Chain, Once, IntoIterator};
|
||||
use std::slice::{Iter, IterMut};
|
||||
use gecko_bindings::structs::nsStyleAutoArray;
|
||||
|
||||
impl<T> nsStyleAutoArray<T> {
|
||||
pub fn iter_mut(&mut self) -> Chain<Once<&mut T>, IterMut<T>> {
|
||||
once(&mut self.mFirstElement).chain(self.mOtherElements.iter_mut())
|
||||
}
|
||||
pub fn iter(&self) -> Chain<Once<&T>, Iter<T>> {
|
||||
once(&self.mFirstElement).chain(self.mOtherElements.iter())
|
||||
}
|
||||
|
||||
// Note that often structs containing autoarrays will have
|
||||
// additional member fields that contain the length, which must be kept
|
||||
// in sync
|
||||
pub fn len(&self) -> usize {
|
||||
1 + self.mOtherElements.len()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T> IntoIterator for &'a mut nsStyleAutoArray<T> {
|
||||
type Item = &'a mut T;
|
||||
type IntoIter = Chain<Once<&'a mut T>, IterMut<'a, T>>;
|
||||
fn into_iter(self) -> Self::IntoIter {
|
||||
self.iter_mut()
|
||||
}
|
||||
}
|
397
components/style/gecko_bindings/sugar/ns_style_coord.rs
Normal file
397
components/style/gecko_bindings/sugar/ns_style_coord.rs
Normal file
|
@ -0,0 +1,397 @@
|
|||
/* 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 gecko_bindings::bindings::{Gecko_ResetStyleCoord, Gecko_SetStyleCoordCalcValue, Gecko_AddRefCalcArbitraryThread};
|
||||
use std::mem;
|
||||
use gecko_bindings::structs::{nsStyleCoord_Calc, nsStyleUnit, nsStyleUnion, nsStyleCoord, nsStyleSides, nsStyleCorners};
|
||||
use gecko_bindings::structs::{nsStyleCoord_CalcValue, nscoord};
|
||||
|
||||
impl nsStyleCoord {
|
||||
#[inline]
|
||||
pub fn null() -> Self {
|
||||
// Can't construct directly because it has private fields
|
||||
let mut coord: Self = unsafe { mem::zeroed() };
|
||||
coord.leaky_set_null();
|
||||
coord
|
||||
}
|
||||
}
|
||||
|
||||
impl CoordData for nsStyleCoord {
|
||||
#[inline]
|
||||
fn unit(&self) -> nsStyleUnit {
|
||||
unsafe {
|
||||
*self.get_mUnit()
|
||||
}
|
||||
}
|
||||
#[inline]
|
||||
fn union(&self) -> nsStyleUnion {
|
||||
unsafe {
|
||||
*self.get_mValue()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl CoordDataMut for nsStyleCoord {
|
||||
unsafe fn values_mut(&mut self) -> (&mut nsStyleUnit, &mut nsStyleUnion) {
|
||||
let unit = self.get_mUnit_mut() as *mut _;
|
||||
let value = self.get_mValue_mut() as *mut _;
|
||||
(&mut *unit, &mut *value)
|
||||
}
|
||||
}
|
||||
|
||||
impl nsStyleCoord_CalcValue {
|
||||
pub fn new() -> Self {
|
||||
nsStyleCoord_CalcValue {
|
||||
mLength: 0,
|
||||
mPercent: 0.0,
|
||||
mHasPercent: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl nsStyleSides {
|
||||
#[inline]
|
||||
pub fn data_at(&self, index: usize) -> SidesData {
|
||||
SidesData {
|
||||
sides: self,
|
||||
index: index,
|
||||
}
|
||||
}
|
||||
#[inline]
|
||||
pub fn data_at_mut(&mut self, index: usize) -> SidesDataMut {
|
||||
SidesDataMut {
|
||||
sides: self,
|
||||
index: index,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct SidesData<'a> {
|
||||
sides: &'a nsStyleSides,
|
||||
index: usize,
|
||||
}
|
||||
pub struct SidesDataMut<'a> {
|
||||
sides: &'a mut nsStyleSides,
|
||||
index: usize,
|
||||
}
|
||||
|
||||
impl<'a> CoordData for SidesData<'a> {
|
||||
#[inline]
|
||||
fn unit(&self) -> nsStyleUnit {
|
||||
unsafe {
|
||||
self.sides.get_mUnits()[self.index]
|
||||
}
|
||||
}
|
||||
#[inline]
|
||||
fn union(&self) -> nsStyleUnion {
|
||||
unsafe {
|
||||
self.sides.get_mValues()[self.index]
|
||||
}
|
||||
}
|
||||
}
|
||||
impl<'a> CoordData for SidesDataMut<'a> {
|
||||
#[inline]
|
||||
fn unit(&self) -> nsStyleUnit {
|
||||
unsafe {
|
||||
self.sides.get_mUnits()[self.index]
|
||||
}
|
||||
}
|
||||
#[inline]
|
||||
fn union(&self) -> nsStyleUnion {
|
||||
unsafe {
|
||||
self.sides.get_mValues()[self.index]
|
||||
}
|
||||
}
|
||||
}
|
||||
impl<'a> CoordDataMut for SidesDataMut<'a> {
|
||||
unsafe fn values_mut(&mut self) -> (&mut nsStyleUnit, &mut nsStyleUnion) {
|
||||
let unit = &mut self.sides.get_mUnits_mut()[self.index] as *mut _;
|
||||
let value = &mut self.sides.get_mValues_mut()[self.index] as *mut _;
|
||||
(&mut *unit, &mut *value)
|
||||
}
|
||||
}
|
||||
|
||||
impl nsStyleCorners {
|
||||
#[inline]
|
||||
pub fn data_at(&self, index: usize) -> CornersData {
|
||||
CornersData {
|
||||
corners: self,
|
||||
index: index,
|
||||
}
|
||||
}
|
||||
#[inline]
|
||||
pub fn data_at_mut(&mut self, index: usize) -> CornersDataMut {
|
||||
CornersDataMut {
|
||||
corners: self,
|
||||
index: index,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct CornersData<'a> {
|
||||
corners: &'a nsStyleCorners,
|
||||
index: usize,
|
||||
}
|
||||
pub struct CornersDataMut<'a> {
|
||||
corners: &'a mut nsStyleCorners,
|
||||
index: usize,
|
||||
}
|
||||
|
||||
impl<'a> CoordData for CornersData<'a> {
|
||||
fn unit(&self) -> nsStyleUnit {
|
||||
unsafe {
|
||||
self.corners.get_mUnits()[self.index]
|
||||
}
|
||||
}
|
||||
fn union(&self) -> nsStyleUnion {
|
||||
unsafe {
|
||||
self.corners.get_mValues()[self.index]
|
||||
}
|
||||
}
|
||||
}
|
||||
impl<'a> CoordData for CornersDataMut<'a> {
|
||||
fn unit(&self) -> nsStyleUnit {
|
||||
unsafe {
|
||||
self.corners.get_mUnits()[self.index]
|
||||
}
|
||||
}
|
||||
fn union(&self) -> nsStyleUnion {
|
||||
unsafe {
|
||||
self.corners.get_mValues()[self.index]
|
||||
}
|
||||
}
|
||||
}
|
||||
impl<'a> CoordDataMut for CornersDataMut<'a> {
|
||||
unsafe fn values_mut(&mut self) -> (&mut nsStyleUnit, &mut nsStyleUnion) {
|
||||
let unit = &mut self.corners.get_mUnits_mut()[self.index] as *mut _;
|
||||
let value = &mut self.corners.get_mValues_mut()[self.index] as *mut _;
|
||||
(&mut *unit, &mut *value)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
/// Enum representing the tagged union that is CoordData.
|
||||
/// In release mode this should never actually exist in the code,
|
||||
/// and will be optimized out by threading matches and inlining.
|
||||
pub enum CoordDataValue {
|
||||
Null,
|
||||
Normal,
|
||||
Auto,
|
||||
None,
|
||||
Percent(f32),
|
||||
Factor(f32),
|
||||
Degree(f32),
|
||||
Grad(f32),
|
||||
Radian(f32),
|
||||
Turn(f32),
|
||||
FlexFraction(f32),
|
||||
Coord(nscoord),
|
||||
Integer(i32),
|
||||
Enumerated(u32),
|
||||
Calc(nsStyleCoord_CalcValue),
|
||||
}
|
||||
|
||||
|
||||
pub trait CoordDataMut : CoordData {
|
||||
// This can't be two methods since we can't mutably borrow twice
|
||||
/// This is unsafe since it's possible to modify
|
||||
/// the unit without changing the union
|
||||
unsafe fn values_mut(&mut self) -> (&mut nsStyleUnit, &mut nsStyleUnion);
|
||||
|
||||
/// Clean up any resources used by the union
|
||||
/// Currently, this only happens if the nsStyleUnit
|
||||
/// is a Calc
|
||||
#[inline]
|
||||
fn reset(&mut self) {
|
||||
unsafe {
|
||||
if self.unit() == nsStyleUnit::eStyleUnit_Calc {
|
||||
let (unit, union) = self.values_mut();
|
||||
Gecko_ResetStyleCoord(unit, union);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn copy_from<T: CoordData>(&mut self, other: &T) {
|
||||
unsafe {
|
||||
self.reset();
|
||||
{
|
||||
let (unit, union) = self.values_mut();
|
||||
*unit = other.unit();
|
||||
*union = other.union();
|
||||
}
|
||||
self.addref_if_calc();
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn copy_from_unchecked<T: CoordData>(&mut self, other: &T) {
|
||||
let (unit, union) = self.values_mut();
|
||||
*unit = other.unit();
|
||||
*union = other.union();
|
||||
}
|
||||
|
||||
/// Useful for initializing uninits
|
||||
/// (set_value may segfault on uninits)
|
||||
fn leaky_set_null(&mut self) {
|
||||
use gecko_bindings::structs::nsStyleUnit::*;
|
||||
unsafe {
|
||||
let (unit, union) = self.values_mut();
|
||||
*unit = eStyleUnit_Null;
|
||||
*union.mInt.as_mut() = 0;
|
||||
}
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn set_value(&mut self, value: CoordDataValue) {
|
||||
use self::CoordDataValue::*;
|
||||
use gecko_bindings::structs::nsStyleUnit::*;
|
||||
self.reset();
|
||||
unsafe {
|
||||
let (unit, union) = self.values_mut();
|
||||
match value {
|
||||
Null => {
|
||||
*unit = eStyleUnit_Null;
|
||||
*union.mInt.as_mut() = 0;
|
||||
}
|
||||
Normal => {
|
||||
*unit = eStyleUnit_Normal;
|
||||
*union.mInt.as_mut() = 0;
|
||||
}
|
||||
Auto => {
|
||||
*unit = eStyleUnit_Auto;
|
||||
*union.mInt.as_mut() = 0;
|
||||
}
|
||||
None => {
|
||||
*unit = eStyleUnit_None;
|
||||
*union.mInt.as_mut() = 0;
|
||||
}
|
||||
Percent(f) => {
|
||||
*unit = eStyleUnit_Percent;
|
||||
*union.mFloat.as_mut() = f;
|
||||
}
|
||||
Factor(f) => {
|
||||
*unit = eStyleUnit_Factor;
|
||||
*union.mFloat.as_mut() = f;
|
||||
}
|
||||
Degree(f) => {
|
||||
*unit = eStyleUnit_Degree;
|
||||
*union.mFloat.as_mut() = f;
|
||||
}
|
||||
Grad(f) => {
|
||||
*unit = eStyleUnit_Grad;
|
||||
*union.mFloat.as_mut() = f;
|
||||
}
|
||||
Radian(f) => {
|
||||
*unit = eStyleUnit_Radian;
|
||||
*union.mFloat.as_mut() = f;
|
||||
}
|
||||
Turn(f) => {
|
||||
*unit = eStyleUnit_Turn;
|
||||
*union.mFloat.as_mut() = f;
|
||||
}
|
||||
FlexFraction(f) => {
|
||||
*unit = eStyleUnit_FlexFraction;
|
||||
*union.mFloat.as_mut() = f;
|
||||
}
|
||||
Coord(coord) => {
|
||||
*unit = eStyleUnit_Coord;
|
||||
*union.mInt.as_mut() = coord;
|
||||
}
|
||||
Integer(i) => {
|
||||
*unit = eStyleUnit_Integer;
|
||||
*union.mInt.as_mut() = i;
|
||||
}
|
||||
Enumerated(i) => {
|
||||
*unit = eStyleUnit_Enumerated;
|
||||
*union.mInt.as_mut() = i as i32;
|
||||
}
|
||||
Calc(calc) => {
|
||||
// Gecko_SetStyleCoordCalcValue changes the unit internally
|
||||
Gecko_SetStyleCoordCalcValue(unit, union, calc);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn as_calc_mut(&mut self) -> &mut nsStyleCoord_Calc {
|
||||
debug_assert!(self.unit() == nsStyleUnit::eStyleUnit_Calc);
|
||||
&mut *(*self.union().mPointer.as_mut() as *mut nsStyleCoord_Calc)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn addref_if_calc(&mut self) {
|
||||
unsafe {
|
||||
if self.unit() == nsStyleUnit::eStyleUnit_Calc {
|
||||
Gecko_AddRefCalcArbitraryThread(self.as_calc_mut());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
pub trait CoordData {
|
||||
fn unit(&self) -> nsStyleUnit;
|
||||
fn union(&self) -> nsStyleUnion;
|
||||
|
||||
|
||||
#[inline(always)]
|
||||
fn as_value(&self) -> CoordDataValue {
|
||||
use self::CoordDataValue::*;
|
||||
use gecko_bindings::structs::nsStyleUnit::*;
|
||||
unsafe {
|
||||
match self.unit() {
|
||||
eStyleUnit_Null => Null,
|
||||
eStyleUnit_Normal => Normal,
|
||||
eStyleUnit_Auto => Auto,
|
||||
eStyleUnit_None => None,
|
||||
eStyleUnit_Percent => Percent(self.get_float()),
|
||||
eStyleUnit_Factor => Factor(self.get_float()),
|
||||
eStyleUnit_Degree => Degree(self.get_float()),
|
||||
eStyleUnit_Grad => Grad(self.get_float()),
|
||||
eStyleUnit_Radian => Radian(self.get_float()),
|
||||
eStyleUnit_Turn => Turn(self.get_float()),
|
||||
eStyleUnit_FlexFraction => FlexFraction(self.get_float()),
|
||||
eStyleUnit_Coord => Coord(self.get_integer()),
|
||||
eStyleUnit_Integer => Integer(self.get_integer()),
|
||||
eStyleUnit_Enumerated => Enumerated(self.get_integer() as u32),
|
||||
eStyleUnit_Calc => Calc(self.get_calc_value()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
/// Pretend inner value is a float; obtain it.
|
||||
unsafe fn get_float(&self) -> f32 {
|
||||
use gecko_bindings::structs::nsStyleUnit::*;
|
||||
debug_assert!(self.unit() == eStyleUnit_Percent || self.unit() == eStyleUnit_Factor
|
||||
|| self.unit() == eStyleUnit_Degree || self.unit() == eStyleUnit_Grad
|
||||
|| self.unit() == eStyleUnit_Radian || self.unit() == eStyleUnit_Turn
|
||||
|| self.unit() == eStyleUnit_FlexFraction);
|
||||
*self.union().mFloat.as_ref()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
/// Pretend inner value is an int; obtain it.
|
||||
unsafe fn get_integer(&self) -> i32 {
|
||||
use gecko_bindings::structs::nsStyleUnit::*;
|
||||
debug_assert!(self.unit() == eStyleUnit_Coord || self.unit() == eStyleUnit_Integer
|
||||
|| self.unit() == eStyleUnit_Enumerated);
|
||||
*self.union().mInt.as_ref()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
/// Pretend inner value is a calc; obtain it.
|
||||
/// Ensure that the unit is Calc before calling this.
|
||||
unsafe fn get_calc_value(&self) -> nsStyleCoord_CalcValue {
|
||||
debug_assert!(self.unit() == nsStyleUnit::eStyleUnit_Calc);
|
||||
(*self.as_calc())._base
|
||||
}
|
||||
|
||||
|
||||
#[inline]
|
||||
unsafe fn as_calc(&self) -> &nsStyleCoord_Calc {
|
||||
debug_assert!(self.unit() == nsStyleUnit::eStyleUnit_Calc);
|
||||
&*(*self.union().mPointer.as_ref() as *const nsStyleCoord_Calc)
|
||||
}
|
||||
}
|
93
components/style/gecko_bindings/sugar/ns_t_array.rs
Normal file
93
components/style/gecko_bindings/sugar/ns_t_array.rs
Normal file
|
@ -0,0 +1,93 @@
|
|||
/* 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 gecko_bindings::bindings;
|
||||
use std::mem;
|
||||
use std::ops::{Deref, DerefMut};
|
||||
use std::os::raw::c_void;
|
||||
use std::slice;
|
||||
use gecko_bindings::structs::{nsTArray, nsTArrayHeader};
|
||||
|
||||
impl<T> Deref for nsTArray<T> {
|
||||
type Target = [T];
|
||||
|
||||
fn deref<'a>(&'a self) -> &'a [T] {
|
||||
unsafe {
|
||||
slice::from_raw_parts(self.slice_begin(),
|
||||
self.header().mLength as usize)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> DerefMut for nsTArray<T> {
|
||||
fn deref_mut<'a>(&'a mut self) -> &'a mut [T] {
|
||||
unsafe {
|
||||
slice::from_raw_parts_mut(self.slice_begin(),
|
||||
self.header().mLength as usize)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> nsTArray<T> {
|
||||
#[inline]
|
||||
fn header<'a>(&'a self) -> &'a nsTArrayHeader {
|
||||
debug_assert!(!self.mBuffer.is_null());
|
||||
unsafe { mem::transmute(self.mBuffer) }
|
||||
}
|
||||
// unsafe, since header may be in shared static or something
|
||||
unsafe fn header_mut<'a>(&'a mut self) -> &'a mut nsTArrayHeader {
|
||||
debug_assert!(!self.mBuffer.is_null());
|
||||
|
||||
mem::transmute(self.mBuffer)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn slice_begin(&self) -> *mut T {
|
||||
debug_assert!(!self.mBuffer.is_null());
|
||||
(self.mBuffer as *const nsTArrayHeader).offset(1) as *mut _
|
||||
}
|
||||
|
||||
/// Ensures the array has enough capacity at least to hold `cap` elements.
|
||||
///
|
||||
/// NOTE: This doesn't call the constructor on the values!
|
||||
pub fn ensure_capacity(&mut self, cap: usize) {
|
||||
if cap >= self.len() {
|
||||
unsafe {
|
||||
bindings::Gecko_EnsureTArrayCapacity(self as *mut nsTArray<T> as *mut _,
|
||||
cap, mem::size_of::<T>())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Clears the array storage without calling the destructor on the values.
|
||||
#[inline]
|
||||
pub unsafe fn clear(&mut self) {
|
||||
if self.len() != 0 {
|
||||
bindings::Gecko_ClearPODTArray(self as *mut nsTArray<T> as *mut _,
|
||||
mem::size_of::<T>(),
|
||||
mem::align_of::<T>());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// Clears a POD array. This is safe since copy types are memcopyable.
|
||||
#[inline]
|
||||
pub fn clear_pod(&mut self)
|
||||
where T: Copy
|
||||
{
|
||||
unsafe { self.clear() }
|
||||
}
|
||||
|
||||
// unsafe because the array may contain uninits
|
||||
// This will not call constructors, either manually
|
||||
// add bindings or run the typed ensurecapacity call
|
||||
// on the gecko side
|
||||
pub unsafe fn set_len(&mut self, len: u32) {
|
||||
// this can leak
|
||||
debug_assert!(len >= self.len() as u32);
|
||||
self.ensure_capacity(len as usize);
|
||||
let mut header = self.header_mut();
|
||||
header.mLength = len;
|
||||
}
|
||||
}
|
397
components/style/gecko_bindings/sugar/ownership.rs
Normal file
397
components/style/gecko_bindings/sugar/ownership.rs
Normal file
|
@ -0,0 +1,397 @@
|
|||
/* 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::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
|
||||
pub unsafe trait HasFFI : Sized {
|
||||
type FFIType: Sized;
|
||||
}
|
||||
|
||||
/// 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
|
||||
///
|
||||
/// &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
|
||||
///
|
||||
/// &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
|
||||
///
|
||||
/// &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
|
||||
///
|
||||
/// &mut GeckoType -> &mut ServoType
|
||||
fn from_ffi_mut(ffi: &mut Self::FFIType) -> &mut Self {
|
||||
unsafe { transmute(ffi) }
|
||||
}
|
||||
}
|
||||
|
||||
/// Indicates that the given Servo type is passed over FFI
|
||||
/// as a Box
|
||||
pub unsafe trait HasBoxFFI : HasSimpleFFI {
|
||||
#[inline]
|
||||
fn into_ffi(self: Box<Self>) -> Owned<Self::FFIType> {
|
||||
unsafe { transmute(self) }
|
||||
}
|
||||
}
|
||||
|
||||
/// 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
|
||||
///
|
||||
/// In this case, the FFIType is the rough equivalent of ArcInner<Self>
|
||||
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.
|
||||
unsafe fn addref_opt(ptr: Borrowed<Self::FFIType>) {
|
||||
forget(ptr.as_arc_opt::<Self>().clone())
|
||||
}
|
||||
|
||||
/// Given a (possibly null) borrowed FFI reference, decrements the refcount.
|
||||
/// Unsafe since it doesn't consume the backing Arc. Run it only when you
|
||||
/// know that a strong reference to the backing Arc is disappearing
|
||||
/// (usually on the C++ side) without running the Arc destructor.
|
||||
unsafe fn release_opt(ptr: Borrowed<Self::FFIType>) {
|
||||
if let Some(arc) = ptr.as_arc_opt::<Self>() {
|
||||
let _: Arc<_> = ptr::read(arc as *const Arc<_>);
|
||||
}
|
||||
}
|
||||
|
||||
/// Artificially increments the refcount of a borrowed Arc over FFI.
|
||||
unsafe fn addref(ptr: &Self::FFIType) {
|
||||
forget(Self::as_arc(&ptr).clone())
|
||||
}
|
||||
|
||||
/// Given a non-null borrowed FFI reference, decrements the refcount.
|
||||
/// Unsafe since it doesn't consume the backing Arc. Run it only when you
|
||||
/// know that a strong reference to the backing Arc is disappearing
|
||||
/// (usually on the C++ side) without running the Arc destructor.
|
||||
unsafe fn release(ptr: &Self::FFIType) {
|
||||
let _: Arc<_> = ptr::read(Self::as_arc(&ptr) as *const Arc<_>);
|
||||
}
|
||||
#[inline]
|
||||
/// Converts a borrowed FFI reference to a borrowed Arc.
|
||||
///
|
||||
/// &GeckoType -> &Arc<ServoType>
|
||||
fn as_arc<'a>(ptr: &'a &Self::FFIType) -> &'a Arc<Self> {
|
||||
debug_assert!(!(ptr as *const _).is_null());
|
||||
unsafe {
|
||||
transmute::<&&Self::FFIType, &Arc<Self>>(ptr)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
/// Gecko-FFI-safe borrowed type
|
||||
/// This can be null.
|
||||
pub struct Borrowed<'a, T: 'a> {
|
||||
ptr: *const T,
|
||||
_marker: PhantomData<&'a T>,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
/// Gecko-FFI-safe mutably borrowed type
|
||||
/// This can be null.
|
||||
pub struct BorrowedMut<'a, T: 'a> {
|
||||
ptr: *mut T,
|
||||
_marker: PhantomData<&'a mut T>,
|
||||
}
|
||||
|
||||
// manual impls because derive doesn't realize that `T: Clone` isn't necessary
|
||||
impl<'a, T> Copy for Borrowed<'a, T> {}
|
||||
|
||||
impl<'a, T> Clone for Borrowed<'a, T> {
|
||||
#[inline]
|
||||
fn clone(&self) -> Self { *self }
|
||||
}
|
||||
|
||||
impl<'a, T> Borrowed<'a, T> {
|
||||
#[inline]
|
||||
pub fn is_null(self) -> bool {
|
||||
self.ptr == ptr::null()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
/// Like Deref, but gives an Option
|
||||
pub fn borrow_opt(self) -> Option<&'a T> {
|
||||
if self.is_null() {
|
||||
None
|
||||
} else {
|
||||
Some(unsafe { &*self.ptr })
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
/// Borrowed<GeckoType> -> Option<&Arc<ServoType>>
|
||||
pub fn as_arc_opt<U>(&self) -> Option<&Arc<U>> where U: HasArcFFI<FFIType = T> {
|
||||
unsafe {
|
||||
if self.is_null() {
|
||||
None
|
||||
} else {
|
||||
Some(transmute::<&Borrowed<_>, &Arc<_>>(self))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
/// Converts a borrowed FFI reference to a borrowed Arc.
|
||||
/// Panics on null.
|
||||
///
|
||||
/// &Borrowed<GeckoType> -> &Arc<ServoType>
|
||||
pub fn as_arc<U>(&self) -> &Arc<U> where U: HasArcFFI<FFIType = T> {
|
||||
self.as_arc_opt().unwrap()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
/// Borrowed<ServoType> -> Borrowed<GeckoType>
|
||||
pub fn as_ffi(self) -> Borrowed<'a, <Self as HasFFI>::FFIType> where Self: HasSimpleFFI {
|
||||
unsafe { transmute(self) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
/// Borrowed<GeckoType> -> Borrowed<ServoType>
|
||||
pub fn from_ffi<U>(self) -> Borrowed<'a, U> where U: HasSimpleFFI<FFIType = T> {
|
||||
unsafe { transmute(self) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
/// Borrowed<GeckoType> -> &ServoType
|
||||
pub fn as_servo_ref<U>(self) -> Option<&'a U> where U: HasSimpleFFI<FFIType = T> {
|
||||
self.borrow_opt().map(HasSimpleFFI::from_ffi)
|
||||
}
|
||||
|
||||
pub fn null() -> Borrowed<'static, T> {
|
||||
Borrowed {
|
||||
ptr: ptr::null_mut(),
|
||||
_marker: PhantomData
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T> BorrowedMut<'a, T> {
|
||||
#[inline]
|
||||
/// Like DerefMut, but gives an Option
|
||||
pub fn borrow_mut_opt(self) -> Option<&'a mut T> {
|
||||
// We have two choices for the signature here, it can either be
|
||||
// Self -> Option<&'a mut T> or
|
||||
// &'b mut Self -> Option<'b mut T>
|
||||
// The former consumes the BorrowedMut (which isn't Copy),
|
||||
// which can be annoying. The latter only temporarily
|
||||
// borrows it, so the return value can't exit the scope
|
||||
// even if Self has a longer lifetime ('a)
|
||||
//
|
||||
// This is basically the implicit "reborrow" pattern used with &mut
|
||||
// not cleanly translating to our custom types.
|
||||
|
||||
// I've chosen the former solution -- you can manually convert back
|
||||
// if you need to reuse the BorrowedMut.
|
||||
if self.is_null() {
|
||||
None
|
||||
} else {
|
||||
Some(unsafe { &mut *self.ptr })
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
/// BorrowedMut<GeckoType> -> &mut ServoType
|
||||
pub fn as_servo_mut_ref<U>(self) -> Option<&'a mut U> where U: HasSimpleFFI<FFIType = T> {
|
||||
self.borrow_mut_opt().map(HasSimpleFFI::from_ffi_mut)
|
||||
}
|
||||
|
||||
pub fn null_mut() -> BorrowedMut<'static, T> {
|
||||
BorrowedMut {
|
||||
ptr: ptr::null_mut(),
|
||||
_marker: PhantomData
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// technically not how we're supposed to use
|
||||
// Deref, but that's a minor style issue
|
||||
impl<'a, T> Deref for BorrowedMut<'a, T> {
|
||||
type Target = Borrowed<'a, T>;
|
||||
fn deref(&self) -> &Self::Target {
|
||||
unsafe { transmute(self) }
|
||||
}
|
||||
}
|
||||
|
||||
#[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<T> {
|
||||
ptr: *const T,
|
||||
_marker: PhantomData<T>,
|
||||
}
|
||||
|
||||
impl<T> Strong<T> {
|
||||
#[inline]
|
||||
pub fn is_null(&self) -> bool {
|
||||
self.ptr == ptr::null()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
/// Given a non-null strong FFI reference,
|
||||
/// converts it into a servo-side Arc
|
||||
/// Panics on null.
|
||||
///
|
||||
/// Strong<GeckoType> -> Arc<ServoType>
|
||||
pub fn into_arc<U>(self) -> Arc<U> where U: HasArcFFI<FFIType = T> {
|
||||
self.into_arc_opt().unwrap()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
/// Given a strong FFI reference,
|
||||
/// converts it into a servo-side Arc
|
||||
/// Returns None on null.
|
||||
///
|
||||
/// Strong<GeckoType> -> Arc<ServoType>
|
||||
pub fn into_arc_opt<U>(self) -> Option<Arc<U>> where U: HasArcFFI<FFIType = T> {
|
||||
if self.is_null() {
|
||||
None
|
||||
} else {
|
||||
unsafe { Some(transmute(self)) }
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
/// Produces a null strong FFI reference
|
||||
pub fn null() -> Self {
|
||||
unsafe { transmute(ptr::null::<T>()) }
|
||||
}
|
||||
}
|
||||
|
||||
pub unsafe trait FFIArcHelpers {
|
||||
type Inner: HasArcFFI;
|
||||
/// Converts an Arc into a strong FFI reference.
|
||||
///
|
||||
/// Arc<ServoType> -> Strong<GeckoType>
|
||||
fn into_strong(self) -> Strong<<Self::Inner as HasFFI>::FFIType>;
|
||||
/// Produces a (nullable) borrowed FFI reference by borrowing an Arc.
|
||||
///
|
||||
/// &Arc<ServoType> -> Borrowed<GeckoType>
|
||||
fn as_borrowed_opt(&self) -> Borrowed<<Self::Inner as HasFFI>::FFIType>;
|
||||
/// Produces a borrowed FFI reference by borrowing an Arc.
|
||||
///
|
||||
/// &Arc<ServoType> -> &GeckoType
|
||||
fn as_borrowed(&self) -> &<Self::Inner as HasFFI>::FFIType;
|
||||
}
|
||||
|
||||
unsafe impl<T: HasArcFFI> FFIArcHelpers for Arc<T> {
|
||||
type Inner = T;
|
||||
#[inline]
|
||||
fn into_strong(self) -> Strong<T::FFIType> {
|
||||
unsafe { transmute(self) }
|
||||
}
|
||||
#[inline]
|
||||
fn as_borrowed_opt(&self) -> Borrowed<T::FFIType> {
|
||||
let borrowedptr = self as *const Arc<T> as *const Borrowed<T::FFIType>;
|
||||
unsafe { ptr::read(borrowedptr) }
|
||||
}
|
||||
#[inline]
|
||||
fn as_borrowed(&self) -> &T::FFIType {
|
||||
let borrowedptr = self as *const Arc<T> as *const & T::FFIType;
|
||||
unsafe { ptr::read(borrowedptr) }
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
/// Gecko-FFI-safe owned pointer
|
||||
/// Cannot be null
|
||||
/// Leaks on drop. Please don't drop this.
|
||||
pub struct Owned<T> {
|
||||
ptr: *mut T,
|
||||
_marker: PhantomData<T>,
|
||||
}
|
||||
|
||||
impl<T> Owned<T> {
|
||||
/// Owned<GeckoType> -> Box<ServoType>
|
||||
pub fn into_box<U>(self) -> Box<T> where U: HasBoxFFI<FFIType = T> {
|
||||
unsafe { transmute(self) }
|
||||
}
|
||||
pub fn maybe(self) -> OwnedOrNull<T> {
|
||||
unsafe { transmute(self) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Deref for Owned<T> {
|
||||
type Target = T;
|
||||
fn deref(&self) -> &T {
|
||||
unsafe { &*self.ptr }
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> DerefMut for Owned<T> {
|
||||
fn deref_mut(&mut self) -> &mut T {
|
||||
unsafe { &mut *self.ptr }
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
/// Gecko-FFI-safe owned pointer
|
||||
/// Can be null
|
||||
pub struct OwnedOrNull<T> {
|
||||
ptr: *mut T,
|
||||
_marker: PhantomData<T>,
|
||||
}
|
||||
|
||||
impl<T> OwnedOrNull<T> {
|
||||
pub fn is_null(&self) -> bool {
|
||||
self.ptr == ptr::null_mut()
|
||||
}
|
||||
/// OwnedOrNull<GeckoType> -> Option<Box<ServoType>>
|
||||
pub fn into_box_opt<U>(self) -> Option<Box<T>> where U: HasBoxFFI<FFIType = T> {
|
||||
if self.is_null() {
|
||||
None
|
||||
} else {
|
||||
Some(unsafe { transmute(self) })
|
||||
}
|
||||
}
|
||||
|
||||
/// OwnedOrNull<GeckoType> -> Option<Owned<GeckoType>>
|
||||
pub fn into_owned_opt(self) -> Option<Owned<T>> {
|
||||
if self.is_null() {
|
||||
None
|
||||
} else {
|
||||
Some(unsafe { transmute(self) })
|
||||
}
|
||||
}
|
||||
|
||||
pub fn borrow(&self) -> Borrowed<T> {
|
||||
unsafe { transmute(self) }
|
||||
}
|
||||
|
||||
pub fn borrow_mut(&self) -> BorrowedMut<T> {
|
||||
unsafe { transmute(self) }
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue