@@ -19,15 +19,35 @@ pub unsafe trait HasFFI : Sized {
19
19
/// Indicates that a given Servo type has the same layout
20
20
/// as the corresponding HasFFI::FFIType type
21
21
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
22
27
fn as_ffi ( & self ) -> & Self :: FFIType {
23
28
unsafe { transmute ( self ) }
24
29
}
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
25
35
fn as_ffi_mut ( & mut self ) -> & mut Self :: FFIType {
26
36
unsafe { transmute ( self ) }
27
37
}
38
+ #[ inline]
39
+ /// Given an FFI-safe reference obtained from Gecko
40
+ /// converts it to a Servo-side reference
41
+ ///
42
+ /// &GeckoType -> &ServoType
28
43
fn from_ffi ( ffi : & Self :: FFIType ) -> & Self {
29
44
unsafe { transmute ( ffi) }
30
45
}
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
31
51
fn from_ffi_mut ( ffi : & mut Self :: FFIType ) -> & mut Self {
32
52
unsafe { transmute ( ffi) }
33
53
}
@@ -36,6 +56,7 @@ pub unsafe trait HasSimpleFFI : HasFFI {
36
56
/// Indicates that the given Servo type is passed over FFI
37
57
/// as a Box
38
58
pub unsafe trait HasBoxFFI : HasSimpleFFI {
59
+ #[ inline]
39
60
fn into_ffi ( self : Box < Self > ) -> Owned < Self :: FFIType > {
40
61
unsafe { transmute ( self ) }
41
62
}
@@ -67,25 +88,47 @@ pub unsafe trait HasArcFFI : HasFFI {
67
88
}
68
89
69
90
#[ repr( C ) ]
70
- /// Gecko-FFI-safe borrowed Arc (&T where T is an ArcInner).
91
+ /// Gecko-FFI-safe borrowed type
71
92
/// This can be null.
72
93
pub struct Borrowed < ' a , T : ' a > {
73
94
ptr : * const T ,
74
95
_marker : PhantomData < & ' a T > ,
75
96
}
76
97
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
+
77
106
// manual impls because derive doesn't realize that `T: Clone` isn't necessary
78
107
impl < ' a , T > Copy for Borrowed < ' a , T > { }
79
108
80
109
impl < ' a , T > Clone for Borrowed < ' a , T > {
110
+ #[ inline]
81
111
fn clone ( & self ) -> Self { * self }
82
112
}
83
113
84
114
impl < ' a , T > Borrowed < ' a , T > {
115
+ #[ inline]
85
116
pub fn is_null ( & self ) -> bool {
86
117
self . ptr == ptr:: null ( )
87
118
}
88
119
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>>
89
132
pub fn as_arc_opt < U > ( & self ) -> Option < & Arc < U > > where U : HasArcFFI < FFIType = T > {
90
133
unsafe {
91
134
if self . is_null ( ) {
@@ -96,11 +139,71 @@ impl<'a, T> Borrowed<'a, T> {
96
139
}
97
140
}
98
141
142
+ #[ inline]
99
143
/// Converts a borrowed FFI reference to a borrowed Arc.
100
- /// Panics on null
144
+ /// Panics on null.
145
+ ///
146
+ /// &Borrowed<GeckoType> -> &Arc<ServoType>
101
147
pub fn as_arc < U > ( & self ) -> & Arc < U > where U : HasArcFFI < FFIType = T > {
102
148
self . as_arc_opt ( ) . unwrap ( )
103
149
}
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
+ }
104
207
}
105
208
106
209
#[ repr( C ) ]
@@ -112,17 +215,23 @@ pub struct Strong<T> {
112
215
}
113
216
114
217
impl < T > Strong < T > {
218
+ #[ inline]
115
219
pub fn is_null ( & self ) -> bool {
116
220
self . ptr == ptr:: null ( )
117
221
}
118
222
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
120
226
/// Panics on null.
227
+ ///
228
+ /// Strong<GeckoType> -> Arc<ServoType>
121
229
pub fn into_arc < U > ( self ) -> Arc < U > where U : HasArcFFI < FFIType = T > {
122
230
assert ! ( !self . is_null( ) ) ;
123
231
unsafe { transmute ( self ) }
124
232
}
125
233
234
+ #[ inline]
126
235
/// Produces a null strong FFI reference
127
236
pub fn null_strong ( ) -> Self {
128
237
unsafe { transmute ( ptr:: null :: < T > ( ) ) }
@@ -132,16 +241,22 @@ impl<T> Strong<T> {
132
241
pub unsafe trait FFIArcHelpers {
133
242
type Inner : HasArcFFI ;
134
243
/// Converts an Arc into a strong FFI reference.
244
+ ///
245
+ /// Arc<ServoType> -> Strong<GeckoType>
135
246
fn into_strong ( self ) -> Strong < <Self :: Inner as HasFFI >:: FFIType > ;
136
247
/// Produces a borrowed FFI reference by borrowing an Arc.
248
+ ///
249
+ /// &Arc<ServoType> -> Borrowed<GeckoType>
137
250
fn as_borrowed ( & self ) -> Borrowed < <Self :: Inner as HasFFI >:: FFIType > ;
138
251
}
139
252
140
253
unsafe impl < T : HasArcFFI > FFIArcHelpers for Arc < T > {
141
254
type Inner = T ;
255
+ #[ inline]
142
256
fn into_strong ( self ) -> Strong < T :: FFIType > {
143
257
unsafe { transmute ( self ) }
144
258
}
259
+ #[ inline]
145
260
fn as_borrowed ( & self ) -> Borrowed < T :: FFIType > {
146
261
let borrowedptr = self as * const Arc < T > as * const Borrowed < T :: FFIType > ;
147
262
unsafe { ptr:: read ( borrowedptr) }
@@ -157,9 +272,13 @@ pub struct Owned<T> {
157
272
}
158
273
159
274
impl < T > Owned < T > {
275
+ /// Owned<GeckoType> -> Box<ServoType>
160
276
pub fn into_box < U > ( self ) -> Box < T > where U : HasBoxFFI < FFIType = T > {
161
277
unsafe { transmute ( self ) }
162
278
}
279
+ pub fn maybe ( self ) -> MaybeOwned < T > {
280
+ unsafe { transmute ( self ) }
281
+ }
163
282
}
164
283
165
284
impl < T > Deref for Owned < T > {
@@ -174,3 +293,33 @@ impl<T> DerefMut for Owned<T> {
174
293
unsafe { & mut * self . ptr }
175
294
}
176
295
}
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
+ }
0 commit comments