1use skia_bindings::{
2 C_SkRefCntBase_ref, C_SkRefCntBase_unique, C_SkRefCntBase_unref, SkNVRefCnt, SkRefCnt,
3 SkRefCntBase,
4};
5use 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::*.
15pub use std::convert::{TryFrom, TryInto};
16
17/// Convert any reference into any other.
18pub(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
24pub(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
30pub(crate) trait IntoOption {
31 type Target;
32 fn into_option(self) -> Option<Self::Target>;
33}
34
35impl<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
47impl<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
55impl 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
67pub(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
74impl 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
92pub(crate) trait RefCount {
93 fn ref_cnt(&self) -> usize;
94}
95
96impl 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
109impl NativeBase<SkRefCntBase> for SkRefCnt {}
110
111impl RefCount for SkRefCnt {
112 fn ref_cnt(&self) -> usize {
113 self.base().ref_cnt()
114 }
115}
116
117impl 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
127pub 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
136impl 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
161pub 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
173impl<Native, Base: NativeRefCounted> NativeRefCounted for Native
174where
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.
195pub 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.
210pub trait NativeDrop {
211 fn drop(&mut self);
212}
213
214/// Clone for bindings types we can not implement Clone for.
215pub 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.
221pub 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.
227pub 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)]
235pub 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
242impl<N: NativeDrop> AsRef<Handle<N>> for Handle<N> {
243 fn as_ref(&self) -> &Self {
244 self
245 }
246}
247
248impl<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
314pub(crate) trait ReplaceWith<Other> {
315 fn replace_with(&mut self, other: Other) -> Other;
316}
317
318impl<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]
327pub(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]
336pub(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
341impl<N: NativeDrop> Drop for Handle<N> {
342 fn drop(&mut self) {
343 self.0.drop()
344 }
345}
346
347impl<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
359impl<N: NativeDrop + NativeClone> Clone for Handle<N> {
360 fn clone(&self) -> Self {
361 Self::from_native_c(self.0.clone())
362 }
363}
364
365impl<N: NativeDrop + NativePartialEq> PartialEq for Handle<N> {
366 fn eq(&self, rhs: &Self) -> bool {
367 self.native().eq(rhs.native())
368 }
369}
370
371impl<N: NativeDrop + NativeHash> Hash for Handle<N> {
372 fn hash<H: Hasher>(&self, state: &mut H) {
373 self.native().hash(state);
374 }
375}
376
377pub(crate) trait NativeSliceAccess<N: NativeDrop> {
378 fn native(&self) -> &[N];
379 fn native_mut(&mut self) -> &mut [N];
380}
381
382impl<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.
402pub(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
409pub(crate) trait NativePointerOrNullMut {
410 type Native;
411
412 fn native_ptr_or_null_mut(&mut self) -> *mut Self::Native;
413}
414
415impl<H, N> NativePointerOrNull for Option<&H>
416where
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
436impl<H, N> NativePointerOrNullMut for Option<&mut H>
437where
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
450pub(crate) trait NativePointerOrNullMut2<N> {
451 fn native_ptr_or_null_mut(&mut self) -> *mut N;
452}
453
454pub(crate) trait NativePointerOrNull2<N> {
455 fn native_ptr_or_null(&self) -> *const N;
456}
457
458impl<H, N> NativePointerOrNull2<N> for Option<&H>
459where
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
470impl<H, N> NativePointerOrNullMut2<N> for Option<&mut H>
471where
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)]
485pub struct RefHandle<N: NativeDrop>(ptr::NonNull<N>);
486
487impl<N: NativeDrop> Drop for RefHandle<N> {
488 fn drop(&mut self) {
489 self.native_mut().drop()
490 }
491}
492
493impl<N: NativeDrop + NativePartialEq> PartialEq for RefHandle<N> {
494 fn eq(&self, rhs: &Self) -> bool {
495 self.native().eq(rhs.native())
496 }
497}
498
499impl<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
510impl<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)]
529pub 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.
533impl<N: NativeRefCounted> From<&RCHandle<N>> for RCHandle<N> {
534 fn from(rch: &RCHandle<N>) -> Self {
535 rch.clone()
536 }
537}
538
539impl<N: NativeRefCounted> AsRef<RCHandle<N>> for RCHandle<N> {
540 fn as_ref(&self) -> &Self {
541 self
542 }
543}
544
545impl<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)]
584mod 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
607impl<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
621impl<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
630impl<N: NativeRefCounted> Drop for RCHandle<N> {
631 #[inline]
632 fn drop(&mut self) {
633 unsafe { self.0.as_ref()._unref() };
634 }
635}
636
637impl<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.
644pub(crate) trait IntoPtr<N> {
645 fn into_ptr(self) -> *mut N;
646}
647
648impl<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.
657pub(crate) trait IntoPtrOrNull {
658 type Native;
659 fn into_ptr_or_null(self) -> *mut Self::Native;
660}
661
662impl<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.
671pub trait IndexGet {}
672
673/// Tag the type to automatically implement get() and set() functions
674/// for all Index & IndexMut implementation for that type.
675pub trait IndexSet {}
676
677pub trait IndexGetter<I, O: Copy> {
678 fn get(&self, index: I) -> O;
679}
680
681impl<T, I, O: Copy> IndexGetter<I, O> for T
682where
683 T: Index<I, Output = O> + IndexGet,
684{
685 fn get(&self, index: I) -> O {
686 self[index]
687 }
688}
689
690pub trait IndexSetter<I, O: Copy> {
691 fn set(&mut self, index: I, value: O) -> &mut Self;
692}
693
694impl<T, I, O: Copy> IndexSetter<I, O> for T
695where
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.
706pub trait NativeTransmutable<NT: Sized>: Sized
707where
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
781pub(crate) trait NativeTransmutableSliceAccess<NT: Sized> {
782 fn native(&self) -> &[NT];
783 fn native_mut(&mut self) -> &mut [NT];
784}
785
786impl<NT, ElementT> NativeTransmutableSliceAccess<NT> for [ElementT]
787where
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
799impl<NT, RustT> NativeTransmutable<Option<NT>> for Option<RustT> where RustT: NativeTransmutable<NT> {}
800
801impl<NT, RustT> NativeTransmutable<Option<&[NT]>> for Option<&[RustT]> where
802 RustT: NativeTransmutable<NT>
803{
804}
805
806pub(crate) trait NativeTransmutableOptionSliceAccessMut<NT: Sized> {
807 fn native_mut(&mut self) -> &mut Option<&mut [NT]>;
808}
809
810impl<NT, RustT> NativeTransmutableOptionSliceAccessMut<NT> for Option<&mut [RustT]>
811where
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
824pub(crate) trait AsPointerOrNull<PointerT> {
825 fn as_ptr_or_null(&self) -> *const PointerT;
826}
827
828pub(crate) trait AsPointerOrNullMut<PointerT>: AsPointerOrNull<PointerT> {
829 fn as_ptr_or_null_mut(&mut self) -> *mut PointerT;
830}
831
832impl<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
841impl<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
850impl<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
859impl<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
868impl<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
877impl<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
886impl<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
895impl<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>
906pub trait Captures<U> {}
907
908impl<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)]
913pub struct Borrows<'a, H>(H, PhantomData<&'a ()>);
914
915impl<'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.
924impl<'a, H> DerefMut for Borrows<'a, H> {
925 fn deref_mut(&mut self) -> &mut Self::Target {
926 &mut self.0
927 }
928}
929
930impl<'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
939pub(crate) trait BorrowsFrom: Sized {
940 fn borrows<D: ?Sized>(self, _dep: &D) -> Borrows<Self>;
941}
942
943impl<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.
950pub 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
960pub struct Sendable<H: ConditionallySend>(H);
961unsafe impl<H: ConditionallySend> Send for Sendable<H> {}
962
963impl<H: ConditionallySend> Sendable<H> {
964 pub fn unwrap(self) -> H {
965 self.0
966 }
967}
968
969pub 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.
980impl<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.
995pub(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