blob: b7b82e4ef2583608de8b3f9000d40b83c469ad64 [file] [log] [blame]
David Tolnay7fdd4a82021-04-10 11:53:04 -07001use core::mem::{self, MaybeUninit};
David Tolnay9bffb932021-01-02 02:15:21 -08002use core::ptr::{self, NonNull};
David Tolnay5515a9e2020-11-25 19:07:54 -08003use core::slice;
4
David Tolnay7fdd4a82021-04-10 11:53:04 -07005// ABI compatible with C++ rust::Slice<T> (not necessarily &[T]).
David Tolnay5515a9e2020-11-25 19:07:54 -08006#[repr(C)]
David Tolnay5515a9e2020-11-25 19:07:54 -08007pub struct RustSlice {
David Tolnay7fdd4a82021-04-10 11:53:04 -07008 repr: [MaybeUninit<usize>; mem::size_of::<NonNull<[()]>>() / mem::size_of::<usize>()],
David Tolnay5515a9e2020-11-25 19:07:54 -08009}
10
11impl RustSlice {
David Tolnay9bffb932021-01-02 02:15:21 -080012 pub fn from_ref<T>(slice: &[T]) -> Self {
David Tolnay5577e7c2021-04-10 11:36:45 -070013 let ptr = NonNull::from(slice).cast::<T>();
14 let len = slice.len();
15 Self::from_raw_parts(ptr, len)
David Tolnay5515a9e2020-11-25 19:07:54 -080016 }
17
David Tolnay9bffb932021-01-02 02:15:21 -080018 pub fn from_mut<T>(slice: &mut [T]) -> Self {
David Tolnay5577e7c2021-04-10 11:36:45 -070019 let ptr = NonNull::from(&mut *slice).cast::<T>();
20 let len = slice.len();
21 Self::from_raw_parts(ptr, len)
22 }
23
24 pub unsafe fn as_slice<'a, T>(self) -> &'a [T] {
25 let ptr = self.as_ptr();
26 let len = self.len();
27 slice::from_raw_parts(ptr.as_ptr(), len)
28 }
29
30 pub unsafe fn as_mut_slice<'a, T>(self) -> &'a mut [T] {
31 let ptr = self.as_ptr();
32 let len = self.len();
33 slice::from_raw_parts_mut(ptr.as_ptr(), len)
34 }
35
36 pub(crate) fn from_raw_parts<T>(ptr: NonNull<T>, len: usize) -> Self {
37 // TODO: use NonNull::from_raw_parts(ptr.cast(), len) when stable.
38 // https://doc.rust-lang.org/nightly/std/ptr/struct.NonNull.html#method.from_raw_parts
39 // https://github.com/rust-lang/rust/issues/81513
40 let ptr = ptr::slice_from_raw_parts_mut(ptr.as_ptr().cast(), len);
David Tolnay7fdd4a82021-04-10 11:53:04 -070041 unsafe { mem::transmute::<NonNull<[()]>, RustSlice>(NonNull::new_unchecked(ptr)) }
David Tolnay5515a9e2020-11-25 19:07:54 -080042 }
43
David Tolnay5577e7c2021-04-10 11:36:45 -070044 pub(crate) fn as_ptr<T>(&self) -> NonNull<T> {
David Tolnay7fdd4a82021-04-10 11:53:04 -070045 let rust_slice = RustSlice { repr: self.repr };
46 let repr = unsafe { mem::transmute::<RustSlice, NonNull<[()]>>(rust_slice) };
47 repr.cast()
David Tolnay5515a9e2020-11-25 19:07:54 -080048 }
49
David Tolnay5577e7c2021-04-10 11:36:45 -070050 pub(crate) fn len(&self) -> usize {
David Tolnay7fdd4a82021-04-10 11:53:04 -070051 let rust_slice = RustSlice { repr: self.repr };
52 let repr = unsafe { mem::transmute::<RustSlice, NonNull<[()]>>(rust_slice) };
53 // TODO: use repr.len() when stable.
David Tolnay5577e7c2021-04-10 11:36:45 -070054 // https://doc.rust-lang.org/nightly/std/ptr/struct.NonNull.html#method.len
55 // https://github.com/rust-lang/rust/issues/71146
David Tolnay7fdd4a82021-04-10 11:53:04 -070056 unsafe { repr.as_ref() }.len()
David Tolnay5515a9e2020-11-25 19:07:54 -080057 }
58}
59
David Tolnay7fdd4a82021-04-10 11:53:04 -070060const_assert_eq!(mem::size_of::<NonNull<[()]>>(), mem::size_of::<RustSlice>());
David Tolnay5515a9e2020-11-25 19:07:54 -080061const_assert_eq!(
David Tolnay7fdd4a82021-04-10 11:53:04 -070062 mem::align_of::<NonNull<[()]>>(),
63 mem::align_of::<RustSlice>(),
David Tolnay5515a9e2020-11-25 19:07:54 -080064);