1 | use skia_bindings::{ |
2 | C_SkRefCntBase_ref, C_SkRefCntBase_unique, C_SkRefCntBase_unref, SkNVRefCnt, SkRefCnt, |
3 | SkRefCntBase, |
4 | }; |
5 | use std::{ |
6 | hash::{Hash, Hasher}, |
7 | marker::PhantomData, |
8 | mem::{self, MaybeUninit}, |
9 | ops::{Deref, DerefMut, Index, IndexMut}, |
10 | ptr::{self, NonNull}, |
11 | slice, |
12 | }; |
13 | |
14 | // Re-export TryFrom / TryInto to make them available in all modules that use prelude::*. |
15 | pub use std::convert::{TryFrom, TryInto}; |
16 | |
17 | /// Convert any reference into any other. |
18 | pub(crate) unsafe fn transmute_ref<FromT, ToT>(from: &FromT) -> &ToT { |
19 | // TODO: can we do this statically for all instantiations of transmute_ref? |
20 | debug_assert_eq!(mem::size_of::<FromT>(), mem::size_of::<ToT>()); |
21 | &*(from as *const FromT as *const ToT) |
22 | } |
23 | |
24 | pub(crate) unsafe fn transmute_ref_mut<FromT, ToT>(from: &mut FromT) -> &mut ToT { |
25 | // TODO: can we do this statically for all instantiations of transmute_ref_mut? |
26 | debug_assert_eq!(mem::size_of::<FromT>(), mem::size_of::<ToT>()); |
27 | &mut *(from as *mut FromT as *mut ToT) |
28 | } |
29 | |
30 | pub(crate) trait IntoOption { |
31 | type Target; |
32 | fn into_option(self) -> Option<Self::Target>; |
33 | } |
34 | |
35 | impl<T> IntoOption for *const T { |
36 | type Target = *const T; |
37 | |
38 | fn into_option(self) -> Option<Self::Target> { |
39 | if !self.is_null() { |
40 | Some(self) |
41 | } else { |
42 | None |
43 | } |
44 | } |
45 | } |
46 | |
47 | impl<T> IntoOption for *mut T { |
48 | type Target = ptr::NonNull<T>; |
49 | |
50 | fn into_option(self) -> Option<Self::Target> { |
51 | ptr::NonNull::new(self) |
52 | } |
53 | } |
54 | |
55 | impl IntoOption for bool { |
56 | type Target = (); |
57 | |
58 | fn into_option(self) -> Option<Self::Target> { |
59 | if self { |
60 | Some(()) |
61 | } else { |
62 | None |
63 | } |
64 | } |
65 | } |
66 | |
67 | pub(crate) trait IfBoolSome { |
68 | fn if_true_some<V>(self, v: V) -> Option<V>; |
69 | fn if_false_some<V>(self, v: V) -> Option<V>; |
70 | fn if_true_then_some<V>(self, f: impl FnOnce() -> V) -> Option<V>; |
71 | fn if_false_then_some<V>(self, f: impl FnOnce() -> V) -> Option<V>; |
72 | } |
73 | |
74 | impl IfBoolSome for bool { |
75 | fn if_true_some<V>(self, v: V) -> Option<V> { |
76 | self.into_option().and(optb:Some(v)) |
77 | } |
78 | |
79 | fn if_false_some<V>(self, v: V) -> Option<V> { |
80 | (!self).if_true_some(v) |
81 | } |
82 | |
83 | fn if_true_then_some<V>(self, f: impl FnOnce() -> V) -> Option<V> { |
84 | self.into_option().map(|()| f()) |
85 | } |
86 | |
87 | fn if_false_then_some<V>(self, f: impl FnOnce() -> V) -> Option<V> { |
88 | (!self).into_option().map(|()| f()) |
89 | } |
90 | } |
91 | |
92 | pub(crate) trait RefCount { |
93 | fn ref_cnt(&self) -> usize; |
94 | } |
95 | |
96 | impl RefCount for SkRefCntBase { |
97 | // the problem here is that the binding generator represents std::atomic as an u8 (we |
98 | // are lucky that the C alignment rules make space for an i32), so to get the ref |
99 | // counter, we need to get the u8 pointer to fRefCnt and interpret it as an i32 pointer. |
100 | #[allow (clippy::cast_ptr_alignment)] |
101 | fn ref_cnt(&self) -> usize { |
102 | unsafe { |
103 | let ptr: *const i32 = &self.fRefCnt as *const _ as *const i32; |
104 | (*ptr).try_into().unwrap() |
105 | } |
106 | } |
107 | } |
108 | |
109 | impl NativeBase<SkRefCntBase> for SkRefCnt {} |
110 | |
111 | impl RefCount for SkRefCnt { |
112 | fn ref_cnt(&self) -> usize { |
113 | self.base().ref_cnt() |
114 | } |
115 | } |
116 | |
117 | impl RefCount for SkNVRefCnt { |
118 | #[allow (clippy::cast_ptr_alignment)] |
119 | fn ref_cnt(&self) -> usize { |
120 | unsafe { |
121 | let ptr: *const i32 = &self.fRefCnt as *const _ as *const i32; |
122 | (*ptr).try_into().unwrap() |
123 | } |
124 | } |
125 | } |
126 | |
127 | pub trait NativeRefCounted: Sized { |
128 | fn _ref(&self); |
129 | fn _unref(&self); |
130 | fn unique(&self) -> bool; |
131 | fn _ref_cnt(&self) -> usize { |
132 | unimplemented!(); |
133 | } |
134 | } |
135 | |
136 | impl NativeRefCounted for SkRefCntBase { |
137 | fn _ref(&self) { |
138 | unsafe { C_SkRefCntBase_ref(self) } |
139 | } |
140 | |
141 | fn _unref(&self) { |
142 | unsafe { C_SkRefCntBase_unref(self) } |
143 | } |
144 | |
145 | fn unique(&self) -> bool { |
146 | unsafe { C_SkRefCntBase_unique(self) } |
147 | } |
148 | |
149 | #[allow (clippy::cast_ptr_alignment)] |
150 | fn _ref_cnt(&self) -> usize { |
151 | unsafe { |
152 | let ptr: *const i32 = &self.fRefCnt as *const _ as *const i32; |
153 | (*ptr).try_into().unwrap() |
154 | } |
155 | } |
156 | } |
157 | |
158 | /// Implements NativeRefCounted by just providing a reference to the base class |
159 | /// that implements a RefCount. |
160 | /// TODO: use NativeBase |
161 | pub trait NativeRefCountedBase { |
162 | type Base: NativeRefCounted; |
163 | |
164 | /// Returns the ref counter base class of the ref counted type. |
165 | /// |
166 | /// Default implementation assumes that the base class ptr is the same as the |
167 | /// ptr to self. |
168 | fn ref_counted_base(&self) -> &Self::Base { |
169 | unsafe { &*(self as *const _ as *const Self::Base) } |
170 | } |
171 | } |
172 | |
173 | impl<Native, Base: NativeRefCounted> NativeRefCounted for Native |
174 | where |
175 | Native: NativeRefCountedBase<Base = Base>, |
176 | { |
177 | fn _ref(&self) { |
178 | self.ref_counted_base()._ref(); |
179 | } |
180 | |
181 | fn _unref(&self) { |
182 | self.ref_counted_base()._unref(); |
183 | } |
184 | |
185 | fn unique(&self) -> bool { |
186 | self.ref_counted_base().unique() |
187 | } |
188 | |
189 | fn _ref_cnt(&self) -> usize { |
190 | self.ref_counted_base()._ref_cnt() |
191 | } |
192 | } |
193 | |
194 | /// Trait that enables access to a native representation of a wrapper type. |
195 | pub trait NativeAccess { |
196 | type Native; |
197 | /// Provides shared access to the native type of the wrapper. |
198 | fn native(&self) -> &Self::Native; |
199 | |
200 | /// Provides exclusive access to the native type of the wrapper. |
201 | fn native_mut(&mut self) -> &mut Self::Native; |
202 | |
203 | // Returns a ptr to the native mutable value. |
204 | unsafe fn native_mut_force(&self) -> *mut Self::Native { |
205 | self.native() as *const Self::Native as *mut Self::Native |
206 | } |
207 | } |
208 | |
209 | /// Implements Drop for native types we can not implement Drop for. |
210 | pub trait NativeDrop { |
211 | fn drop(&mut self); |
212 | } |
213 | |
214 | /// Clone for bindings types we can not implement Clone for. |
215 | pub trait NativeClone { |
216 | fn clone(&self) -> Self; |
217 | } |
218 | |
219 | /// Even though some types may have value semantics, equality |
220 | /// comparison may need to be customized. |
221 | pub trait NativePartialEq { |
222 | fn eq(&self, rhs: &Self) -> bool; |
223 | } |
224 | |
225 | /// Implements Hash for the native type so that the wrapper type |
226 | /// can derive it from. |
227 | pub trait NativeHash { |
228 | fn hash<H: Hasher>(&self, state: &mut H); |
229 | } |
230 | |
231 | /// Wraps a native type that can be represented in Rust memory. |
232 | /// |
233 | /// This type requires an implementation of the `NativeDrop` trait. |
234 | #[repr (transparent)] |
235 | pub struct Handle<N: NativeDrop>( |
236 | N, |
237 | // `*const` is needed to prevent automatic Send and Sync derivation, which happens when the |
238 | // underlying type generated by bindgen is Send and Sync. |
239 | PhantomData<*const ()>, |
240 | ); |
241 | |
242 | impl<N: NativeDrop> AsRef<Handle<N>> for Handle<N> { |
243 | fn as_ref(&self) -> &Self { |
244 | self |
245 | } |
246 | } |
247 | |
248 | impl<N: NativeDrop> Handle<N> { |
249 | /// Wrap a native instance into a handle. |
250 | #[must_use ] |
251 | pub(crate) fn from_native_c(n: N) -> Self { |
252 | Handle(n, PhantomData) |
253 | } |
254 | |
255 | /// Create a reference to the Rust wrapper from a reference to the native type. |
256 | #[must_use ] |
257 | pub(crate) fn from_native_ref(n: &N) -> &Self { |
258 | unsafe { transmute_ref(n) } |
259 | } |
260 | |
261 | /// Create a mutable reference to the Rust wrapper from a reference to the native type. |
262 | #[must_use ] |
263 | pub(crate) fn from_native_ref_mut(n: &mut N) -> &mut Self { |
264 | unsafe { transmute_ref_mut(n) } |
265 | } |
266 | |
267 | /// Converts a pointer to a native value into a pointer to the Rust value. |
268 | #[must_use ] |
269 | pub(crate) fn from_native_ptr(np: *const N) -> *const Self { |
270 | np as _ |
271 | } |
272 | |
273 | /// Converts a pointer to a mutable native value into a pointer to the mutable Rust value. |
274 | #[allow (unused)] |
275 | #[must_use ] |
276 | pub(crate) fn from_native_ptr_mut(np: *mut N) -> *mut Self { |
277 | np as _ |
278 | } |
279 | |
280 | /// Constructs a C++ object in place by calling a |
281 | /// function that expects a pointer that points to |
282 | /// uninitialized memory of the native type. |
283 | #[must_use ] |
284 | pub(crate) fn construct(construct: impl FnOnce(*mut N)) -> Self { |
285 | Self::try_construct(|i| { |
286 | construct(i); |
287 | true |
288 | }) |
289 | .unwrap() |
290 | } |
291 | |
292 | #[must_use ] |
293 | pub(crate) fn try_construct(construct: impl FnOnce(*mut N) -> bool) -> Option<Self> { |
294 | self::try_construct(construct).map(Self::from_native_c) |
295 | } |
296 | |
297 | /// Replaces the native instance with the one from this Handle, and returns the replaced one |
298 | /// wrapped in a Rust Handle without dropping either one. |
299 | #[must_use ] |
300 | pub(crate) fn replace_native(mut self, native: &mut N) -> Self { |
301 | mem::swap(&mut self.0, native); |
302 | self |
303 | } |
304 | |
305 | /// Consumes the wrapper and returns the native type. |
306 | #[must_use ] |
307 | pub(crate) fn into_native(mut self) -> N { |
308 | let r = mem::replace(&mut self.0, unsafe { mem::zeroed() }); |
309 | mem::forget(self); |
310 | r |
311 | } |
312 | } |
313 | |
314 | pub(crate) trait ReplaceWith<Other> { |
315 | fn replace_with(&mut self, other: Other) -> Other; |
316 | } |
317 | |
318 | impl<N: NativeDrop> ReplaceWith<Handle<N>> for N { |
319 | fn replace_with(&mut self, other: Handle<N>) -> Handle<N> { |
320 | other.replace_native(self) |
321 | } |
322 | } |
323 | |
324 | /// Constructs a C++ object in place by calling a lambda that is meant to initialize |
325 | /// the pointer to the Rust memory provided as a pointer. |
326 | #[must_use ] |
327 | pub(crate) fn construct<N>(construct: impl FnOnce(*mut N)) -> N { |
328 | try_constructOption(|i: *mut N| { |
329 | construct(i); |
330 | true |
331 | }) |
332 | .unwrap() |
333 | } |
334 | |
335 | #[must_use ] |
336 | pub(crate) fn try_construct<N>(construct: impl FnOnce(*mut N) -> bool) -> Option<N> { |
337 | let mut instance: MaybeUninit = MaybeUninit::uninit(); |
338 | construct(instance.as_mut_ptr()).if_true_then_some(|| unsafe { instance.assume_init() }) |
339 | } |
340 | |
341 | impl<N: NativeDrop> Drop for Handle<N> { |
342 | fn drop(&mut self) { |
343 | self.0.drop() |
344 | } |
345 | } |
346 | |
347 | impl<N: NativeDrop> NativeAccess for Handle<N> { |
348 | type Native = N; |
349 | |
350 | fn native(&self) -> &N { |
351 | &self.0 |
352 | } |
353 | |
354 | fn native_mut(&mut self) -> &mut N { |
355 | &mut self.0 |
356 | } |
357 | } |
358 | |
359 | impl<N: NativeDrop + NativeClone> Clone for Handle<N> { |
360 | fn clone(&self) -> Self { |
361 | Self::from_native_c(self.0.clone()) |
362 | } |
363 | } |
364 | |
365 | impl<N: NativeDrop + NativePartialEq> PartialEq for Handle<N> { |
366 | fn eq(&self, rhs: &Self) -> bool { |
367 | self.native().eq(rhs.native()) |
368 | } |
369 | } |
370 | |
371 | impl<N: NativeDrop + NativeHash> Hash for Handle<N> { |
372 | fn hash<H: Hasher>(&self, state: &mut H) { |
373 | self.native().hash(state); |
374 | } |
375 | } |
376 | |
377 | pub(crate) trait NativeSliceAccess<N: NativeDrop> { |
378 | fn native(&self) -> &[N]; |
379 | fn native_mut(&mut self) -> &mut [N]; |
380 | } |
381 | |
382 | impl<N: NativeDrop> NativeSliceAccess<N> for [Handle<N>] { |
383 | fn native(&self) -> &[N] { |
384 | let ptr: *const N = self |
385 | .first() |
386 | .map(|f| f.native() as *const N) |
387 | .unwrap_or(default:ptr::null()); |
388 | unsafe { slice::from_raw_parts(data:ptr, self.len()) } |
389 | } |
390 | |
391 | fn native_mut(&mut self) -> &mut [N] { |
392 | let ptr: *mut N = self |
393 | .first_mut() |
394 | .map(|f| f.native_mut() as *mut N) |
395 | .unwrap_or(default:ptr::null_mut()); |
396 | unsafe { slice::from_raw_parts_mut(data:ptr, self.len()) } |
397 | } |
398 | } |
399 | |
400 | /// A trait that supports retrieving a pointer from an Option<Handle<Native>>. |
401 | /// Returns a null pointer if the Option is None. |
402 | pub(crate) trait NativePointerOrNull { |
403 | type Native; |
404 | |
405 | fn native_ptr_or_null(&self) -> *const Self::Native; |
406 | unsafe fn native_ptr_or_null_mut_force(&self) -> *mut Self::Native; |
407 | } |
408 | |
409 | pub(crate) trait NativePointerOrNullMut { |
410 | type Native; |
411 | |
412 | fn native_ptr_or_null_mut(&mut self) -> *mut Self::Native; |
413 | } |
414 | |
415 | impl<H, N> NativePointerOrNull for Option<&H> |
416 | where |
417 | H: NativeAccess<Native = N>, |
418 | { |
419 | type Native = N; |
420 | |
421 | fn native_ptr_or_null(&self) -> *const N { |
422 | match self { |
423 | Some(handle: &&H) => handle.native(), |
424 | None => ptr::null(), |
425 | } |
426 | } |
427 | |
428 | unsafe fn native_ptr_or_null_mut_force(&self) -> *mut N { |
429 | match self { |
430 | Some(handle: &&H) => handle.native_mut_force(), |
431 | None => ptr::null_mut(), |
432 | } |
433 | } |
434 | } |
435 | |
436 | impl<H, N> NativePointerOrNullMut for Option<&mut H> |
437 | where |
438 | H: NativeAccess<Native = N>, |
439 | { |
440 | type Native = N; |
441 | |
442 | fn native_ptr_or_null_mut(&mut self) -> *mut N { |
443 | match self { |
444 | Some(handle: &mut &mut H) => handle.native_mut(), |
445 | None => ptr::null_mut(), |
446 | } |
447 | } |
448 | } |
449 | |
450 | pub(crate) trait NativePointerOrNullMut2<N> { |
451 | fn native_ptr_or_null_mut(&mut self) -> *mut N; |
452 | } |
453 | |
454 | pub(crate) trait NativePointerOrNull2<N> { |
455 | fn native_ptr_or_null(&self) -> *const N; |
456 | } |
457 | |
458 | impl<H, N> NativePointerOrNull2<N> for Option<&H> |
459 | where |
460 | H: NativeTransmutable<N>, |
461 | { |
462 | fn native_ptr_or_null(&self) -> *const N { |
463 | match self { |
464 | Some(handle: &&H) => handle.native(), |
465 | None => ptr::null(), |
466 | } |
467 | } |
468 | } |
469 | |
470 | impl<H, N> NativePointerOrNullMut2<N> for Option<&mut H> |
471 | where |
472 | H: NativeTransmutable<N>, |
473 | { |
474 | fn native_ptr_or_null_mut(&mut self) -> *mut N { |
475 | match self { |
476 | Some(handle: &mut &mut H) => handle.native_mut(), |
477 | None => ptr::null_mut(), |
478 | } |
479 | } |
480 | } |
481 | |
482 | /// A wrapper type that represents a native type with a pointer to |
483 | /// the native object. |
484 | #[repr (transparent)] |
485 | pub struct RefHandle<N: NativeDrop>(ptr::NonNull<N>); |
486 | |
487 | impl<N: NativeDrop> Drop for RefHandle<N> { |
488 | fn drop(&mut self) { |
489 | self.native_mut().drop() |
490 | } |
491 | } |
492 | |
493 | impl<N: NativeDrop + NativePartialEq> PartialEq for RefHandle<N> { |
494 | fn eq(&self, rhs: &Self) -> bool { |
495 | self.native().eq(rhs.native()) |
496 | } |
497 | } |
498 | |
499 | impl<N: NativeDrop> NativeAccess for RefHandle<N> { |
500 | type Native = N; |
501 | |
502 | fn native(&self) -> &N { |
503 | unsafe { self.0.as_ref() } |
504 | } |
505 | fn native_mut(&mut self) -> &mut N { |
506 | unsafe { self.0.as_mut() } |
507 | } |
508 | } |
509 | |
510 | impl<N: NativeDrop> RefHandle<N> { |
511 | /// Creates a RefHandle from a native pointer. |
512 | /// |
513 | /// From this time on, the handle owns the object that the pointer points |
514 | /// to and will call its NativeDrop implementation if it goes out of scope. |
515 | pub(crate) fn from_ptr(ptr: *mut N) -> Option<Self> { |
516 | ptr::NonNull::new(ptr).map(Self) |
517 | } |
518 | |
519 | pub(crate) fn into_ptr(self) -> *mut N { |
520 | let p: *mut N = self.0.as_ptr(); |
521 | mem::forget(self); |
522 | p |
523 | } |
524 | } |
525 | |
526 | /// A wrapper type represented by a reference counted pointer |
527 | /// to the native type. |
528 | #[repr (transparent)] |
529 | pub struct RCHandle<Native: NativeRefCounted>(ptr::NonNull<Native>); |
530 | |
531 | /// A reference counted handle is cheap to clone, so we do support a conversion |
532 | /// from a reference to a ref counter to an owned handle. |
533 | impl<N: NativeRefCounted> From<&RCHandle<N>> for RCHandle<N> { |
534 | fn from(rch: &RCHandle<N>) -> Self { |
535 | rch.clone() |
536 | } |
537 | } |
538 | |
539 | impl<N: NativeRefCounted> AsRef<RCHandle<N>> for RCHandle<N> { |
540 | fn as_ref(&self) -> &Self { |
541 | self |
542 | } |
543 | } |
544 | |
545 | impl<N: NativeRefCounted> RCHandle<N> { |
546 | /// Creates an reference counted handle from a native pointer. |
547 | /// |
548 | /// Takes ownership of the object the pointer points to, does not increase the reference count. |
549 | /// |
550 | /// Returns `None` if the pointer is `null`. |
551 | #[inline ] |
552 | pub(crate) fn from_ptr(ptr: *mut N) -> Option<Self> { |
553 | ptr::NonNull::new(ptr).map(Self) |
554 | } |
555 | |
556 | /// Creates an reference counted handle from a pointer. |
557 | /// |
558 | /// Returns `None` if the pointer is `null`. |
559 | /// |
560 | /// Shares ownership with the object referenced to by the pointer, therefore increases the |
561 | /// reference count. |
562 | #[inline ] |
563 | pub(crate) fn from_unshared_ptr(ptr: *mut N) -> Option<Self> { |
564 | ptr::NonNull::new(ptr).map(|ptr| { |
565 | unsafe { ptr.as_ref()._ref() }; |
566 | Self(ptr) |
567 | }) |
568 | } |
569 | |
570 | /// Create a reference to the Rust wrapper from a reference to a pointer that points |
571 | /// to the native type. |
572 | pub(crate) fn from_unshared_ptr_ref(n: &*mut N) -> &Option<Self> { |
573 | unsafe { transmute_ref(n) } |
574 | } |
575 | |
576 | /// Returns the pointer to the handle. |
577 | #[allow (unused)] |
578 | pub(crate) fn as_ptr(&self) -> &NonNull<N> { |
579 | &self.0 |
580 | } |
581 | } |
582 | |
583 | #[cfg (test)] |
584 | mod rc_handle_tests { |
585 | use std::ptr; |
586 | |
587 | use skia_bindings::{SkFontMgr, SkTypeface}; |
588 | |
589 | use crate::{prelude::NativeAccess, FontMgr, Typeface}; |
590 | |
591 | #[test ] |
592 | fn rc_native_ref_null() { |
593 | let f: *mut SkTypeface = ptr::null_mut(); |
594 | let r = Typeface::from_unshared_ptr(f); |
595 | assert!(r.is_none()) |
596 | } |
597 | |
598 | #[test ] |
599 | fn rc_native_ref_non_null() { |
600 | let mut font_mgr = FontMgr::new(); |
601 | let f: *mut SkFontMgr = font_mgr.native_mut(); |
602 | let r = FontMgr::from_unshared_ptr(f); |
603 | assert!(r.is_some()) |
604 | } |
605 | } |
606 | |
607 | impl<N: NativeRefCounted> NativeAccess for RCHandle<N> { |
608 | type Native = N; |
609 | |
610 | /// Returns a reference to the native representation. |
611 | fn native(&self) -> &N { |
612 | unsafe { self.0.as_ref() } |
613 | } |
614 | |
615 | /// Returns a mutable reference to the native representation. |
616 | fn native_mut(&mut self) -> &mut N { |
617 | unsafe { self.0.as_mut() } |
618 | } |
619 | } |
620 | |
621 | impl<N: NativeRefCounted> Clone for RCHandle<N> { |
622 | fn clone(&self) -> Self { |
623 | // Support shared mutability when a ref-counted handle is cloned. |
624 | let ptr: NonNull = self.0; |
625 | unsafe { ptr.as_ref()._ref() }; |
626 | Self(ptr) |
627 | } |
628 | } |
629 | |
630 | impl<N: NativeRefCounted> Drop for RCHandle<N> { |
631 | #[inline ] |
632 | fn drop(&mut self) { |
633 | unsafe { self.0.as_ref()._unref() }; |
634 | } |
635 | } |
636 | |
637 | impl<N: NativeRefCounted + NativePartialEq> PartialEq for RCHandle<N> { |
638 | fn eq(&self, rhs: &Self) -> bool { |
639 | self.native().eq(rhs.native()) |
640 | } |
641 | } |
642 | |
643 | /// A trait that consumes self and converts it to a ptr to the native type. |
644 | pub(crate) trait IntoPtr<N> { |
645 | fn into_ptr(self) -> *mut N; |
646 | } |
647 | |
648 | impl<N: NativeRefCounted> IntoPtr<N> for RCHandle<N> { |
649 | fn into_ptr(self) -> *mut N { |
650 | let ptr: *mut N = self.0.as_ptr(); |
651 | mem::forget(self); |
652 | ptr |
653 | } |
654 | } |
655 | |
656 | /// A trait that consumes self and converts it to a ptr to the native type or null. |
657 | pub(crate) trait IntoPtrOrNull { |
658 | type Native; |
659 | fn into_ptr_or_null(self) -> *mut Self::Native; |
660 | } |
661 | |
662 | impl<N: NativeRefCounted> IntoPtrOrNull for Option<RCHandle<N>> { |
663 | type Native = N; |
664 | fn into_ptr_or_null(self) -> *mut N { |
665 | self.map(|rc| rc.into_ptr()).unwrap_or(default:ptr::null_mut()) |
666 | } |
667 | } |
668 | |
669 | /// Tag the type to automatically implement get() functions for |
670 | /// all Index implementations. |
671 | pub trait IndexGet {} |
672 | |
673 | /// Tag the type to automatically implement get() and set() functions |
674 | /// for all Index & IndexMut implementation for that type. |
675 | pub trait IndexSet {} |
676 | |
677 | pub trait IndexGetter<I, O: Copy> { |
678 | fn get(&self, index: I) -> O; |
679 | } |
680 | |
681 | impl<T, I, O: Copy> IndexGetter<I, O> for T |
682 | where |
683 | T: Index<I, Output = O> + IndexGet, |
684 | { |
685 | fn get(&self, index: I) -> O { |
686 | self[index] |
687 | } |
688 | } |
689 | |
690 | pub trait IndexSetter<I, O: Copy> { |
691 | fn set(&mut self, index: I, value: O) -> &mut Self; |
692 | } |
693 | |
694 | impl<T, I, O: Copy> IndexSetter<I, O> for T |
695 | where |
696 | T: IndexMut<I, Output = O> + IndexSet, |
697 | { |
698 | fn set(&mut self, index: I, value: O) -> &mut Self { |
699 | self[index] = value; |
700 | self |
701 | } |
702 | } |
703 | |
704 | /// Trait to mark a native type that can be treated a Rust type _inplace_ with the same size and |
705 | /// field layout. |
706 | pub trait NativeTransmutable<NT: Sized>: Sized |
707 | where |
708 | Self: Sized, |
709 | { |
710 | /// Provides access to the native value through a |
711 | /// transmuted reference to the Rust value. |
712 | fn native(&self) -> &NT { |
713 | unsafe { transmute_ref(self) } |
714 | } |
715 | |
716 | /// Provides mutable access to the native value through a transmuted reference to the Rust |
717 | /// value. |
718 | fn native_mut(&mut self) -> &mut NT { |
719 | unsafe { transmute_ref_mut(self) } |
720 | } |
721 | |
722 | /// Copies the native value to an equivalent Rust value. |
723 | /// |
724 | /// The `_c` suffix is to remind callers that values that requires C++ ABI features can't be |
725 | /// used here. |
726 | fn from_native_c(nt: NT) -> Self { |
727 | let r = unsafe { mem::transmute_copy::<NT, Self>(&nt) }; |
728 | // don't drop, the Rust type takes over. |
729 | mem::forget(nt); |
730 | r |
731 | } |
732 | |
733 | /// Copies the rust type to an equivalent instance of the native type. |
734 | fn into_native(self) -> NT { |
735 | let r = unsafe { mem::transmute_copy::<Self, NT>(&self) }; |
736 | // don't drop, the native type takes over. |
737 | mem::forget(self); |
738 | r |
739 | } |
740 | |
741 | /// Provides access to the Rust value through a |
742 | /// transmuted reference to the native value. |
743 | fn from_native_ref(nt: &NT) -> &Self { |
744 | unsafe { transmute_ref(nt) } |
745 | } |
746 | |
747 | /// Provides access to the Rust value through a |
748 | /// transmuted reference to the native mutable value. |
749 | fn from_native_ref_mut(nt: &mut NT) -> &mut Self { |
750 | unsafe { transmute_ref_mut(nt) } |
751 | } |
752 | |
753 | /// Converts a pointer to a native value into a pointer to the Rust value. |
754 | fn from_native_ptr(np: *const NT) -> *const Self { |
755 | np as _ |
756 | } |
757 | |
758 | /// Converts a pointer to a mutable native value into a pointer to the mutable Rust value. |
759 | fn from_native_ptr_mut(np: *mut NT) -> *mut Self { |
760 | np as _ |
761 | } |
762 | |
763 | /// Runs a test that proves that the native and the Rust type are of the same size. |
764 | fn test_layout() { |
765 | assert_eq!(mem::size_of::<Self>(), mem::size_of::<NT>()); |
766 | } |
767 | |
768 | fn construct(construct: impl FnOnce(*mut NT)) -> Self { |
769 | Self::try_construct(|i| { |
770 | construct(i); |
771 | true |
772 | }) |
773 | .unwrap() |
774 | } |
775 | |
776 | fn try_construct(construct: impl FnOnce(*mut NT) -> bool) -> Option<Self> { |
777 | self::try_construct(construct).map(Self::from_native_c) |
778 | } |
779 | } |
780 | |
781 | pub(crate) trait NativeTransmutableSliceAccess<NT: Sized> { |
782 | fn native(&self) -> &[NT]; |
783 | fn native_mut(&mut self) -> &mut [NT]; |
784 | } |
785 | |
786 | impl<NT, ElementT> NativeTransmutableSliceAccess<NT> for [ElementT] |
787 | where |
788 | ElementT: NativeTransmutable<NT>, |
789 | { |
790 | fn native(&self) -> &[NT] { |
791 | unsafe { &*(self as *const [ElementT] as *const [NT]) } |
792 | } |
793 | |
794 | fn native_mut(&mut self) -> &mut [NT] { |
795 | unsafe { &mut *(self as *mut [ElementT] as *mut [NT]) } |
796 | } |
797 | } |
798 | |
799 | impl<NT, RustT> NativeTransmutable<Option<NT>> for Option<RustT> where RustT: NativeTransmutable<NT> {} |
800 | |
801 | impl<NT, RustT> NativeTransmutable<Option<&[NT]>> for Option<&[RustT]> where |
802 | RustT: NativeTransmutable<NT> |
803 | { |
804 | } |
805 | |
806 | pub(crate) trait NativeTransmutableOptionSliceAccessMut<NT: Sized> { |
807 | fn native_mut(&mut self) -> &mut Option<&mut [NT]>; |
808 | } |
809 | |
810 | impl<NT, RustT> NativeTransmutableOptionSliceAccessMut<NT> for Option<&mut [RustT]> |
811 | where |
812 | RustT: NativeTransmutable<NT>, |
813 | { |
814 | fn native_mut(&mut self) -> &mut Option<&mut [NT]> { |
815 | unsafe { transmute_ref_mut(self) } |
816 | } |
817 | } |
818 | |
819 | // |
820 | // Convenience functions to access Option<&[]> as optional ptr (opt_ptr) |
821 | // that may be null. |
822 | // |
823 | |
824 | pub(crate) trait AsPointerOrNull<PointerT> { |
825 | fn as_ptr_or_null(&self) -> *const PointerT; |
826 | } |
827 | |
828 | pub(crate) trait AsPointerOrNullMut<PointerT>: AsPointerOrNull<PointerT> { |
829 | fn as_ptr_or_null_mut(&mut self) -> *mut PointerT; |
830 | } |
831 | |
832 | impl<E> AsPointerOrNull<E> for Option<E> { |
833 | fn as_ptr_or_null(&self) -> *const E { |
834 | match self { |
835 | Some(e: &E) => e, |
836 | None => ptr::null(), |
837 | } |
838 | } |
839 | } |
840 | |
841 | impl<E> AsPointerOrNullMut<E> for Option<E> { |
842 | fn as_ptr_or_null_mut(&mut self) -> *mut E { |
843 | match self { |
844 | Some(e: &mut E) => e, |
845 | None => ptr::null_mut(), |
846 | } |
847 | } |
848 | } |
849 | |
850 | impl<E> AsPointerOrNull<E> for Option<&[E]> { |
851 | fn as_ptr_or_null(&self) -> *const E { |
852 | match self { |
853 | Some(slice: &&[E]) => slice.as_ptr(), |
854 | None => ptr::null(), |
855 | } |
856 | } |
857 | } |
858 | |
859 | impl<E> AsPointerOrNull<E> for Option<&mut [E]> { |
860 | fn as_ptr_or_null(&self) -> *const E { |
861 | match self { |
862 | Some(slice: &&mut [E]) => slice.as_ptr(), |
863 | None => ptr::null(), |
864 | } |
865 | } |
866 | } |
867 | |
868 | impl<E> AsPointerOrNullMut<E> for Option<&mut [E]> { |
869 | fn as_ptr_or_null_mut(&mut self) -> *mut E { |
870 | match self { |
871 | Some(slice: &mut &mut [E]) => slice.as_mut_ptr(), |
872 | None => ptr::null_mut(), |
873 | } |
874 | } |
875 | } |
876 | |
877 | impl<E> AsPointerOrNull<E> for Option<&Vec<E>> { |
878 | fn as_ptr_or_null(&self) -> *const E { |
879 | match self { |
880 | Some(v: &&Vec) => v.as_ptr(), |
881 | None => ptr::null(), |
882 | } |
883 | } |
884 | } |
885 | |
886 | impl<E> AsPointerOrNull<E> for Option<Vec<E>> { |
887 | fn as_ptr_or_null(&self) -> *const E { |
888 | match self { |
889 | Some(v: &Vec) => v.as_ptr(), |
890 | None => ptr::null(), |
891 | } |
892 | } |
893 | } |
894 | |
895 | impl<E> AsPointerOrNullMut<E> for Option<Vec<E>> { |
896 | fn as_ptr_or_null_mut(&mut self) -> *mut E { |
897 | match self { |
898 | Some(v: &mut Vec) => v.as_mut_ptr(), |
899 | None => ptr::null_mut(), |
900 | } |
901 | } |
902 | } |
903 | |
904 | // impl Trait + 'a or '_ is almost always wrong: |
905 | // <https://www.youtube.com/watch?v=CWiz_RtA1Hw> |
906 | pub trait Captures<U> {} |
907 | |
908 | impl<T: ?Sized, U> Captures<U> for T {} |
909 | |
910 | // Wraps a handle so that the Rust's borrow checker assumes it represents |
911 | // something that borrows something else. |
912 | #[repr (transparent)] |
913 | pub struct Borrows<'a, H>(H, PhantomData<&'a ()>); |
914 | |
915 | impl<'a, H> Deref for Borrows<'a, H> { |
916 | type Target = H; |
917 | fn deref(&self) -> &Self::Target { |
918 | &self.0 |
919 | } |
920 | } |
921 | |
922 | // TODO: this is most likely unsafe because someone could replace the |
923 | // value the reference is pointing to. |
924 | impl<'a, H> DerefMut for Borrows<'a, H> { |
925 | fn deref_mut(&mut self) -> &mut Self::Target { |
926 | &mut self.0 |
927 | } |
928 | } |
929 | |
930 | impl<'a, H> Borrows<'a, H> { |
931 | /// Notify that the borrowed dependency is not referred to anymore and return the handle. |
932 | /// # Safety |
933 | /// The borrowed dependency must be removed before calling `release()`. |
934 | pub unsafe fn release(self) -> H { |
935 | self.0 |
936 | } |
937 | } |
938 | |
939 | pub(crate) trait BorrowsFrom: Sized { |
940 | fn borrows<D: ?Sized>(self, _dep: &D) -> Borrows<Self>; |
941 | } |
942 | |
943 | impl<T: Sized> BorrowsFrom for T { |
944 | fn borrows<D: ?Sized>(self, _dep: &D) -> Borrows<Self> { |
945 | Borrows(self, PhantomData) |
946 | } |
947 | } |
948 | |
949 | /// Declares a base class for a native type. |
950 | pub trait NativeBase<Base> { |
951 | fn base(&self) -> &Base { |
952 | unsafe { &*(self as *const Self as *const Base) } |
953 | } |
954 | |
955 | fn base_mut(&mut self) -> &mut Base { |
956 | unsafe { &mut *(self as *mut Self as *mut Base) } |
957 | } |
958 | } |
959 | |
960 | pub struct Sendable<H: ConditionallySend>(H); |
961 | unsafe impl<H: ConditionallySend> Send for Sendable<H> {} |
962 | |
963 | impl<H: ConditionallySend> Sendable<H> { |
964 | pub fn unwrap(self) -> H { |
965 | self.0 |
966 | } |
967 | } |
968 | |
969 | pub trait ConditionallySend: Sized { |
970 | /// Returns `true` if the handle can be sent to another thread. |
971 | fn can_send(&self) -> bool; |
972 | /// Wrap the handle in a type that can be sent to another thread and unwrapped there. |
973 | /// |
974 | /// Guaranteed to succeed of can_send() returns `true`. |
975 | fn wrap_send(self) -> Result<Sendable<Self>, Self>; |
976 | } |
977 | |
978 | /// `RCHandle<H>` is conditionally Send and can be sent to |
979 | /// another thread when its reference count is 1. |
980 | impl<H: NativeRefCountedBase> ConditionallySend for RCHandle<H> { |
981 | fn can_send(&self) -> bool { |
982 | self.native().unique() |
983 | } |
984 | |
985 | fn wrap_send(self) -> Result<Sendable<Self>, Self> { |
986 | if self.can_send() { |
987 | Ok(Sendable(self)) |
988 | } else { |
989 | Err(self) |
990 | } |
991 | } |
992 | } |
993 | |
994 | /// Functions that are (supposedly) _safer_ variants of the ones Rust provides. |
995 | pub(crate) mod safer { |
996 | use core::slice; |
997 | use std::ptr; |
998 | |
999 | /// Invokes [slice::from_raw_parts] with the `ptr` only when `len` != 0, otherwise passes |
1000 | /// `ptr::NonNull::dangling()` as recommended. |
1001 | /// |
1002 | /// Panics if `len` != 0 and `ptr` is `null`. |
1003 | pub unsafe fn from_raw_parts<'a, T>(ptr: *const T, len: usize) -> &'a [T] { |
1004 | let ptr = if len == 0 { |
1005 | ptr::NonNull::dangling().as_ptr() |
1006 | } else { |
1007 | assert!(!ptr.is_null()); |
1008 | ptr |
1009 | }; |
1010 | slice::from_raw_parts(ptr, len) |
1011 | } |
1012 | |
1013 | /// Invokes [slice::from_raw_parts_mut] with the `ptr` only if `len` != 0, otherwise passes |
1014 | /// `ptr::NonNull::dangling()` as recommended. |
1015 | /// |
1016 | /// Panics if `len` != 0 and `ptr` is `null`. |
1017 | pub unsafe fn from_raw_parts_mut<'a, T>(ptr: *mut T, len: usize) -> &'a mut [T] { |
1018 | let ptr = if len == 0 { |
1019 | ptr::NonNull::dangling().as_ptr() as *mut _ |
1020 | } else { |
1021 | assert!(!ptr.is_null()); |
1022 | ptr |
1023 | }; |
1024 | slice::from_raw_parts_mut(ptr, len) |
1025 | } |
1026 | } |
1027 | |