blob: 4b6b12ba1cb1a1372a96cfa965b9f6fb897cdf51 [file] [log] [blame]
David Tolnay5515a9e2020-11-25 19:07:54 -08001use core::mem;
David Tolnay9bffb932021-01-02 02:15:21 -08002use core::ptr::{self, NonNull};
David Tolnay5515a9e2020-11-25 19:07:54 -08003use core::slice;
4
David Tolnay5515a9e2020-11-25 19:07:54 -08005#[repr(C)]
David Tolnay5515a9e2020-11-25 19:07:54 -08006pub struct RustSlice {
David Tolnay5577e7c2021-04-10 11:36:45 -07007 repr: NonNull<[()]>,
David Tolnay5515a9e2020-11-25 19:07:54 -08008}
9
10impl RustSlice {
David Tolnay9bffb932021-01-02 02:15:21 -080011 pub fn from_ref<T>(slice: &[T]) -> Self {
David Tolnay5577e7c2021-04-10 11:36:45 -070012 let ptr = NonNull::from(slice).cast::<T>();
13 let len = slice.len();
14 Self::from_raw_parts(ptr, len)
David Tolnay5515a9e2020-11-25 19:07:54 -080015 }
16
David Tolnay9bffb932021-01-02 02:15:21 -080017 pub fn from_mut<T>(slice: &mut [T]) -> Self {
David Tolnay5577e7c2021-04-10 11:36:45 -070018 let ptr = NonNull::from(&mut *slice).cast::<T>();
19 let len = slice.len();
20 Self::from_raw_parts(ptr, len)
21 }
22
23 pub unsafe fn as_slice<'a, T>(self) -> &'a [T] {
24 let ptr = self.as_ptr();
25 let len = self.len();
26 slice::from_raw_parts(ptr.as_ptr(), len)
27 }
28
29 pub unsafe fn as_mut_slice<'a, T>(self) -> &'a mut [T] {
30 let ptr = self.as_ptr();
31 let len = self.len();
32 slice::from_raw_parts_mut(ptr.as_ptr(), len)
33 }
34
35 pub(crate) fn from_raw_parts<T>(ptr: NonNull<T>, len: usize) -> Self {
36 // TODO: use NonNull::from_raw_parts(ptr.cast(), len) when stable.
37 // https://doc.rust-lang.org/nightly/std/ptr/struct.NonNull.html#method.from_raw_parts
38 // https://github.com/rust-lang/rust/issues/81513
39 let ptr = ptr::slice_from_raw_parts_mut(ptr.as_ptr().cast(), len);
David Tolnay5515a9e2020-11-25 19:07:54 -080040 RustSlice {
David Tolnay9bffb932021-01-02 02:15:21 -080041 repr: unsafe { NonNull::new_unchecked(ptr) },
David Tolnay5515a9e2020-11-25 19:07:54 -080042 }
43 }
44
David Tolnay5577e7c2021-04-10 11:36:45 -070045 pub(crate) fn as_ptr<T>(&self) -> NonNull<T> {
46 self.repr.cast()
David Tolnay5515a9e2020-11-25 19:07:54 -080047 }
48
David Tolnay5577e7c2021-04-10 11:36:45 -070049 pub(crate) fn len(&self) -> usize {
50 // TODO: use self.repr.len() when stable.
51 // https://doc.rust-lang.org/nightly/std/ptr/struct.NonNull.html#method.len
52 // https://github.com/rust-lang/rust/issues/71146
53 let slice = unsafe { self.repr.as_ref() };
54 slice.len()
David Tolnay5515a9e2020-11-25 19:07:54 -080055 }
56}
57
58const_assert_eq!(
59 mem::size_of::<Option<RustSlice>>(),
60 mem::size_of::<RustSlice>(),
61);