Skip to content

Commit eb6dd87

Browse files
committed
Add MaybeOwned, and use for ServoNodeData. More docs.
1 parent 8874416 commit eb6dd87

File tree

5 files changed

+216
-32
lines changed

5 files changed

+216
-32
lines changed

ports/geckolib/binding_tools/regen.py

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -150,12 +150,16 @@
150150
"void_types": [
151151
"nsINode", "nsIDocument", "nsIPrincipal", "nsIURI",
152152
],
153-
"servo_arc_types": [
153+
"servo_maybe_arc_types": [
154154
"ServoComputedValues", "RawServoStyleSheet",
155155
"ServoDeclarationBlock"
156156
],
157157
"servo_owned_types": [
158158
"RawServoStyleSet",
159+
"RawGeckoNode",
160+
],
161+
"servo_maybe_owned_types": [
162+
"ServoNodeData",
159163
],
160164
},
161165

@@ -318,8 +322,8 @@ def build(objdir, target_name, debug, debugger, kind_name=None,
318322
for ty in current_target["void_types"]:
319323
flags.append("--raw-line")
320324
flags.append("pub enum {} {{}}".format(ty))
321-
if "servo_arc_types" in current_target:
322-
for ty in current_target["servo_arc_types"]:
325+
if "servo_maybe_arc_types" in current_target:
326+
for ty in current_target["servo_maybe_arc_types"]:
323327
flags.append("--blacklist-type")
324328
flags.append("{}Strong".format(ty))
325329
flags.append("--raw-line")
@@ -342,6 +346,22 @@ def build(objdir, target_name, debug, debugger, kind_name=None,
342346
flags.append("{}Owned".format(ty))
343347
flags.append("--raw-line")
344348
flags.append("pub type {0}Owned = ::sugar::ownership::Owned<{0}>;".format(ty))
349+
if "servo_maybe_owned_types" in current_target:
350+
for ty in current_target["servo_maybe_owned_types"]:
351+
flags.append("--blacklist-type")
352+
flags.append("{}Borrowed".format(ty))
353+
flags.append("--raw-line")
354+
flags.append("pub type {0}Borrowed<'a> = ::sugar::ownership::Borrowed<'a, {0}>;"
355+
.format(ty))
356+
flags.append("--blacklist-type")
357+
flags.append("{}BorrowedMut".format(ty))
358+
flags.append("--raw-line")
359+
flags.append("pub type {0}BorrowedMut<'a> = ::sugar::ownership::BorrowedMut<'a, {0}>;"
360+
.format(ty))
361+
flags.append("--blacklist-type")
362+
flags.append("{}Owned".format(ty))
363+
flags.append("--raw-line")
364+
flags.append("pub type {0}Owned = ::sugar::ownership::MaybeOwned<{0}>;".format(ty))
345365
if "structs_types" in current_target:
346366
for ty in current_target["structs_types"]:
347367
ty_fragments = ty.split("::")

ports/geckolib/gecko_bindings/bindings.rs

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,12 @@ pub type ServoDeclarationBlockBorrowed<'a> = ::sugar::ownership::Borrowed<'a, Se
1414
pub type RawServoStyleSetBorrowed<'a> = &'a RawServoStyleSet;
1515
pub type RawServoStyleSetBorrowedMut<'a> = &'a mut RawServoStyleSet;
1616
pub type RawServoStyleSetOwned = ::sugar::ownership::Owned<RawServoStyleSet>;
17+
pub type RawGeckoNodeBorrowed<'a> = &'a RawGeckoNode;
18+
pub type RawGeckoNodeBorrowedMut<'a> = &'a mut RawGeckoNode;
19+
pub type RawGeckoNodeOwned = ::sugar::ownership::Owned<RawGeckoNode>;
20+
pub type ServoNodeDataBorrowed<'a> = ::sugar::ownership::Borrowed<'a, ServoNodeData>;
21+
pub type ServoNodeDataBorrowedMut<'a> = ::sugar::ownership::BorrowedMut<'a, ServoNodeData>;
22+
pub type ServoNodeDataOwned = ::sugar::ownership::MaybeOwned<ServoNodeData>;
1723
use structs::nsStyleFont;
1824
unsafe impl Send for nsStyleFont {}
1925
unsafe impl Sync for nsStyleFont {}
@@ -267,9 +273,10 @@ extern "C" {
267273
-> u32;
268274
pub fn Gecko_GetServoDeclarationBlock(element: *mut RawGeckoElement)
269275
-> ServoDeclarationBlockBorrowed;
270-
pub fn Gecko_GetNodeData(node: *mut RawGeckoNode) -> *mut ServoNodeData;
271-
pub fn Gecko_SetNodeData(node: *mut RawGeckoNode,
272-
data: *mut ServoNodeData);
276+
pub fn Gecko_GetNodeData(node: RawGeckoNodeBorrowed)
277+
-> ServoNodeDataBorrowed;
278+
pub fn Gecko_SetNodeData(node: RawGeckoNodeBorrowedMut,
279+
data: ServoNodeDataOwned);
273280
pub fn Gecko_Atomize(aString: *const ::std::os::raw::c_char, aLength: u32)
274281
-> *mut nsIAtom;
275282
pub fn Gecko_AddRefAtom(aAtom: *mut nsIAtom);
@@ -459,7 +466,7 @@ extern "C" {
459466
pub fn Gecko_CopyConstruct_nsStyleEffects(ptr: *mut nsStyleEffects,
460467
other: *const nsStyleEffects);
461468
pub fn Gecko_Destroy_nsStyleEffects(ptr: *mut nsStyleEffects);
462-
pub fn Servo_NodeData_Drop(data: *mut ServoNodeData);
469+
pub fn Servo_NodeData_Drop(data: ServoNodeDataOwned);
463470
pub fn Servo_StyleSheet_FromUTF8Bytes(bytes: *const u8, length: u32,
464471
parsing_mode: SheetParsingMode,
465472
base_bytes: *const u8,

ports/geckolib/gecko_bindings/sugar/ownership.rs

Lines changed: 152 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,15 +19,35 @@ pub unsafe trait HasFFI : Sized {
1919
/// Indicates that a given Servo type has the same layout
2020
/// as the corresponding HasFFI::FFIType type
2121
pub unsafe trait HasSimpleFFI : HasFFI {
22+
#[inline]
23+
/// Given a Servo-side reference, converts it to an
24+
/// FFI-safe reference which can be passed to Gecko
25+
///
26+
/// &ServoType -> &GeckoType
2227
fn as_ffi(&self) -> &Self::FFIType {
2328
unsafe { transmute(self) }
2429
}
30+
#[inline]
31+
/// Given a Servo-side mutable reference, converts it to an
32+
/// FFI-safe mutable reference which can be passed to Gecko
33+
///
34+
/// &mut ServoType -> &mut GeckoType
2535
fn as_ffi_mut(&mut self) -> &mut Self::FFIType {
2636
unsafe { transmute(self) }
2737
}
38+
#[inline]
39+
/// Given an FFI-safe reference obtained from Gecko
40+
/// converts it to a Servo-side reference
41+
///
42+
/// &GeckoType -> &ServoType
2843
fn from_ffi(ffi: &Self::FFIType) -> &Self {
2944
unsafe { transmute(ffi) }
3045
}
46+
#[inline]
47+
/// Given an FFI-safe mutable reference obtained from Gecko
48+
/// converts it to a Servo-side mutable reference
49+
///
50+
/// &mut GeckoType -> &mut ServoType
3151
fn from_ffi_mut(ffi: &mut Self::FFIType) -> &mut Self {
3252
unsafe { transmute(ffi) }
3353
}
@@ -36,6 +56,7 @@ pub unsafe trait HasSimpleFFI : HasFFI {
3656
/// Indicates that the given Servo type is passed over FFI
3757
/// as a Box
3858
pub unsafe trait HasBoxFFI : HasSimpleFFI {
59+
#[inline]
3960
fn into_ffi(self: Box<Self>) -> Owned<Self::FFIType> {
4061
unsafe { transmute(self) }
4162
}
@@ -67,25 +88,47 @@ pub unsafe trait HasArcFFI : HasFFI {
6788
}
6889

6990
#[repr(C)]
70-
/// Gecko-FFI-safe borrowed Arc (&T where T is an ArcInner).
91+
/// Gecko-FFI-safe borrowed type
7192
/// This can be null.
7293
pub struct Borrowed<'a, T: 'a> {
7394
ptr: *const T,
7495
_marker: PhantomData<&'a T>,
7596
}
7697

98+
#[repr(C)]
99+
/// Gecko-FFI-safe mutably borrowed type
100+
/// This can be null.
101+
pub struct BorrowedMut<'a, T: 'a> {
102+
ptr: *mut T,
103+
_marker: PhantomData<&'a mut T>,
104+
}
105+
77106
// manual impls because derive doesn't realize that `T: Clone` isn't necessary
78107
impl<'a, T> Copy for Borrowed<'a, T> {}
79108

80109
impl<'a, T> Clone for Borrowed<'a, T> {
110+
#[inline]
81111
fn clone(&self) -> Self { *self }
82112
}
83113

84114
impl<'a, T> Borrowed<'a, T> {
115+
#[inline]
85116
pub fn is_null(&self) -> bool {
86117
self.ptr == ptr::null()
87118
}
88119

120+
#[inline]
121+
/// Like Deref, but gives an Option
122+
pub fn borrow_opt(self) -> Option<&'a T> {
123+
if self.is_null() {
124+
None
125+
} else {
126+
Some(unsafe { &*self.ptr })
127+
}
128+
}
129+
130+
#[inline]
131+
/// Borrowed<GeckoType> -> Option<&Arc<ServoType>>
89132
pub fn as_arc_opt<U>(&self) -> Option<&Arc<U>> where U: HasArcFFI<FFIType = T> {
90133
unsafe {
91134
if self.is_null() {
@@ -96,11 +139,71 @@ impl<'a, T> Borrowed<'a, T> {
96139
}
97140
}
98141

142+
#[inline]
99143
/// Converts a borrowed FFI reference to a borrowed Arc.
100-
/// Panics on null
144+
/// Panics on null.
145+
///
146+
/// &Borrowed<GeckoType> -> &Arc<ServoType>
101147
pub fn as_arc<U>(&self) -> &Arc<U> where U: HasArcFFI<FFIType = T> {
102148
self.as_arc_opt().unwrap()
103149
}
150+
151+
#[inline]
152+
/// Borrowed<ServoType> -> Borrowed<GeckoType>
153+
pub fn as_ffi(&self) -> Borrowed<<Self as HasFFI>::FFIType> where Self: HasSimpleFFI {
154+
unsafe { transmute(self) }
155+
}
156+
157+
#[inline]
158+
/// Borrowed<GeckoType> -> Borrowed<ServoType>
159+
pub fn from_ffi<U>(self) -> Borrowed<'a, U> where U: HasSimpleFFI<FFIType = T> {
160+
unsafe { transmute(self) }
161+
}
162+
163+
#[inline]
164+
/// Borrowed<GeckoType> -> &ServoType
165+
pub fn as_servo_ref<U>(self) -> Option<&'a U> where U: HasSimpleFFI<FFIType = T> {
166+
self.borrow_opt().map(HasSimpleFFI::from_ffi)
167+
}
168+
}
169+
170+
impl<'a, T> BorrowedMut<'a, T> {
171+
#[inline]
172+
/// Like DerefMut, but gives an Option
173+
pub fn borrow_mut_opt(self) -> Option<&'a mut T> {
174+
// We have two choices for the signature here, it can either be
175+
// Self -> Option<&'a mut T> or
176+
// &'b mut Self -> Option<'b mut T>
177+
// The former consumes the BorrowedMut (which isn't Copy),
178+
// which can be annoying. The latter only temporarily
179+
// borrows it, so the return value can't exit the scope
180+
// even if Self has a longer lifetime ('a)
181+
//
182+
// This is basically the implicit "reborrow" pattern used with &mut
183+
// not cleanly translating to our custom types.
184+
185+
// I've chosen the former solution -- you can manually convert back
186+
// if you need to reuse the BorrowedMut.
187+
if self.is_null() {
188+
None
189+
} else {
190+
Some(unsafe { &mut *self.ptr })
191+
}
192+
}
193+
194+
#[inline]
195+
/// BorrowedMut<GeckoType> -> &mut ServoType
196+
pub fn as_servo_mut_ref<U>(self) -> Option<&'a mut U> where U: HasSimpleFFI<FFIType = T> {
197+
self.borrow_mut_opt().map(HasSimpleFFI::from_ffi_mut)
198+
}
199+
}
200+
201+
// technically not
202+
impl<'a, T> Deref for BorrowedMut<'a, T> {
203+
type Target = Borrowed<'a, T>;
204+
fn deref(&self) -> &Self::Target {
205+
unsafe { transmute(self) }
206+
}
104207
}
105208

106209
#[repr(C)]
@@ -112,17 +215,23 @@ pub struct Strong<T> {
112215
}
113216

114217
impl<T> Strong<T> {
218+
#[inline]
115219
pub fn is_null(&self) -> bool {
116220
self.ptr == ptr::null()
117221
}
118222

119-
/// Given a non-null strong FFI reference, converts it into an Arc.
223+
#[inline]
224+
/// Given a non-null strong FFI reference,
225+
/// converts it into a servo-side Arc
120226
/// Panics on null.
227+
///
228+
/// Strong<GeckoType> -> Arc<ServoType>
121229
pub fn into_arc<U>(self) -> Arc<U> where U: HasArcFFI<FFIType = T> {
122230
assert!(!self.is_null());
123231
unsafe { transmute(self) }
124232
}
125233

234+
#[inline]
126235
/// Produces a null strong FFI reference
127236
pub fn null_strong() -> Self {
128237
unsafe { transmute(ptr::null::<T>()) }
@@ -132,16 +241,22 @@ impl<T> Strong<T> {
132241
pub unsafe trait FFIArcHelpers {
133242
type Inner: HasArcFFI;
134243
/// Converts an Arc into a strong FFI reference.
244+
///
245+
/// Arc<ServoType> -> Strong<GeckoType>
135246
fn into_strong(self) -> Strong<<Self::Inner as HasFFI>::FFIType>;
136247
/// Produces a borrowed FFI reference by borrowing an Arc.
248+
///
249+
/// &Arc<ServoType> -> Borrowed<GeckoType>
137250
fn as_borrowed(&self) -> Borrowed<<Self::Inner as HasFFI>::FFIType>;
138251
}
139252

140253
unsafe impl<T: HasArcFFI> FFIArcHelpers for Arc<T> {
141254
type Inner = T;
255+
#[inline]
142256
fn into_strong(self) -> Strong<T::FFIType> {
143257
unsafe { transmute(self) }
144258
}
259+
#[inline]
145260
fn as_borrowed(&self) -> Borrowed<T::FFIType> {
146261
let borrowedptr = self as *const Arc<T> as *const Borrowed<T::FFIType>;
147262
unsafe { ptr::read(borrowedptr) }
@@ -157,9 +272,13 @@ pub struct Owned<T> {
157272
}
158273

159274
impl<T> Owned<T> {
275+
/// Owned<GeckoType> -> Box<ServoType>
160276
pub fn into_box<U>(self) -> Box<T> where U: HasBoxFFI<FFIType = T> {
161277
unsafe { transmute(self) }
162278
}
279+
pub fn maybe(self) -> MaybeOwned<T> {
280+
unsafe { transmute(self) }
281+
}
163282
}
164283

165284
impl<T> Deref for Owned<T> {
@@ -174,3 +293,33 @@ impl<T> DerefMut for Owned<T> {
174293
unsafe { &mut *self.ptr }
175294
}
176295
}
296+
297+
#[repr(C)]
298+
/// Gecko-FFI-safe owned pointer
299+
/// Can be null
300+
pub struct MaybeOwned<T> {
301+
ptr: *mut T,
302+
_marker: PhantomData<T>,
303+
}
304+
305+
impl<T> MaybeOwned<T> {
306+
pub fn is_null(&self) -> bool {
307+
self.ptr == ptr::null_mut()
308+
}
309+
/// MaybeOwned<GeckoType> -> Option<Box<ServoType>>
310+
pub fn into_box_opt<U>(self) -> Option<Box<T>> where U: HasBoxFFI<FFIType = T> {
311+
if self.is_null() {
312+
None
313+
} else {
314+
Some(unsafe { transmute(self) })
315+
}
316+
}
317+
318+
pub fn borrow(&self) -> Borrowed<T> {
319+
unsafe { transmute(self) }
320+
}
321+
322+
pub fn borrow_mut(&self) -> BorrowedMut<T> {
323+
unsafe { transmute(self) }
324+
}
325+
}

ports/geckolib/glue.rs

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,10 @@ use env_logger;
1010
use euclid::Size2D;
1111
use gecko_bindings::bindings::{RawGeckoDocument, RawGeckoElement, RawGeckoNode};
1212
use gecko_bindings::bindings::{RawServoStyleSet, RawServoStyleSetBorrowedMut};
13-
use gecko_bindings::bindings::RawServoStyleSetOwned;
13+
use gecko_bindings::bindings::{RawServoStyleSetOwned, ServoNodeDataOwned};
1414
use gecko_bindings::bindings::{RawServoStyleSheetBorrowed, ServoComputedValuesBorrowed};
1515
use gecko_bindings::bindings::{RawServoStyleSheetStrong, ServoComputedValuesStrong};
16-
use gecko_bindings::bindings::{ServoDeclarationBlock, ServoNodeData, ThreadSafePrincipalHolder};
16+
use gecko_bindings::bindings::{ServoDeclarationBlock, ThreadSafePrincipalHolder};
1717
use gecko_bindings::bindings::{ServoDeclarationBlockBorrowed, ServoDeclarationBlockStrong};
1818
use gecko_bindings::bindings::{ThreadSafeURIHolder, nsHTMLCSSStyleSheet};
1919
use gecko_bindings::ptr::{GeckoArcPrincipal, GeckoArcURI};
@@ -136,10 +136,8 @@ pub extern "C" fn Servo_StyleWorkerThreadCount() -> u32 {
136136
}
137137

138138
#[no_mangle]
139-
pub extern "C" fn Servo_NodeData_Drop(data: *mut ServoNodeData) -> () {
140-
unsafe {
141-
let _ = Box::<NonOpaqueStyleData>::from_raw(data as *mut NonOpaqueStyleData);
142-
}
139+
pub extern "C" fn Servo_NodeData_Drop(data: ServoNodeDataOwned) -> () {
140+
let _ = data.into_box_opt::<NonOpaqueStyleData>();
143141
}
144142

145143
#[no_mangle]

0 commit comments

Comments
 (0)