style: Document the sugar for nsStyleCoord.

This commit is contained in:
Emilio Cobos Álvarez 2017-01-02 03:28:08 +01:00
parent 1bd246905c
commit 96fb1378d7
No known key found for this signature in database
GPG key ID: 056B727BB9C1027C

View file

@ -2,6 +2,8 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this * 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/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
//! Rust helpers for Gecko's `nsStyleCoord`.
use gecko_bindings::bindings::{Gecko_ResetStyleCoord, Gecko_SetStyleCoordCalcValue, Gecko_AddRefCalcArbitraryThread}; use gecko_bindings::bindings::{Gecko_ResetStyleCoord, Gecko_SetStyleCoordCalcValue, Gecko_AddRefCalcArbitraryThread};
use gecko_bindings::structs::{nsStyleCoord_Calc, nsStyleUnit, nsStyleUnion, nsStyleCoord, nsStyleSides, nsStyleCorners}; use gecko_bindings::structs::{nsStyleCoord_Calc, nsStyleUnit, nsStyleUnion, nsStyleCoord, nsStyleSides, nsStyleCorners};
use gecko_bindings::structs::{nsStyleCoord_CalcValue, nscoord}; use gecko_bindings::structs::{nsStyleCoord_CalcValue, nscoord};
@ -9,6 +11,7 @@ use std::mem;
impl nsStyleCoord { impl nsStyleCoord {
#[inline] #[inline]
/// Get a `null` nsStyleCoord.
pub fn null() -> Self { pub fn null() -> Self {
// Can't construct directly because it has private fields // Can't construct directly because it has private fields
let mut coord: Self = unsafe { mem::zeroed() }; let mut coord: Self = unsafe { mem::zeroed() };
@ -41,6 +44,7 @@ impl CoordDataMut for nsStyleCoord {
} }
impl nsStyleCoord_CalcValue { impl nsStyleCoord_CalcValue {
/// Create an "empty" CalcValue (whose value is `0`).
pub fn new() -> Self { pub fn new() -> Self {
nsStyleCoord_CalcValue { nsStyleCoord_CalcValue {
mLength: 0, mLength: 0,
@ -51,6 +55,8 @@ impl nsStyleCoord_CalcValue {
} }
impl nsStyleSides { impl nsStyleSides {
/// Immutably get the `nsStyleCoord`-like object representing the side at
/// index `index`.
#[inline] #[inline]
pub fn data_at(&self, index: usize) -> SidesData { pub fn data_at(&self, index: usize) -> SidesData {
SidesData { SidesData {
@ -58,6 +64,9 @@ impl nsStyleSides {
index: index, index: index,
} }
} }
/// Mutably get the `nsStyleCoord`-like object representing the side at
/// index `index`.
#[inline] #[inline]
pub fn data_at_mut(&mut self, index: usize) -> SidesDataMut { pub fn data_at_mut(&mut self, index: usize) -> SidesDataMut {
SidesDataMut { SidesDataMut {
@ -67,10 +76,15 @@ impl nsStyleSides {
} }
} }
/// A `nsStyleCoord`-like object on top of an immutable reference to
/// `nsStyleSides`.
pub struct SidesData<'a> { pub struct SidesData<'a> {
sides: &'a nsStyleSides, sides: &'a nsStyleSides,
index: usize, index: usize,
} }
/// A `nsStyleCoord`-like object on top of an mutable reference to
/// `nsStyleSides`.
pub struct SidesDataMut<'a> { pub struct SidesDataMut<'a> {
sides: &'a mut nsStyleSides, sides: &'a mut nsStyleSides,
index: usize, index: usize,
@ -113,6 +127,8 @@ impl<'a> CoordDataMut for SidesDataMut<'a> {
} }
impl nsStyleCorners { impl nsStyleCorners {
/// Get a `nsStyleCoord` like object representing the given index's value
/// and unit.
#[inline] #[inline]
pub fn data_at(&self, index: usize) -> CornersData { pub fn data_at(&self, index: usize) -> CornersData {
CornersData { CornersData {
@ -120,6 +136,9 @@ impl nsStyleCorners {
index: index, index: index,
} }
} }
/// Get a `nsStyleCoord` like object representing the mutable given index's
/// value and unit.
#[inline] #[inline]
pub fn data_at_mut(&mut self, index: usize) -> CornersDataMut { pub fn data_at_mut(&mut self, index: usize) -> CornersDataMut {
CornersDataMut { CornersDataMut {
@ -129,10 +148,13 @@ impl nsStyleCorners {
} }
} }
/// A `nsStyleCoord`-like struct on top of `nsStyleCorners`.
pub struct CornersData<'a> { pub struct CornersData<'a> {
corners: &'a nsStyleCorners, corners: &'a nsStyleCorners,
index: usize, index: usize,
} }
/// A `nsStyleCoord`-like struct on top of a mutable `nsStyleCorners` reference.
pub struct CornersDataMut<'a> { pub struct CornersDataMut<'a> {
corners: &'a mut nsStyleCorners, corners: &'a mut nsStyleCorners,
index: usize, index: usize,
@ -172,36 +194,56 @@ impl<'a> CoordDataMut for CornersDataMut<'a> {
#[derive(Copy, Clone)] #[derive(Copy, Clone)]
/// Enum representing the tagged union that is CoordData. /// 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. /// In release mode this should never actually exist in the code, and will be
/// optimized out by threading matches and inlining.
pub enum CoordDataValue { pub enum CoordDataValue {
/// eStyleUnit_Null
Null, Null,
/// eStyleUnit_Normal
Normal, Normal,
/// eStyleUnit_Auto
Auto, Auto,
/// eStyleUnit_None
None, None,
/// eStyleUnit_Percent
Percent(f32), Percent(f32),
/// eStyleUnit_Factor
Factor(f32), Factor(f32),
/// eStyleUnit_Degree
Degree(f32), Degree(f32),
/// eStyleUnit_Grad
Grad(f32), Grad(f32),
/// eStyleUnit_Radian
Radian(f32), Radian(f32),
/// eStyleUnit_Turn
Turn(f32), Turn(f32),
/// eStyleUnit_FlexFraction
FlexFraction(f32), FlexFraction(f32),
/// eStyleUnit_Coord
Coord(nscoord), Coord(nscoord),
/// eStyleUnit_Integer
Integer(i32), Integer(i32),
/// eStyleUnit_Enumerated
Enumerated(u32), Enumerated(u32),
/// eStyleUnit_Calc
Calc(nsStyleCoord_CalcValue), Calc(nsStyleCoord_CalcValue),
} }
/// A trait to abstract on top of a mutable `nsStyleCoord`-like object.
pub trait CoordDataMut : CoordData { pub trait CoordDataMut : CoordData {
// This can't be two methods since we can't mutably borrow twice /// Get mutably the unit and the union.
/// This is unsafe since it's possible to modify ///
/// the unit without changing the union /// This is unsafe since it's possible to modify the unit without changing
/// the union.
///
/// NB: This can't be two methods since we can't mutably borrow twice
unsafe fn values_mut(&mut self) -> (&mut nsStyleUnit, &mut nsStyleUnion); unsafe fn values_mut(&mut self) -> (&mut nsStyleUnit, &mut nsStyleUnion);
/// Clean up any resources used by the union /// Clean up any resources used by the union.
/// Currently, this only happens if the nsStyleUnit ///
/// is a Calc /// Currently, this only happens if the nsStyleUnit is a Calc.
#[inline] #[inline]
fn reset(&mut self) { fn reset(&mut self) {
unsafe { unsafe {
@ -213,27 +255,26 @@ pub trait CoordDataMut : CoordData {
} }
#[inline] #[inline]
/// Copies the unit and value from another `CoordData` type.
fn copy_from<T: CoordData>(&mut self, other: &T) { fn copy_from<T: CoordData>(&mut self, other: &T) {
unsafe { unsafe {
self.reset(); self.reset();
{ self.copy_from_unchecked(other);
let (unit, union) = self.values_mut();
*unit = other.unit();
*union = other.union();
}
self.addref_if_calc(); self.addref_if_calc();
} }
} }
#[inline] #[inline]
/// Copies the unit and value from another `CoordData` type without checking
/// the type of the value (so refcounted values like calc may leak).
unsafe fn copy_from_unchecked<T: CoordData>(&mut self, other: &T) { unsafe fn copy_from_unchecked<T: CoordData>(&mut self, other: &T) {
let (unit, union) = self.values_mut(); let (unit, union) = self.values_mut();
*unit = other.unit(); *unit = other.unit();
*union = other.union(); *union = other.union();
} }
/// Useful for initializing uninits /// Useful for initializing uninits, given that `set_value` may segfault on
/// (set_value may segfault on uninits) /// uninits.
fn leaky_set_null(&mut self) { fn leaky_set_null(&mut self) {
use gecko_bindings::structs::nsStyleUnit::*; use gecko_bindings::structs::nsStyleUnit::*;
unsafe { unsafe {
@ -244,6 +285,7 @@ pub trait CoordDataMut : CoordData {
} }
#[inline(always)] #[inline(always)]
/// Sets the inner value.
fn set_value(&mut self, value: CoordDataValue) { fn set_value(&mut self, value: CoordDataValue) {
use gecko_bindings::structs::nsStyleUnit::*; use gecko_bindings::structs::nsStyleUnit::*;
use self::CoordDataValue::*; use self::CoordDataValue::*;
@ -316,12 +358,16 @@ pub trait CoordDataMut : CoordData {
} }
#[inline] #[inline]
/// Gets the `Calc` value mutably, asserts in debug builds if the unit is
/// not `Calc`.
unsafe fn as_calc_mut(&mut self) -> &mut nsStyleCoord_Calc { unsafe fn as_calc_mut(&mut self) -> &mut nsStyleCoord_Calc {
debug_assert!(self.unit() == nsStyleUnit::eStyleUnit_Calc); debug_assert!(self.unit() == nsStyleUnit::eStyleUnit_Calc);
&mut *(*self.union().mPointer.as_mut() as *mut nsStyleCoord_Calc) &mut *(*self.union().mPointer.as_mut() as *mut nsStyleCoord_Calc)
} }
#[inline] #[inline]
/// Does what it promises, if the unit is `calc`, it bumps the reference
/// count _of the calc expression_.
fn addref_if_calc(&mut self) { fn addref_if_calc(&mut self) {
unsafe { unsafe {
if self.unit() == nsStyleUnit::eStyleUnit_Calc { if self.unit() == nsStyleUnit::eStyleUnit_Calc {
@ -330,12 +376,16 @@ pub trait CoordDataMut : CoordData {
} }
} }
} }
/// A trait to abstract on top of a `nsStyleCoord`-like object.
pub trait CoordData { pub trait CoordData {
/// Get the unit of this object.
fn unit(&self) -> nsStyleUnit; fn unit(&self) -> nsStyleUnit;
/// Get the `nsStyleUnion` for this object.
fn union(&self) -> nsStyleUnion; fn union(&self) -> nsStyleUnion;
#[inline(always)] #[inline(always)]
/// Get the appropriate value for this object.
fn as_value(&self) -> CoordDataValue { fn as_value(&self) -> CoordDataValue {
use gecko_bindings::structs::nsStyleUnit::*; use gecko_bindings::structs::nsStyleUnit::*;
use self::CoordDataValue::*; use self::CoordDataValue::*;
@ -390,6 +440,7 @@ pub trait CoordData {
#[inline] #[inline]
/// Pretend the inner value is a calc expression, and obtain it.
unsafe fn as_calc(&self) -> &nsStyleCoord_Calc { unsafe fn as_calc(&self) -> &nsStyleCoord_Calc {
debug_assert!(self.unit() == nsStyleUnit::eStyleUnit_Calc); debug_assert!(self.unit() == nsStyleUnit::eStyleUnit_Calc);
&*(*self.union().mPointer.as_ref() as *const nsStyleCoord_Calc) &*(*self.union().mPointer.as_ref() as *const nsStyleCoord_Calc)