| David Tolnay | cb07a84 | 2021-04-16 16:08:52 -0700 | [diff] [blame^] | 1 | #![allow(missing_docs)] |
| 2 | |
| David Tolnay | 7fdd4a8 | 2021-04-10 11:53:04 -0700 | [diff] [blame] | 3 | use core::mem::{self, MaybeUninit}; |
| David Tolnay | 9bffb93 | 2021-01-02 02:15:21 -0800 | [diff] [blame] | 4 | use core::ptr::{self, NonNull}; |
| David Tolnay | 5515a9e | 2020-11-25 19:07:54 -0800 | [diff] [blame] | 5 | use core::slice; |
| 6 | |
| David Tolnay | 7fdd4a8 | 2021-04-10 11:53:04 -0700 | [diff] [blame] | 7 | // ABI compatible with C++ rust::Slice<T> (not necessarily &[T]). |
| David Tolnay | 5515a9e | 2020-11-25 19:07:54 -0800 | [diff] [blame] | 8 | #[repr(C)] |
| David Tolnay | 5515a9e | 2020-11-25 19:07:54 -0800 | [diff] [blame] | 9 | pub struct RustSlice { |
| David Tolnay | 7fdd4a8 | 2021-04-10 11:53:04 -0700 | [diff] [blame] | 10 | repr: [MaybeUninit<usize>; mem::size_of::<NonNull<[()]>>() / mem::size_of::<usize>()], |
| David Tolnay | 5515a9e | 2020-11-25 19:07:54 -0800 | [diff] [blame] | 11 | } |
| 12 | |
| 13 | impl RustSlice { |
| David Tolnay | 9bffb93 | 2021-01-02 02:15:21 -0800 | [diff] [blame] | 14 | pub fn from_ref<T>(slice: &[T]) -> Self { |
| David Tolnay | 5577e7c | 2021-04-10 11:36:45 -0700 | [diff] [blame] | 15 | let ptr = NonNull::from(slice).cast::<T>(); |
| 16 | let len = slice.len(); |
| 17 | Self::from_raw_parts(ptr, len) |
| David Tolnay | 5515a9e | 2020-11-25 19:07:54 -0800 | [diff] [blame] | 18 | } |
| 19 | |
| David Tolnay | 9bffb93 | 2021-01-02 02:15:21 -0800 | [diff] [blame] | 20 | pub fn from_mut<T>(slice: &mut [T]) -> Self { |
| David Tolnay | 5577e7c | 2021-04-10 11:36:45 -0700 | [diff] [blame] | 21 | 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] { |
| 27 | let ptr = self.as_ptr(); |
| 28 | let len = self.len(); |
| 29 | slice::from_raw_parts(ptr.as_ptr(), len) |
| 30 | } |
| 31 | |
| 32 | pub unsafe fn as_mut_slice<'a, T>(self) -> &'a mut [T] { |
| 33 | let ptr = self.as_ptr(); |
| 34 | let len = self.len(); |
| 35 | slice::from_raw_parts_mut(ptr.as_ptr(), len) |
| 36 | } |
| 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 Tolnay | 7fdd4a8 | 2021-04-10 11:53:04 -0700 | [diff] [blame] | 43 | unsafe { mem::transmute::<NonNull<[()]>, RustSlice>(NonNull::new_unchecked(ptr)) } |
| David Tolnay | 5515a9e | 2020-11-25 19:07:54 -0800 | [diff] [blame] | 44 | } |
| 45 | |
| David Tolnay | 5577e7c | 2021-04-10 11:36:45 -0700 | [diff] [blame] | 46 | pub(crate) fn as_ptr<T>(&self) -> NonNull<T> { |
| David Tolnay | 7fdd4a8 | 2021-04-10 11:53:04 -0700 | [diff] [blame] | 47 | let rust_slice = RustSlice { repr: self.repr }; |
| 48 | let repr = unsafe { mem::transmute::<RustSlice, NonNull<[()]>>(rust_slice) }; |
| 49 | repr.cast() |
| David Tolnay | 5515a9e | 2020-11-25 19:07:54 -0800 | [diff] [blame] | 50 | } |
| 51 | |
| David Tolnay | 5577e7c | 2021-04-10 11:36:45 -0700 | [diff] [blame] | 52 | pub(crate) fn len(&self) -> usize { |
| David Tolnay | 7fdd4a8 | 2021-04-10 11:53:04 -0700 | [diff] [blame] | 53 | 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 Tolnay | 5577e7c | 2021-04-10 11:36:45 -0700 | [diff] [blame] | 56 | // https://doc.rust-lang.org/nightly/std/ptr/struct.NonNull.html#method.len |
| 57 | // https://github.com/rust-lang/rust/issues/71146 |
| David Tolnay | 7fdd4a8 | 2021-04-10 11:53:04 -0700 | [diff] [blame] | 58 | unsafe { repr.as_ref() }.len() |
| David Tolnay | 5515a9e | 2020-11-25 19:07:54 -0800 | [diff] [blame] | 59 | } |
| 60 | } |
| 61 | |
| David Tolnay | 7fdd4a8 | 2021-04-10 11:53:04 -0700 | [diff] [blame] | 62 | const_assert_eq!(mem::size_of::<NonNull<[()]>>(), mem::size_of::<RustSlice>()); |
| David Tolnay | 5515a9e | 2020-11-25 19:07:54 -0800 | [diff] [blame] | 63 | const_assert_eq!( |
| David Tolnay | 7fdd4a8 | 2021-04-10 11:53:04 -0700 | [diff] [blame] | 64 | mem::align_of::<NonNull<[()]>>(), |
| 65 | mem::align_of::<RustSlice>(), |
| David Tolnay | 5515a9e | 2020-11-25 19:07:54 -0800 | [diff] [blame] | 66 | ); |