133d722a9Sopenharmony_ci#![allow(missing_docs)]
233d722a9Sopenharmony_ci
333d722a9Sopenharmony_ciuse core::mem::{self, MaybeUninit};
433d722a9Sopenharmony_ciuse core::ptr::{self, NonNull};
533d722a9Sopenharmony_ciuse core::slice;
633d722a9Sopenharmony_ci
733d722a9Sopenharmony_ci// ABI compatible with C++ rust::Slice<T> (not necessarily &[T]).
833d722a9Sopenharmony_ci#[repr(C)]
933d722a9Sopenharmony_cipub struct RustSlice {
1033d722a9Sopenharmony_ci    repr: [MaybeUninit<usize>; mem::size_of::<NonNull<[()]>>() / mem::size_of::<usize>()],
1133d722a9Sopenharmony_ci}
1233d722a9Sopenharmony_ci
1333d722a9Sopenharmony_ciimpl RustSlice {
1433d722a9Sopenharmony_ci    pub fn from_ref<T>(slice: &[T]) -> Self {
1533d722a9Sopenharmony_ci        let ptr = NonNull::from(slice).cast::<T>();
1633d722a9Sopenharmony_ci        let len = slice.len();
1733d722a9Sopenharmony_ci        Self::from_raw_parts(ptr, len)
1833d722a9Sopenharmony_ci    }
1933d722a9Sopenharmony_ci
2033d722a9Sopenharmony_ci    pub fn from_mut<T>(slice: &mut [T]) -> Self {
2133d722a9Sopenharmony_ci        let ptr = NonNull::from(&mut *slice).cast::<T>();
2233d722a9Sopenharmony_ci        let len = slice.len();
2333d722a9Sopenharmony_ci        Self::from_raw_parts(ptr, len)
2433d722a9Sopenharmony_ci    }
2533d722a9Sopenharmony_ci
2633d722a9Sopenharmony_ci    pub unsafe fn as_slice<'a, T>(self) -> &'a [T] {
2733d722a9Sopenharmony_ci        let ptr = self.as_non_null_ptr().as_ptr();
2833d722a9Sopenharmony_ci        let len = self.len();
2933d722a9Sopenharmony_ci        unsafe { slice::from_raw_parts(ptr, len) }
3033d722a9Sopenharmony_ci    }
3133d722a9Sopenharmony_ci
3233d722a9Sopenharmony_ci    pub unsafe fn as_mut_slice<'a, T>(self) -> &'a mut [T] {
3333d722a9Sopenharmony_ci        let ptr = self.as_non_null_ptr().as_ptr();
3433d722a9Sopenharmony_ci        let len = self.len();
3533d722a9Sopenharmony_ci        unsafe { slice::from_raw_parts_mut(ptr, len) }
3633d722a9Sopenharmony_ci    }
3733d722a9Sopenharmony_ci
3833d722a9Sopenharmony_ci    pub(crate) fn from_raw_parts<T>(ptr: NonNull<T>, len: usize) -> Self {
3933d722a9Sopenharmony_ci        // TODO: use NonNull::from_raw_parts(ptr.cast(), len) when stable.
4033d722a9Sopenharmony_ci        // https://doc.rust-lang.org/nightly/std/ptr/struct.NonNull.html#method.from_raw_parts
4133d722a9Sopenharmony_ci        // https://github.com/rust-lang/rust/issues/81513
4233d722a9Sopenharmony_ci        let ptr = ptr::slice_from_raw_parts_mut(ptr.as_ptr().cast(), len);
4333d722a9Sopenharmony_ci        unsafe { mem::transmute::<NonNull<[()]>, RustSlice>(NonNull::new_unchecked(ptr)) }
4433d722a9Sopenharmony_ci    }
4533d722a9Sopenharmony_ci
4633d722a9Sopenharmony_ci    pub(crate) fn as_non_null_ptr<T>(&self) -> NonNull<T> {
4733d722a9Sopenharmony_ci        let rust_slice = RustSlice { repr: self.repr };
4833d722a9Sopenharmony_ci        let repr = unsafe { mem::transmute::<RustSlice, NonNull<[()]>>(rust_slice) };
4933d722a9Sopenharmony_ci        repr.cast()
5033d722a9Sopenharmony_ci    }
5133d722a9Sopenharmony_ci
5233d722a9Sopenharmony_ci    pub(crate) fn len(&self) -> usize {
5333d722a9Sopenharmony_ci        let rust_slice = RustSlice { repr: self.repr };
5433d722a9Sopenharmony_ci        let repr = unsafe { mem::transmute::<RustSlice, NonNull<[()]>>(rust_slice) };
5533d722a9Sopenharmony_ci        // TODO: use repr.len() when stable.
5633d722a9Sopenharmony_ci        // https://doc.rust-lang.org/nightly/std/ptr/struct.NonNull.html#method.len
5733d722a9Sopenharmony_ci        // https://github.com/rust-lang/rust/issues/71146
5833d722a9Sopenharmony_ci        unsafe { repr.as_ref() }.len()
5933d722a9Sopenharmony_ci    }
6033d722a9Sopenharmony_ci}
6133d722a9Sopenharmony_ci
6233d722a9Sopenharmony_ciconst_assert_eq!(mem::size_of::<NonNull<[()]>>(), mem::size_of::<RustSlice>());
6333d722a9Sopenharmony_ciconst_assert_eq!(
6433d722a9Sopenharmony_ci    mem::align_of::<NonNull<[()]>>(),
6533d722a9Sopenharmony_ci    mem::align_of::<RustSlice>(),
6633d722a9Sopenharmony_ci);
67