Skip to main content

skia_safe/
prelude.rs

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