1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
|
/* 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 https://mozilla.org/MPL/2.0/. */
//! Helpers for different FFI pointer kinds that Gecko's FFI layer uses.
use crate::gecko_bindings::structs::root::mozilla::detail::CopyablePtr;
use servo_arc::{Arc, RawOffsetArc};
use std::marker::PhantomData;
use std::mem::{forget, transmute};
use std::ops::{Deref, DerefMut};
use std::ptr;
/// Indicates that a given Servo type has a corresponding Gecko FFI type.
pub unsafe trait HasFFI: Sized + 'static {
/// The corresponding Gecko type that this rust type represents.
///
/// See the examples in `components/style/gecko/conversions.rs`.
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]
/// Converts a borrowed Arc to a borrowed FFI reference.
///
/// &Arc<ServoType> -> &GeckoType
fn into_ffi(self: Box<Self>) -> Owned<Self::FFIType> {
unsafe { transmute(self) }
}
/// Drops an owned FFI pointer. This conceptually takes the
/// Owned<Self::FFIType>, except it's a bit of a paint to do that without
/// much benefit.
#[inline]
unsafe fn drop_ffi(ptr: *mut Self::FFIType) {
let _ = Box::from_raw(ptr as *mut 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: Option<&Self::FFIType>) {
forget(Self::arc_from_borrowed(&ptr).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: Option<&Self::FFIType>) {
if let Some(arc) = Self::arc_from_borrowed(&ptr) {
let _: RawOffsetArc<_> = ptr::read(arc as *const RawOffsetArc<_>);
}
}
/// 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 _: RawOffsetArc<_> = ptr::read(Self::as_arc(&ptr) as *const RawOffsetArc<_>);
}
#[inline]
/// Converts a borrowed FFI reference to a borrowed Arc.
///
/// &GeckoType -> &Arc<ServoType>
fn as_arc<'a>(ptr: &'a &Self::FFIType) -> &'a RawOffsetArc<Self> {
unsafe { transmute::<&&Self::FFIType, &RawOffsetArc<Self>>(ptr) }
}
#[inline]
/// Converts a borrowed Arc to a borrowed FFI reference.
///
/// &Arc<ServoType> -> &GeckoType
fn arc_as_borrowed<'a>(arc: &'a RawOffsetArc<Self>) -> &'a &Self::FFIType {
unsafe { transmute::<&RawOffsetArc<Self>, &&Self::FFIType>(arc) }
}
#[inline]
/// Converts a borrowed nullable FFI reference to a borrowed Arc.
///
/// &GeckoType -> &Arc<ServoType>
fn arc_from_borrowed<'a>(ptr: &'a Option<&Self::FFIType>) -> Option<&'a RawOffsetArc<Self>> {
unsafe {
if let Some(ref reference) = *ptr {
Some(transmute::<&&Self::FFIType, &RawOffsetArc<_>>(reference))
} else {
None
}
}
}
}
/// Gecko-FFI-safe Arc (T is an ArcInner).
///
/// This can be null.
///
/// Leaks on drop. Please don't drop this.
#[repr(C)]
pub struct Strong<GeckoType> {
ptr: *const GeckoType,
_marker: PhantomData<GeckoType>,
}
impl<GeckoType> Strong<GeckoType> {
#[inline]
/// Returns whether this reference is null.
pub fn is_null(&self) -> bool {
self.ptr.is_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<ServoType>(self) -> RawOffsetArc<ServoType>
where
ServoType: HasArcFFI<FFIType = GeckoType>,
{
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<ServoType>(self) -> Option<RawOffsetArc<ServoType>>
where
ServoType: HasArcFFI<FFIType = GeckoType>,
{
if self.is_null() {
None
} else {
unsafe { Some(transmute(self)) }
}
}
#[inline]
/// Given a reference to a strong FFI reference, converts it to a reference
/// to a servo-side Arc.
///
/// Returns None on null.
///
/// Strong<GeckoType> -> Arc<ServoType>
pub fn as_arc_opt<ServoType>(&self) -> Option<&RawOffsetArc<ServoType>>
where
ServoType: HasArcFFI<FFIType = GeckoType>,
{
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::<GeckoType>()) }
}
}
/// A few helpers implemented on top of Arc<ServoType> to make it more
/// comfortable to use and write safe code with.
pub unsafe trait FFIArcHelpers {
/// The Rust FFI type that we're implementing methods for.
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 borrowed FFI reference by borrowing an Arc.
///
/// &Arc<ServoType> -> &GeckoType
///
/// Then the `arc_as_borrowed` method can go away.
fn as_borrowed(&self) -> &<Self::Inner as HasFFI>::FFIType;
}
unsafe impl<T: HasArcFFI> FFIArcHelpers for RawOffsetArc<T> {
type Inner = T;
#[inline]
fn into_strong(self) -> Strong<T::FFIType> {
unsafe { transmute(self) }
}
#[inline]
fn as_borrowed(&self) -> &T::FFIType {
unsafe { &*(&**self as *const T as *const T::FFIType) }
}
}
unsafe impl<T: HasArcFFI> FFIArcHelpers for Arc<T> {
type Inner = T;
#[inline]
fn into_strong(self) -> Strong<T::FFIType> {
Arc::into_raw_offset(self).into_strong()
}
#[inline]
fn as_borrowed(&self) -> &T::FFIType {
unsafe { &*(&**self as *const T as *const T::FFIType) }
}
}
#[repr(C)]
#[derive(Debug)]
/// Gecko-FFI-safe owned pointer.
///
/// Cannot be null, and leaks on drop, so needs to be converted into a rust-side
/// `Box` before.
pub struct Owned<GeckoType> {
ptr: *mut GeckoType,
_marker: PhantomData<GeckoType>,
}
impl<GeckoType> Owned<GeckoType> {
/// Converts this instance to a (non-null) instance of `OwnedOrNull`.
pub fn maybe(self) -> OwnedOrNull<GeckoType> {
unsafe { transmute(self) }
}
}
impl<GeckoType> Deref for Owned<GeckoType> {
type Target = GeckoType;
fn deref(&self) -> &GeckoType {
unsafe { &*self.ptr }
}
}
impl<GeckoType> DerefMut for Owned<GeckoType> {
fn deref_mut(&mut self) -> &mut GeckoType {
unsafe { &mut *self.ptr }
}
}
#[repr(C)]
/// Gecko-FFI-safe owned pointer.
///
/// Can be null, and just as `Owned` leaks on `Drop`.
pub struct OwnedOrNull<GeckoType> {
ptr: *mut GeckoType,
_marker: PhantomData<GeckoType>,
}
impl<GeckoType> OwnedOrNull<GeckoType> {
/// Returns a null pointer.
#[inline]
pub fn null() -> Self {
Self {
ptr: ptr::null_mut(),
_marker: PhantomData,
}
}
/// Returns whether this pointer is null.
#[inline]
pub fn is_null(&self) -> bool {
self.ptr.is_null()
}
/// Gets a immutable reference to the underlying Gecko type, or `None` if
/// null.
pub fn borrow(&self) -> Option<&GeckoType> {
unsafe { transmute(self) }
}
/// Gets a mutable reference to the underlying Gecko type, or `None` if
/// null.
pub fn borrow_mut(&self) -> Option<&mut GeckoType> {
unsafe { transmute(self) }
}
}
impl<T> Deref for CopyablePtr<T> {
type Target = T;
fn deref(&self) -> &Self::Target {
&self.mPtr
}
}
impl<T> DerefMut for CopyablePtr<T> {
fn deref_mut<'a>(&'a mut self) -> &'a mut T {
&mut self.mPtr
}
}
|