1use crate::{
2 errors::{ErrorStatus, IntoErr},
3 ffi::NotZeroable,
4};
5
6#[derive(Debug, Clone, Copy, PartialEq, Eq)]
8pub enum InvalidSliceError {
9 PtrNotAligned,
10 PtrIsNull,
11 LenTooLarge,
12 Other,
13}
14
15impl IntoErr for InvalidSliceError {
16 fn into_err(self) -> ErrorStatus {
17 match self {
18 InvalidSliceError::LenTooLarge => ErrorStatus::StrTooLong,
19 _ => ErrorStatus::InvalidPtr,
20 }
21 }
22}
23
24#[repr(C)]
25#[derive(Debug, Clone, Copy)]
26pub struct Slice<T> {
28 pub(crate) ptr: *mut T,
29 pub(crate) len: usize,
30}
31
32impl<T> Slice<T> {
33 #[inline]
34 pub const unsafe fn from_raw_parts(ptr: *mut T, len: usize) -> Self {
35 assert!(
36 !ptr.is_null() && len <= isize::MAX as usize,
37 "RawSlice::from_raw_parts requires ptr to be aligned and non-null, and len must be less than or equal to isize::MAX"
38 );
39 Self { ptr, len }
40 }
41
42 #[inline]
43 pub const fn from_slice_mut(slice: &mut [T]) -> Self {
44 Self {
45 ptr: slice.as_mut_ptr(),
46 len: slice.len(),
47 }
48 }
49
50 #[inline]
51 pub const fn from_slice(slice: &[T]) -> Self {
52 Self {
53 ptr: slice.as_ptr().cast_mut(),
54 len: slice.len(),
55 }
56 }
57
58 #[inline(always)]
59 pub const fn len(&self) -> usize {
60 self.len
61 }
62
63 #[inline(always)]
64 pub const fn as_ptr(&self) -> *const T {
65 self.ptr
66 }
67
68 #[inline]
70 pub const unsafe fn as_slice_mut_unchecked<'a>(&self) -> &'a mut [T] {
71 unsafe { core::slice::from_raw_parts_mut(self.ptr, self.len) }
72 }
73
74 #[inline]
75 pub const unsafe fn as_slice_unchecked<'a>(&self) -> &'a [T] {
76 unsafe { core::slice::from_raw_parts(self.ptr, self.len) }
77 }
78
79 #[inline]
83 pub unsafe fn try_as_slice_mut_custom<'a>(
84 &self,
85 validator: impl FnOnce(*const ()) -> bool,
86 ) -> Result<&'a mut [T], InvalidSliceError> {
87 if self.ptr.is_null() {
88 return Err(InvalidSliceError::PtrIsNull);
89 }
90
91 if !self.ptr.is_aligned() {
92 return Err(InvalidSliceError::PtrNotAligned);
93 }
94
95 if self.len > isize::MAX as usize {
96 return Err(InvalidSliceError::LenTooLarge);
97 }
98
99 if !validator(self.ptr.cast()) {
100 return Err(InvalidSliceError::Other);
101 }
102
103 Ok(unsafe { self.as_slice_mut_unchecked() })
104 }
105
106 #[inline]
110 pub unsafe fn try_as_slice_custom<'a>(
111 &self,
112 validator: impl Fn(*const ()) -> bool,
113 ) -> Result<&'a [T], InvalidSliceError> {
114 unsafe {
115 match self.try_as_slice_mut_custom(validator) {
116 Ok(slice) => Ok(slice),
117 Err(err) => Err(err),
118 }
119 }
120 }
121
122 pub unsafe fn try_as_slice_mut<'a>(&self) -> Result<&'a mut [T], InvalidSliceError> {
123 unsafe {
124 match self.try_as_slice_mut_custom(|_| true) {
125 Ok(slice) => Ok(slice),
126 Err(err) => Err(err),
127 }
128 }
129 }
130
131 pub unsafe fn try_as_slice<'a>(&self) -> Result<&'a [T], InvalidSliceError> {
132 unsafe {
133 match self.try_as_slice_custom(|_| true) {
134 Ok(slice) => Ok(slice),
135 Err(err) => Err(err),
136 }
137 }
138 }
139}
140
141impl<T> Slice<Slice<T>> {
142 #[inline]
151 pub const unsafe fn from_slices_ptr_mut(slices: *mut [*mut [T]]) -> Self {
152 let old_slices = unsafe { &mut *slices };
153 let raw_slices = unsafe { &mut *(slices as *mut [Slice<T>]) };
154
155 let mut i = 0;
156 while i < old_slices.len() {
157 let slice = old_slices[i];
158 raw_slices[i] = unsafe { Slice::from_slice(&*slice) };
159 i += 1;
160 }
161
162 Slice::from_slice(raw_slices)
163 }
164
165 #[inline]
175 pub unsafe fn try_into_slices_ptr_mut(
176 self,
177 custom_validate: impl Fn(*const ()) -> bool,
178 ) -> Result<*mut [*mut [T]], InvalidSliceError> {
179 let root = unsafe { self.try_as_slice_mut_custom(&custom_validate)? };
180 let root_ptr = root as *mut _;
181 let results = unsafe { &mut *(root_ptr as *mut [*mut [T]]) };
182
183 let mut i = 0;
184 while i < results.len() {
185 let slice = &root[i];
186 results[i] = unsafe { slice.try_as_slice_mut_custom(&custom_validate)? };
187 i += 1;
188 }
189
190 Ok(results)
191 }
192}
193
194impl<T> NotZeroable for Slice<T> {
195 #[inline(always)]
196 fn is_zero(&self) -> bool {
197 self.ptr.is_null()
198 }
199}