blob: 069631176e0575685d4236072ab08c867cc0547e [file] [log] [blame]
David Tolnaycb07a842021-04-16 16:08:52 -07001#![allow(missing_docs)]
2
David Tolnay7fdd4a82021-04-10 11:53:04 -07003use core::mem::{self, MaybeUninit};
David Tolnay9bffb932021-01-02 02:15:21 -08004use core::ptr::{self, NonNull};
David Tolnay5515a9e2020-11-25 19:07:54 -08005use core::slice;
6
David Tolnay7fdd4a82021-04-10 11:53:04 -07007// ABI compatible with C++ rust::Slice<T> (not necessarily &[T]).
David Tolnay5515a9e2020-11-25 19:07:54 -08008#[repr(C)]
David Tolnay5515a9e2020-11-25 19:07:54 -08009pub struct RustSlice {
David Tolnay7fdd4a82021-04-10 11:53:04 -070010 repr: [MaybeUninit<usize>; mem::size_of::<NonNull<[()]>>() / mem::size_of::<usize>()],
David Tolnay5515a9e2020-11-25 19:07:54 -080011}
12
13impl RustSlice {
David Tolnay9bffb932021-01-02 02:15:21 -080014 pub fn from_ref<T>(slice: &[T]) -> Self {
David Tolnay5577e7c2021-04-10 11:36:45 -070015 let ptr = NonNull::from(slice).cast::<T>();
16 let len = slice.len();
17 Self::from_raw_parts(ptr, len)
David Tolnay5515a9e2020-11-25 19:07:54 -080018 }
19
David Tolnay9bffb932021-01-02 02:15:21 -080020 pub fn from_mut<T>(slice: &mut [T]) -> Self {
David Tolnay5577e7c2021-04-10 11:36:45 -070021 let ptr = NonNull::from(&mut *slice).cast::<T>();
22 let len = slice.len();
23 Self::from_raw_parts(ptr, len)
24 }
25
26 pub unsafe fn as_slice<'a, T>(self) -> &'a [T] {
David Tolnayc5285c72021-08-27 12:44:05 -070027 let ptr = self.as_non_null_ptr().as_ptr();
David Tolnay5577e7c2021-04-10 11:36:45 -070028 let len = self.len();
David Tolnay0b4b73f2021-08-27 12:12:53 -070029 unsafe { slice::from_raw_parts(ptr, len) }
David Tolnay5577e7c2021-04-10 11:36:45 -070030 }
31
32 pub unsafe fn as_mut_slice<'a, T>(self) -> &'a mut [T] {
David Tolnayc5285c72021-08-27 12:44:05 -070033 let ptr = self.as_non_null_ptr().as_ptr();
David Tolnay5577e7c2021-04-10 11:36:45 -070034 let len = self.len();
David Tolnay0b4b73f2021-08-27 12:12:53 -070035 unsafe { slice::from_raw_parts_mut(ptr, len) }
David Tolnay5577e7c2021-04-10 11:36:45 -070036 }
37
38 pub(crate) fn from_raw_parts<T>(ptr: NonNull<T>, len: usize) -> Self {
39 // TODO: use NonNull::from_raw_parts(ptr.cast(), len) when stable.
40 // https://doc.rust-lang.org/nightly/std/ptr/struct.NonNull.html#method.from_raw_parts
41 // https://github.com/rust-lang/rust/issues/81513
42 let ptr = ptr::slice_from_raw_parts_mut(ptr.as_ptr().cast(), len);
David Tolnay7fdd4a82021-04-10 11:53:04 -070043 unsafe { mem::transmute::<NonNull<[()]>, RustSlice>(NonNull::new_unchecked(ptr)) }
David Tolnay5515a9e2020-11-25 19:07:54 -080044 }
45
David Tolnayc5285c72021-08-27 12:44:05 -070046 pub(crate) fn as_non_null_ptr<T>(&self) -> NonNull<T> {
David Tolnay7fdd4a82021-04-10 11:53:04 -070047 let rust_slice = RustSlice { repr: self.repr };
48 let repr = unsafe { mem::transmute::<RustSlice, NonNull<[()]>>(rust_slice) };
49 repr.cast()
David Tolnay5515a9e2020-11-25 19:07:54 -080050 }
51
David Tolnay5577e7c2021-04-10 11:36:45 -070052 pub(crate) fn len(&self) -> usize {
David Tolnay7fdd4a82021-04-10 11:53:04 -070053 let rust_slice = RustSlice { repr: self.repr };
54 let repr = unsafe { mem::transmute::<RustSlice, NonNull<[()]>>(rust_slice) };
55 // TODO: use repr.len() when stable.
David Tolnay5577e7c2021-04-10 11:36:45 -070056 // https://doc.rust-lang.org/nightly/std/ptr/struct.NonNull.html#method.len
57 // https://github.com/rust-lang/rust/issues/71146
David Tolnay7fdd4a82021-04-10 11:53:04 -070058 unsafe { repr.as_ref() }.len()
David Tolnay5515a9e2020-11-25 19:07:54 -080059 }
60}
61
David Tolnay7fdd4a82021-04-10 11:53:04 -070062const_assert_eq!(mem::size_of::<NonNull<[()]>>(), mem::size_of::<RustSlice>());
David Tolnay5515a9e2020-11-25 19:07:54 -080063const_assert_eq!(
David Tolnay7fdd4a82021-04-10 11:53:04 -070064 mem::align_of::<NonNull<[()]>>(),
65 mem::align_of::<RustSlice>(),
David Tolnay5515a9e2020-11-25 19:07:54 -080066);