1#![allow(dead_code)]
2use std::{
3 fmt::Debug,
4 hash::{Hash, Hasher},
5 marker::PhantomData,
6 mem::{self, MaybeUninit},
7 ops::{Deref, DerefMut, Index, IndexMut},
8 ptr::{self, NonNull},
9 slice,
10};
11
12use skia_bindings::{
13 sk_sp, C_SkRefCntBase_ref, C_SkRefCntBase_unique, C_SkRefCntBase_unref, SkRefCnt, SkRefCntBase,
14};
15
16pub(crate) unsafe fn transmute_ref<FromT, ToT>(from: &FromT) -> &ToT {
18 debug_assert_eq!(mem::size_of::<FromT>(), mem::size_of::<ToT>());
20 debug_assert_eq!(mem::align_of::<FromT>(), mem::align_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 debug_assert_eq!(mem::size_of::<FromT>(), mem::size_of::<ToT>());
27 debug_assert_eq!(mem::align_of::<FromT>(), mem::align_of::<ToT>());
28 &mut *(from as *mut FromT as *mut ToT)
29}
30
31pub(crate) trait IntoOption {
32 type Target;
33 fn into_option(self) -> Option<Self::Target>;
34}
35
36impl<T> IntoOption for *const T {
37 type Target = *const T;
38
39 fn into_option(self) -> Option<Self::Target> {
40 if !self.is_null() {
41 Some(self)
42 } else {
43 None
44 }
45 }
46}
47
48impl<T> IntoOption for *mut T {
49 type Target = ptr::NonNull<T>;
50
51 fn into_option(self) -> Option<Self::Target> {
52 ptr::NonNull::new(self)
53 }
54}
55
56impl IntoOption for bool {
57 type Target = ();
58
59 fn into_option(self) -> Option<Self::Target> {
60 if self {
61 Some(())
62 } else {
63 None
64 }
65 }
66}
67
68pub(crate) trait IfBoolSome {
69 fn if_true_some<V>(self, v: V) -> Option<V>;
70 fn if_false_some<V>(self, v: V) -> Option<V>;
71 fn if_true_then_some<V>(self, f: impl FnOnce() -> V) -> Option<V>;
72 fn if_false_then_some<V>(self, f: impl FnOnce() -> V) -> Option<V>;
73}
74
75impl IfBoolSome for bool {
76 fn if_true_some<V>(self, v: V) -> Option<V> {
77 self.into_option().and(Some(v))
78 }
79
80 fn if_false_some<V>(self, v: V) -> Option<V> {
81 (!self).if_true_some(v)
82 }
83
84 fn if_true_then_some<V>(self, f: impl FnOnce() -> V) -> Option<V> {
85 self.into_option().map(|()| f())
86 }
87
88 fn if_false_then_some<V>(self, f: impl FnOnce() -> V) -> Option<V> {
89 (!self).into_option().map(|()| f())
90 }
91}
92
93#[cfg(test)]
94pub(crate) trait RefCount {
95 fn ref_cnt(&self) -> usize;
96}
97
98#[cfg(test)]
99impl RefCount for SkRefCntBase {
100 #[allow(clippy::cast_ptr_alignment)]
104 fn ref_cnt(&self) -> usize {
105 unsafe {
106 let ptr: *const i32 = &self.fRefCnt as *const _ as *const i32;
107 (*ptr).try_into().unwrap()
108 }
109 }
110}
111
112impl NativeBase<SkRefCntBase> for SkRefCnt {}
113
114#[cfg(test)]
115impl RefCount for SkRefCnt {
116 fn ref_cnt(&self) -> usize {
117 self.base().ref_cnt()
118 }
119}
120
121#[cfg(test)]
122impl RefCount for skia_bindings::SkNVRefCnt {
123 #[allow(clippy::cast_ptr_alignment)]
124 fn ref_cnt(&self) -> usize {
125 unsafe {
126 let ptr: *const i32 = &self.fRefCnt as *const _ as *const i32;
127 (*ptr).try_into().unwrap()
128 }
129 }
130}
131
132pub trait NativeRefCounted: Sized {
133 fn _ref(&self);
134 fn _unref(&self);
135 fn unique(&self) -> bool;
136 fn _ref_cnt(&self) -> usize {
137 unimplemented!();
138 }
139}
140
141impl NativeRefCounted for SkRefCntBase {
142 fn _ref(&self) {
143 unsafe { C_SkRefCntBase_ref(self) }
144 }
145
146 fn _unref(&self) {
147 unsafe { C_SkRefCntBase_unref(self) }
148 }
149
150 fn unique(&self) -> bool {
151 unsafe { C_SkRefCntBase_unique(self) }
152 }
153
154 #[allow(clippy::cast_ptr_alignment)]
155 fn _ref_cnt(&self) -> usize {
156 unsafe {
157 let ptr: *const i32 = &self.fRefCnt as *const _ as *const i32;
158 (*ptr).try_into().unwrap()
159 }
160 }
161}
162
163pub trait NativeRefCountedBase {
167 type Base: NativeRefCounted;
168
169 fn ref_counted_base(&self) -> &Self::Base {
174 unsafe { &*(self as *const _ as *const Self::Base) }
175 }
176}
177
178impl<Native, Base: NativeRefCounted> NativeRefCounted for Native
179where
180 Native: NativeRefCountedBase<Base = Base>,
181{
182 fn _ref(&self) {
183 self.ref_counted_base()._ref();
184 }
185
186 fn _unref(&self) {
187 self.ref_counted_base()._unref();
188 }
189
190 fn unique(&self) -> bool {
191 self.ref_counted_base().unique()
192 }
193
194 fn _ref_cnt(&self) -> usize {
195 self.ref_counted_base()._ref_cnt()
196 }
197}
198
199pub trait NativeAccess {
201 type Native;
202 fn native(&self) -> &Self::Native;
204
205 fn native_mut(&mut self) -> &mut Self::Native;
207
208 unsafe fn native_mut_force(&self) -> *mut Self::Native {
210 self.native() as *const Self::Native as *mut Self::Native
211 }
212}
213
214pub trait NativeDrop {
216 fn drop(&mut self);
217}
218
219pub trait NativeClone {
221 fn clone(&self) -> Self;
222}
223
224pub trait NativePartialEq {
227 fn eq(&self, rhs: &Self) -> bool;
228}
229
230pub trait NativeHash {
233 fn hash<H: Hasher>(&self, state: &mut H);
234}
235
236#[repr(transparent)]
240pub struct Handle<N: NativeDrop>(
241 N,
242 PhantomData<*const ()>,
245);
246
247impl<N: NativeDrop> AsRef<Handle<N>> for Handle<N> {
248 fn as_ref(&self) -> &Self {
249 self
250 }
251}
252
253impl<N: NativeDrop> Handle<N> {
254 #[must_use]
256 pub(crate) fn from_native_c(n: N) -> Self {
257 Handle(n, PhantomData)
258 }
259
260 #[must_use]
262 pub(crate) fn from_native_ref(n: &N) -> &Self {
263 unsafe { transmute_ref(n) }
264 }
265
266 #[must_use]
268 pub(crate) fn from_native_ref_mut(n: &mut N) -> &mut Self {
269 unsafe { transmute_ref_mut(n) }
270 }
271
272 #[must_use]
274 pub(crate) fn from_native_ptr(np: *const N) -> *const Self {
275 np as _
276 }
277
278 #[allow(unused)]
280 #[must_use]
281 pub(crate) fn from_native_ptr_mut(np: *mut N) -> *mut Self {
282 np as _
283 }
284
285 #[must_use]
289 pub(crate) fn construct(construct: impl FnOnce(*mut N)) -> Self {
290 Self::try_construct(|i| {
291 construct(i);
292 true
293 })
294 .unwrap()
295 }
296
297 #[must_use]
298 pub(crate) fn try_construct(construct: impl FnOnce(*mut N) -> bool) -> Option<Self> {
299 self::try_construct(construct).map(Self::from_native_c)
300 }
301
302 #[must_use]
305 pub(crate) fn replace_native(mut self, native: &mut N) -> Self {
306 mem::swap(&mut self.0, native);
307 self
308 }
309
310 #[must_use]
312 pub(crate) fn into_native(mut self) -> N {
313 let r = mem::replace(&mut self.0, unsafe { mem::zeroed() });
314 mem::forget(self);
315 r
316 }
317}
318
319pub(crate) trait ReplaceWith<Other> {
320 fn replace_with(&mut self, other: Other) -> Other;
321}
322
323impl<N: NativeDrop> ReplaceWith<Handle<N>> for N {
324 fn replace_with(&mut self, other: Handle<N>) -> Handle<N> {
325 other.replace_native(self)
326 }
327}
328
329#[must_use]
332pub(crate) fn construct<N>(construct: impl FnOnce(*mut N)) -> N {
333 try_construct(|i| {
334 construct(i);
335 true
336 })
337 .unwrap()
338}
339
340#[must_use]
341pub(crate) fn try_construct<N>(construct: impl FnOnce(*mut N) -> bool) -> Option<N> {
342 let mut instance = MaybeUninit::uninit();
343 construct(instance.as_mut_ptr()).if_true_then_some(|| unsafe { instance.assume_init() })
344}
345
346impl<N: NativeDrop> Drop for Handle<N> {
347 fn drop(&mut self) {
348 self.0.drop()
349 }
350}
351
352impl<N: NativeDrop> NativeAccess for Handle<N> {
353 type Native = N;
354
355 fn native(&self) -> &N {
356 &self.0
357 }
358
359 fn native_mut(&mut self) -> &mut N {
360 &mut self.0
361 }
362}
363
364impl<N: NativeDrop + NativeClone> Clone for Handle<N> {
365 fn clone(&self) -> Self {
366 Self::from_native_c(self.0.clone())
367 }
368}
369
370impl<N: NativeDrop + NativePartialEq> PartialEq for Handle<N> {
371 fn eq(&self, rhs: &Self) -> bool {
372 self.native().eq(rhs.native())
373 }
374}
375
376impl<N: NativeDrop + NativeHash> Hash for Handle<N> {
377 fn hash<H: Hasher>(&self, state: &mut H) {
378 self.native().hash(state);
379 }
380}
381
382pub(crate) trait NativeSliceAccess<N: NativeDrop> {
383 fn native(&self) -> &[N];
384 fn native_mut(&mut self) -> &mut [N];
385}
386
387impl<N: NativeDrop> NativeSliceAccess<N> for [Handle<N>] {
388 fn native(&self) -> &[N] {
389 let ptr = self
390 .first()
391 .map(|f| f.native() as *const N)
392 .unwrap_or(ptr::null());
393 unsafe { slice::from_raw_parts(ptr, self.len()) }
394 }
395
396 fn native_mut(&mut self) -> &mut [N] {
397 let ptr = self
398 .first_mut()
399 .map(|f| f.native_mut() as *mut N)
400 .unwrap_or(ptr::null_mut());
401 unsafe { slice::from_raw_parts_mut(ptr, self.len()) }
402 }
403}
404
405pub(crate) trait NativePointerOrNull {
408 type Native;
409
410 fn native_ptr_or_null(&self) -> *const Self::Native;
411 unsafe fn native_ptr_or_null_mut_force(&self) -> *mut Self::Native;
412}
413
414pub(crate) trait NativePointerOrNullMut {
415 type Native;
416
417 fn native_ptr_or_null_mut(&mut self) -> *mut Self::Native;
418}
419
420impl<H, N> NativePointerOrNull for Option<&H>
421where
422 H: NativeAccess<Native = N>,
423{
424 type Native = N;
425
426 fn native_ptr_or_null(&self) -> *const N {
427 match self {
428 Some(handle) => handle.native(),
429 None => ptr::null(),
430 }
431 }
432
433 unsafe fn native_ptr_or_null_mut_force(&self) -> *mut N {
434 match self {
435 Some(handle) => handle.native_mut_force(),
436 None => ptr::null_mut(),
437 }
438 }
439}
440
441impl<H, N> NativePointerOrNullMut for Option<&mut H>
442where
443 H: NativeAccess<Native = N>,
444{
445 type Native = N;
446
447 fn native_ptr_or_null_mut(&mut self) -> *mut N {
448 match self {
449 Some(handle) => handle.native_mut(),
450 None => ptr::null_mut(),
451 }
452 }
453}
454
455pub(crate) trait NativePointerOrNullMut2<N> {
456 fn native_ptr_or_null_mut(&mut self) -> *mut N;
457}
458
459pub(crate) trait NativePointerOrNull2<N> {
460 fn native_ptr_or_null(&self) -> *const N;
461}
462
463impl<H, N> NativePointerOrNull2<N> for Option<&H>
464where
465 H: NativeTransmutable<N>,
466{
467 fn native_ptr_or_null(&self) -> *const N {
468 match self {
469 Some(handle) => handle.native(),
470 None => ptr::null(),
471 }
472 }
473}
474
475impl<H, N> NativePointerOrNullMut2<N> for Option<&mut H>
476where
477 H: NativeTransmutable<N>,
478{
479 fn native_ptr_or_null_mut(&mut self) -> *mut N {
480 match self {
481 Some(handle) => handle.native_mut(),
482 None => ptr::null_mut(),
483 }
484 }
485}
486
487#[repr(transparent)]
490pub struct RefHandle<N: NativeDrop>(ptr::NonNull<N>);
491
492impl<N: NativeDrop> Drop for RefHandle<N> {
493 fn drop(&mut self) {
494 self.native_mut().drop()
495 }
496}
497
498impl<N: NativeDrop + NativePartialEq> PartialEq for RefHandle<N> {
499 fn eq(&self, rhs: &Self) -> bool {
500 self.native().eq(rhs.native())
501 }
502}
503
504impl<N: NativeDrop> NativeAccess for RefHandle<N> {
505 type Native = N;
506
507 fn native(&self) -> &N {
508 unsafe { self.0.as_ref() }
509 }
510 fn native_mut(&mut self) -> &mut N {
511 unsafe { self.0.as_mut() }
512 }
513}
514
515impl<N: NativeDrop> RefHandle<N> {
516 pub(crate) fn from_ptr(ptr: *mut N) -> Option<Self> {
521 ptr::NonNull::new(ptr).map(Self)
522 }
523
524 pub(crate) fn into_ptr(self) -> *mut N {
525 let p = self.0.as_ptr();
526 mem::forget(self);
527 p
528 }
529}
530
531#[repr(transparent)]
534pub struct RCHandle<Native: NativeRefCounted>(ptr::NonNull<Native>);
535
536impl<N: NativeRefCounted> From<&RCHandle<N>> for RCHandle<N> {
539 fn from(rch: &RCHandle<N>) -> Self {
540 rch.clone()
541 }
542}
543
544impl<N: NativeRefCounted> AsRef<RCHandle<N>> for RCHandle<N> {
545 fn as_ref(&self) -> &Self {
546 self
547 }
548}
549
550impl<N: NativeRefCounted> RCHandle<N> {
551 #[inline]
557 pub(crate) fn from_ptr(ptr: *mut N) -> Option<Self> {
558 ptr::NonNull::new(ptr).map(Self)
559 }
560
561 #[inline]
568 pub(crate) fn from_unshared_ptr(ptr: *mut N) -> Option<Self> {
569 ptr::NonNull::new(ptr).map(|ptr| {
570 unsafe { ptr.as_ref()._ref() };
571 Self(ptr)
572 })
573 }
574
575 pub(crate) fn from_unshared_ptr_ref(n: &*mut N) -> &Option<Self> {
578 unsafe { transmute_ref(n) }
579 }
580
581 pub(crate) fn from_non_null_sp_slice(sp_slice: &[sk_sp<N>]) -> &[Self] {
583 debug_assert!(sp_slice.iter().all(|v| !v.fPtr.is_null()));
584 unsafe { mem::transmute(sp_slice) }
585 }
586
587 #[allow(unused)]
589 pub(crate) fn as_ptr(&self) -> &NonNull<N> {
590 &self.0
591 }
592}
593
594#[cfg(test)]
595mod rc_handle_tests {
596 use std::ptr;
597
598 use skia_bindings::{SkFontMgr, SkTypeface};
599
600 use crate::{prelude::NativeAccess, FontMgr, Typeface};
601
602 #[test]
603 fn rc_native_ref_null() {
604 let f: *mut SkTypeface = ptr::null_mut();
605 let r = Typeface::from_unshared_ptr(f);
606 assert!(r.is_none())
607 }
608
609 #[test]
610 fn rc_native_ref_non_null() {
611 let mut font_mgr = FontMgr::new();
612 let f: *mut SkFontMgr = font_mgr.native_mut();
613 let r = FontMgr::from_unshared_ptr(f);
614 assert!(r.is_some())
615 }
616}
617
618impl<N: NativeRefCounted> NativeAccess for RCHandle<N> {
619 type Native = N;
620
621 fn native(&self) -> &N {
623 unsafe { self.0.as_ref() }
624 }
625
626 fn native_mut(&mut self) -> &mut N {
628 unsafe { self.0.as_mut() }
629 }
630}
631
632impl<N: NativeRefCounted> Clone for RCHandle<N> {
633 fn clone(&self) -> Self {
634 let ptr = self.0;
636 unsafe { ptr.as_ref()._ref() };
637 Self(ptr)
638 }
639}
640
641impl<N: NativeRefCounted> Drop for RCHandle<N> {
642 #[inline]
643 fn drop(&mut self) {
644 unsafe { self.0.as_ref()._unref() };
645 }
646}
647
648impl<N: NativeRefCounted + NativePartialEq> PartialEq for RCHandle<N> {
649 fn eq(&self, rhs: &Self) -> bool {
650 self.native().eq(rhs.native())
651 }
652}
653
654pub(crate) trait IntoPtr<N> {
656 fn into_ptr(self) -> *mut N;
657}
658
659impl<N: NativeRefCounted> IntoPtr<N> for RCHandle<N> {
660 fn into_ptr(self) -> *mut N {
661 let ptr = self.0.as_ptr();
662 mem::forget(self);
663 ptr
664 }
665}
666
667pub(crate) trait IntoPtrOrNull {
669 type Native;
670 fn into_ptr_or_null(self) -> *mut Self::Native;
671}
672
673impl<N: NativeRefCounted> IntoPtrOrNull for Option<RCHandle<N>> {
674 type Native = N;
675 fn into_ptr_or_null(self) -> *mut N {
676 self.map(|rc| rc.into_ptr()).unwrap_or(ptr::null_mut())
677 }
678}
679
680pub trait IndexGet {}
683
684pub trait IndexSet {}
687
688pub trait IndexGetter<I, O: Copy> {
689 #[allow(unused)]
691 fn get(&self, index: I) -> O;
692}
693
694impl<T, I, O: Copy> IndexGetter<I, O> for T
695where
696 T: Index<I, Output = O> + IndexGet,
697{
698 fn get(&self, index: I) -> O {
699 self[index]
700 }
701}
702
703pub trait IndexSetter<I, O: Copy> {
704 fn set(&mut self, index: I, value: O) -> &mut Self;
705}
706
707impl<T, I, O: Copy> IndexSetter<I, O> for T
708where
709 T: IndexMut<I, Output = O> + IndexSet,
710{
711 fn set(&mut self, index: I, value: O) -> &mut Self {
712 self[index] = value;
713 self
714 }
715}
716
717pub trait NativeTransmutable<NT: Sized>: Sized
720where
721 Self: Sized,
722{
723 fn native(&self) -> &NT {
726 unsafe { transmute_ref(self) }
727 }
728
729 fn native_mut(&mut self) -> &mut NT {
732 unsafe { transmute_ref_mut(self) }
733 }
734
735 fn from_native_c(nt: NT) -> Self {
740 let r = unsafe { mem::transmute_copy::<NT, Self>(&nt) };
741 mem::forget(nt);
743 r
744 }
745
746 fn into_native(self) -> NT {
748 let r = unsafe { mem::transmute_copy::<Self, NT>(&self) };
749 mem::forget(self);
751 r
752 }
753
754 fn from_native_ref(nt: &NT) -> &Self {
756 unsafe { transmute_ref(nt) }
757 }
758
759 fn from_native_array_ref<const N: usize>(nt: &[NT; N]) -> &[Self; N] {
762 unsafe { transmute_ref(nt) }
763 }
764
765 fn from_native_ref_mut(nt: &mut NT) -> &mut Self {
768 unsafe { transmute_ref_mut(nt) }
769 }
770
771 fn from_native_ptr(np: *const NT) -> *const Self {
773 np as _
774 }
775
776 fn from_native_ptr_mut(np: *mut NT) -> *mut Self {
778 np as _
779 }
780
781 fn test_layout() {
784 assert_eq!(mem::size_of::<Self>(), mem::size_of::<NT>());
785 assert_eq!(mem::align_of::<Self>(), mem::align_of::<NT>());
786 }
787
788 fn construct(construct: impl FnOnce(*mut NT)) -> Self {
789 Self::try_construct(|i| {
790 construct(i);
791 true
792 })
793 .unwrap()
794 }
795
796 fn try_construct(construct: impl FnOnce(*mut NT) -> bool) -> Option<Self> {
797 self::try_construct(construct).map(Self::from_native_c)
798 }
799}
800
801pub(crate) trait NativeTransmutableSliceAccess<NT: Sized> {
802 fn native(&self) -> &[NT];
803 fn native_mut(&mut self) -> &mut [NT];
804}
805
806impl<NT, ElementT> NativeTransmutableSliceAccess<NT> for [ElementT]
807where
808 ElementT: NativeTransmutable<NT>,
809{
810 fn native(&self) -> &[NT] {
811 unsafe { &*(self as *const [ElementT] as *const [NT]) }
812 }
813
814 fn native_mut(&mut self) -> &mut [NT] {
815 unsafe { &mut *(self as *mut [ElementT] as *mut [NT]) }
816 }
817}
818
819impl<NT, RustT> NativeTransmutable<Option<NT>> for Option<RustT> where RustT: NativeTransmutable<NT> {}
820
821impl<NT, RustT> NativeTransmutable<Option<&[NT]>> for Option<&[RustT]> where
822 RustT: NativeTransmutable<NT>
823{
824}
825
826pub(crate) trait NativeTransmutableOptionSliceAccessMut<NT: Sized> {
827 fn native_mut(&mut self) -> &mut Option<&mut [NT]>;
828}
829
830impl<NT, RustT> NativeTransmutableOptionSliceAccessMut<NT> for Option<&mut [RustT]>
831where
832 RustT: NativeTransmutable<NT>,
833{
834 fn native_mut(&mut self) -> &mut Option<&mut [NT]> {
835 unsafe { transmute_ref_mut(self) }
836 }
837}
838
839pub(crate) trait AsPointerOrNull<PointerT> {
845 fn as_ptr_or_null(&self) -> *const PointerT;
846}
847
848pub(crate) trait AsPointerOrNullMut<PointerT>: AsPointerOrNull<PointerT> {
849 fn as_ptr_or_null_mut(&mut self) -> *mut PointerT;
850}
851
852impl<E> AsPointerOrNull<E> for Option<E> {
853 fn as_ptr_or_null(&self) -> *const E {
854 match self {
855 Some(e) => e,
856 None => ptr::null(),
857 }
858 }
859}
860
861impl<E> AsPointerOrNullMut<E> for Option<E> {
862 fn as_ptr_or_null_mut(&mut self) -> *mut E {
863 match self {
864 Some(e) => e,
865 None => ptr::null_mut(),
866 }
867 }
868}
869
870impl<E> AsPointerOrNull<E> for Option<&[E]> {
871 fn as_ptr_or_null(&self) -> *const E {
872 match self {
873 Some(slice) => slice.as_ptr(),
874 None => ptr::null(),
875 }
876 }
877}
878
879impl<E> AsPointerOrNull<E> for Option<&mut [E]> {
880 fn as_ptr_or_null(&self) -> *const E {
881 match self {
882 Some(slice) => slice.as_ptr(),
883 None => ptr::null(),
884 }
885 }
886}
887
888impl<E> AsPointerOrNullMut<E> for Option<&mut [E]> {
889 fn as_ptr_or_null_mut(&mut self) -> *mut E {
890 match self {
891 Some(slice) => slice.as_mut_ptr(),
892 None => ptr::null_mut(),
893 }
894 }
895}
896
897impl<E> AsPointerOrNull<E> for Option<&Vec<E>> {
898 fn as_ptr_or_null(&self) -> *const E {
899 match self {
900 Some(v) => v.as_ptr(),
901 None => ptr::null(),
902 }
903 }
904}
905
906impl<E> AsPointerOrNull<E> for Option<Vec<E>> {
907 fn as_ptr_or_null(&self) -> *const E {
908 match self {
909 Some(v) => v.as_ptr(),
910 None => ptr::null(),
911 }
912 }
913}
914
915impl<E> AsPointerOrNullMut<E> for Option<Vec<E>> {
916 fn as_ptr_or_null_mut(&mut self) -> *mut E {
917 match self {
918 Some(v) => v.as_mut_ptr(),
919 None => ptr::null_mut(),
920 }
921 }
922}
923
924#[repr(transparent)]
927pub struct Borrows<'a, H>(H, PhantomData<&'a ()>);
928
929impl<H> Deref for Borrows<'_, H> {
930 type Target = H;
931 fn deref(&self) -> &Self::Target {
932 &self.0
933 }
934}
935
936impl<H> DerefMut for Borrows<'_, H> {
939 fn deref_mut(&mut self) -> &mut Self::Target {
940 &mut self.0
941 }
942}
943
944impl<H> Borrows<'_, H> {
945 pub unsafe fn release(self) -> H {
949 self.0
950 }
951}
952
953pub(crate) trait BorrowsFrom: Sized {
954 fn borrows<D: ?Sized>(self, _dep: &D) -> Borrows<Self>;
955}
956
957impl<T: Sized> BorrowsFrom for T {
958 fn borrows<D: ?Sized>(self, _dep: &D) -> Borrows<Self> {
959 Borrows(self, PhantomData)
960 }
961}
962
963impl<H> Borrows<'_, H> {
964 pub(crate) unsafe fn unchecked_new(h: H) -> Self {
965 Self(h, PhantomData)
966 }
967}
968
969pub trait NativeBase<Base> {
971 fn base(&self) -> &Base {
972 unsafe { &*(self as *const Self as *const Base) }
973 }
974
975 fn base_mut(&mut self) -> &mut Base {
976 unsafe { &mut *(self as *mut Self as *mut Base) }
977 }
978}
979
980pub struct Sendable<H: ConditionallySend>(H);
981unsafe impl<H: ConditionallySend> Send for Sendable<H> {}
982
983impl<H: ConditionallySend> Sendable<H> {
984 #[deprecated(note = "Use Sendable::into_inner() instead")]
985 pub fn unwrap(self) -> H {
986 self.0
987 }
988
989 pub fn into_inner(self) -> H {
990 self.0
991 }
992}
993
994impl<H> Debug for Sendable<H>
995where
996 H: Debug + ConditionallySend,
997{
998 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
999 f.debug_tuple("Sendable").field(&self.0).finish()
1000 }
1001}
1002
1003pub trait ConditionallySend: Sized {
1004 fn can_send(&self) -> bool;
1006 fn wrap_send(self) -> Result<Sendable<Self>, Self>;
1010}
1011
1012impl<H: NativeRefCountedBase> ConditionallySend for RCHandle<H> {
1015 fn can_send(&self) -> bool {
1016 self.native().unique()
1017 }
1018
1019 fn wrap_send(self) -> Result<Sendable<Self>, Self> {
1020 if self.can_send() {
1021 Ok(Sendable(self))
1022 } else {
1023 Err(self)
1024 }
1025 }
1026}
1027
1028pub(crate) mod safer {
1030 use core::slice;
1031 use std::ptr;
1032
1033 pub unsafe fn from_raw_parts<'a, T>(ptr: *const T, len: usize) -> &'a [T] {
1038 let ptr = if len == 0 {
1039 ptr::NonNull::dangling().as_ptr()
1040 } else {
1041 assert!(!ptr.is_null());
1042 ptr
1043 };
1044 slice::from_raw_parts(ptr, len)
1045 }
1046
1047 pub unsafe fn from_raw_parts_mut<'a, T>(ptr: *mut T, len: usize) -> &'a mut [T] {
1052 let ptr = if len == 0 {
1053 ptr::NonNull::dangling().as_ptr() as *mut _
1054 } else {
1055 assert!(!ptr.is_null());
1056 ptr
1057 };
1058 slice::from_raw_parts_mut(ptr, len)
1059 }
1060}
1061
1062#[cfg(test)]
1063mod tests {
1064 use skia_bindings::{sk_sp, SkFontMgr};
1065
1066 use crate::RCHandle;
1067
1068 #[test]
1069 fn sp_equals_size_and_alignment_of_rc_handle() {
1070 assert_eq!(
1071 size_of::<sk_sp<SkFontMgr>>(),
1072 size_of::<RCHandle<SkFontMgr>>()
1073 );
1074 assert_eq!(
1075 align_of::<sk_sp<SkFontMgr>>(),
1076 align_of::<RCHandle<SkFontMgr>>()
1077 );
1078 }
1079}