skia_safe/
prelude.rs

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
16/// Convert any reference into any other.
17pub(crate) unsafe fn transmute_ref<FromT, ToT>(from: &FromT) -> &ToT {
18    // TODO: can we do this statically for all instantiations of transmute_ref?
19    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    // 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    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    // the problem here is that the binding generator represents std::atomic as an u8 (we
101    // are lucky that the C alignment rules make space for an i32), so to get the ref
102    // counter, we need to get the u8 pointer to fRefCnt and interpret it as an i32 pointer.
103    #[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
163/// Implements NativeRefCounted by just providing a reference to the base class
164/// that implements a RefCount.
165/// TODO: use NativeBase
166pub trait NativeRefCountedBase {
167    type Base: NativeRefCounted;
168
169    /// Returns the ref counter base class of the ref counted type.
170    ///
171    /// Default implementation assumes that the base class ptr is the same as the
172    /// ptr to self.
173    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
199/// Trait that enables access to a native representation of a wrapper type.
200pub trait NativeAccess {
201    type Native;
202    /// Provides shared access to the native type of the wrapper.
203    fn native(&self) -> &Self::Native;
204
205    /// Provides exclusive access to the native type of the wrapper.
206    fn native_mut(&mut self) -> &mut Self::Native;
207
208    // Returns a ptr to the native mutable value.
209    unsafe fn native_mut_force(&self) -> *mut Self::Native {
210        self.native() as *const Self::Native as *mut Self::Native
211    }
212}
213
214/// Implements Drop for native types we can not implement Drop for.
215pub trait NativeDrop {
216    fn drop(&mut self);
217}
218
219/// Clone for bindings types we can not implement Clone for.
220pub trait NativeClone {
221    fn clone(&self) -> Self;
222}
223
224/// Even though some types may have value semantics, equality
225/// comparison may need to be customized.
226pub trait NativePartialEq {
227    fn eq(&self, rhs: &Self) -> bool;
228}
229
230/// Implements Hash for the native type so that the wrapper type
231/// can derive it from.
232pub trait NativeHash {
233    fn hash<H: Hasher>(&self, state: &mut H);
234}
235
236/// Wraps a native type that can be represented in Rust memory.
237///
238/// This type requires an implementation of the `NativeDrop` trait.
239#[repr(transparent)]
240pub struct Handle<N: NativeDrop>(
241    N,
242    // `*const` is needed to prevent automatic Send and Sync derivation, which happens when the
243    // underlying type generated by bindgen is Send and Sync.
244    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    /// Wrap a native instance into a handle.
255    #[must_use]
256    pub(crate) fn from_native_c(n: N) -> Self {
257        Handle(n, PhantomData)
258    }
259
260    /// Create a reference to the Rust wrapper from a reference to the native type.
261    #[must_use]
262    pub(crate) fn from_native_ref(n: &N) -> &Self {
263        unsafe { transmute_ref(n) }
264    }
265
266    /// Create a mutable reference to the Rust wrapper from a reference to the native type.
267    #[must_use]
268    pub(crate) fn from_native_ref_mut(n: &mut N) -> &mut Self {
269        unsafe { transmute_ref_mut(n) }
270    }
271
272    /// Converts a pointer to a native value into a pointer to the Rust value.
273    #[must_use]
274    pub(crate) fn from_native_ptr(np: *const N) -> *const Self {
275        np as _
276    }
277
278    /// Converts a pointer to a mutable native value into a pointer to the mutable Rust value.
279    #[allow(unused)]
280    #[must_use]
281    pub(crate) fn from_native_ptr_mut(np: *mut N) -> *mut Self {
282        np as _
283    }
284
285    /// Constructs a C++ object in place by calling a
286    /// function that expects a pointer that points to
287    /// uninitialized memory of the native type.
288    #[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    /// Replaces the native instance with the one from this Handle, and returns the replaced one
303    /// wrapped in a Rust Handle without dropping either one.
304    #[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    /// Consumes the wrapper and returns the native type.
311    #[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/// Constructs a C++ object in place by calling a lambda that is meant to initialize
330/// the pointer to the Rust memory provided as a pointer.
331#[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
405/// A trait that supports retrieving a pointer from an Option<Handle<Native>>.
406/// Returns a null pointer if the Option is None.
407pub(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/// A wrapper type that represents a native type with a pointer to
488/// the native object.
489#[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    /// Creates a RefHandle from a native pointer.
517    ///
518    /// From this time on, the handle owns the object that the pointer points
519    /// to and will call its NativeDrop implementation if it goes out of scope.
520    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/// A wrapper type represented by a reference counted pointer
532/// to the native type.
533#[repr(transparent)]
534pub struct RCHandle<Native: NativeRefCounted>(ptr::NonNull<Native>);
535
536/// A reference counted handle is cheap to clone, so we do support a conversion
537/// from a reference to a ref counter to an owned handle.
538impl<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    /// Creates an reference counted handle from a native pointer.
552    ///
553    /// Takes ownership of the object the pointer points to, does not increase the reference count.
554    ///
555    /// Returns `None` if the pointer is `null`.
556    #[inline]
557    pub(crate) fn from_ptr(ptr: *mut N) -> Option<Self> {
558        ptr::NonNull::new(ptr).map(Self)
559    }
560
561    /// Creates an reference counted handle from a pointer.
562    ///
563    /// Returns `None` if the pointer is `null`.
564    ///
565    /// Shares ownership with the object referenced to by the pointer, therefore increases the
566    /// reference count.
567    #[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    /// Create a reference to the Rust wrapper from a reference to a pointer that points
576    /// to the native type.
577    pub(crate) fn from_unshared_ptr_ref(n: &*mut N) -> &Option<Self> {
578        unsafe { transmute_ref(n) }
579    }
580
581    /// Create a reference to a all non-null sk_sp<N> slice.
582    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    /// Returns the pointer to the handle.
588    #[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    /// Returns a reference to the native representation.
622    fn native(&self) -> &N {
623        unsafe { self.0.as_ref() }
624    }
625
626    /// Returns a mutable reference to the native representation.
627    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        // Support shared mutability when a ref-counted handle is cloned.
635        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
654/// A trait that consumes self and converts it to a ptr to the native type.
655pub(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
667/// A trait that consumes self and converts it to a ptr to the native type or null.
668pub(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
680/// Tag the type to automatically implement get() functions for
681/// all Index implementations.
682pub trait IndexGet {}
683
684/// Tag the type to automatically implement get() and set() functions
685/// for all Index & IndexMut implementation for that type.
686pub trait IndexSet {}
687
688pub trait IndexGetter<I, O: Copy> {
689    // TODO: Not sure why clippy 1.78-beta.1 complains about this one.
690    #[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
717/// Trait to mark a native type that can be treated a Rust type _inplace_ with the same size and
718/// field layout.
719pub trait NativeTransmutable<NT: Sized>: Sized
720where
721    Self: Sized,
722{
723    /// Provides access to the native value through a
724    /// transmuted reference to the Rust value.
725    fn native(&self) -> &NT {
726        unsafe { transmute_ref(self) }
727    }
728
729    /// Provides mutable access to the native value through a transmuted reference to the Rust
730    /// value.
731    fn native_mut(&mut self) -> &mut NT {
732        unsafe { transmute_ref_mut(self) }
733    }
734
735    /// Copies the native value to an equivalent Rust value.
736    ///
737    /// The `_c` suffix is to remind callers that values that requires C++ ABI features can't be
738    /// used here.
739    fn from_native_c(nt: NT) -> Self {
740        let r = unsafe { mem::transmute_copy::<NT, Self>(&nt) };
741        // don't drop, the Rust type takes over.
742        mem::forget(nt);
743        r
744    }
745
746    /// Copies the rust type to an equivalent instance of the native type.
747    fn into_native(self) -> NT {
748        let r = unsafe { mem::transmute_copy::<Self, NT>(&self) };
749        // don't drop, the native type takes over.
750        mem::forget(self);
751        r
752    }
753
754    /// Returns a reference to the Rust value by transmuting a reference to the native value.
755    fn from_native_ref(nt: &NT) -> &Self {
756        unsafe { transmute_ref(nt) }
757    }
758
759    /// Returns a reference to the Rust array reference by transmuting a reference to the native
760    /// array.
761    fn from_native_array_ref<const N: usize>(nt: &[NT; N]) -> &[Self; N] {
762        unsafe { transmute_ref(nt) }
763    }
764
765    /// Returns a reference to the Rust value through a transmuted reference to the native mutable
766    /// value.
767    fn from_native_ref_mut(nt: &mut NT) -> &mut Self {
768        unsafe { transmute_ref_mut(nt) }
769    }
770
771    /// Converts a pointer to a native value into a pointer to the Rust value.
772    fn from_native_ptr(np: *const NT) -> *const Self {
773        np as _
774    }
775
776    /// Converts a pointer to a mutable native value into a pointer to the mutable Rust value.
777    fn from_native_ptr_mut(np: *mut NT) -> *mut Self {
778        np as _
779    }
780
781    /// Runs a test that guarantees that the native and the Rust type are of the same size and
782    /// alignment.
783    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
839//
840// Convenience functions to access Option<&[]> as optional ptr (opt_ptr)
841// that may be null.
842//
843
844pub(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// Wraps a handle so that the Rust's borrow checker assumes it represents
925// something that borrows something else.
926#[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
936// TODO: this is most likely unsafe because someone could replace the
937// value the reference is pointing to.
938impl<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    /// Notify that the borrowed dependency is not referred to anymore and return the handle.
946    /// # Safety
947    /// The borrowed dependency must be removed before calling `release()`.
948    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
969/// Declares a base class for a native type.
970pub 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    /// Returns `true` if the handle can be sent to another thread.
1005    fn can_send(&self) -> bool;
1006    /// Wrap the handle in a type that can be sent to another thread and unwrapped there.
1007    ///
1008    /// Guaranteed to succeed of can_send() returns `true`.
1009    fn wrap_send(self) -> Result<Sendable<Self>, Self>;
1010}
1011
1012/// `RCHandle<H>` is conditionally Send and can be sent to
1013/// another thread when its reference count is 1.
1014impl<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
1028/// Functions that are (supposedly) _safer_ variants of the ones Rust provides.
1029pub(crate) mod safer {
1030    use core::slice;
1031    use std::ptr;
1032
1033    /// Invokes [slice::from_raw_parts] with the `ptr` only when `len` != 0, otherwise passes
1034    /// `ptr::NonNull::dangling()` as recommended.
1035    ///
1036    /// Panics if `len` != 0 and `ptr` is `null`.
1037    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    /// Invokes [slice::from_raw_parts_mut] with the `ptr` only if `len` != 0, otherwise passes
1048    /// `ptr::NonNull::dangling()` as recommended.
1049    ///
1050    /// Panics if `len` != 0 and `ptr` is `null`.
1051    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}