• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #![allow(missing_docs)]
2 
3 use core::mem::{self, MaybeUninit};
4 use core::ptr::{self, NonNull};
5 use core::slice;
6 
7 // ABI compatible with C++ rust::Slice<T> (not necessarily &[T]).
8 #[repr(C)]
9 pub struct RustSlice {
10     repr: [MaybeUninit<usize>; mem::size_of::<NonNull<[()]>>() / mem::size_of::<usize>()],
11 }
12 
13 impl RustSlice {
from_ref<T>(slice: &[T]) -> Self14     pub fn from_ref<T>(slice: &[T]) -> Self {
15         let ptr = NonNull::from(slice).cast::<T>();
16         let len = slice.len();
17         Self::from_raw_parts(ptr, len)
18     }
19 
from_mut<T>(slice: &mut [T]) -> Self20     pub fn from_mut<T>(slice: &mut [T]) -> Self {
21         let ptr = NonNull::from(&mut *slice).cast::<T>();
22         let len = slice.len();
23         Self::from_raw_parts(ptr, len)
24     }
25 
as_slice<'a, T>(self) -> &'a [T]26     pub unsafe fn as_slice<'a, T>(self) -> &'a [T] {
27         let ptr = self.as_non_null_ptr().as_ptr();
28         let len = self.len();
29         unsafe { slice::from_raw_parts(ptr, len) }
30     }
31 
as_mut_slice<'a, T>(self) -> &'a mut [T]32     pub unsafe fn as_mut_slice<'a, T>(self) -> &'a mut [T] {
33         let ptr = self.as_non_null_ptr().as_ptr();
34         let len = self.len();
35         unsafe { slice::from_raw_parts_mut(ptr, len) }
36     }
37 
from_raw_parts<T>(ptr: NonNull<T>, len: usize) -> Self38     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);
43         unsafe { mem::transmute::<NonNull<[()]>, RustSlice>(NonNull::new_unchecked(ptr)) }
44     }
45 
as_non_null_ptr<T>(&self) -> NonNull<T>46     pub(crate) fn as_non_null_ptr<T>(&self) -> NonNull<T> {
47         let rust_slice = RustSlice { repr: self.repr };
48         let repr = unsafe { mem::transmute::<RustSlice, NonNull<[()]>>(rust_slice) };
49         repr.cast()
50     }
51 
len(&self) -> usize52     pub(crate) fn len(&self) -> usize {
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.
56         // https://doc.rust-lang.org/nightly/std/ptr/struct.NonNull.html#method.len
57         // https://github.com/rust-lang/rust/issues/71146
58         unsafe { repr.as_ref() }.len()
59     }
60 }
61 
62 const_assert_eq!(mem::size_of::<NonNull<[()]>>(), mem::size_of::<RustSlice>());
63 const_assert_eq!(
64     mem::align_of::<NonNull<[()]>>(),
65     mem::align_of::<RustSlice>(),
66 );
67