sel4_abstract_ptr/
core_ext.rs
1use core::{
8 ops::{self, Bound, Range, RangeBounds, RangeTo},
9 ptr::{self, NonNull},
10 slice::SliceIndex,
11};
12
13pub(crate) fn non_null_slice_len<T>(p: NonNull<[T]>) -> usize {
14 mut_ptr_slice_len(p.as_ptr())
15}
16
17pub(crate) fn mut_ptr_slice_len<T>(p: *mut [T]) -> usize {
18 ptr_meta::metadata(p)
19}
20
21pub(crate) fn non_null_slice_as_mut_ptr<T>(p: NonNull<[T]>) -> *mut T {
22 mut_ptr_slice_as_mut_ptr(p.as_ptr())
23}
24
25pub(crate) fn mut_ptr_slice_as_mut_ptr<T>(p: *mut [T]) -> *mut T {
26 p as *mut T
27}
28
29pub(crate) fn non_null_index<I, T>(
30 p: NonNull<[T]>,
31 index: I,
32) -> NonNull<<I as SliceIndex<[T]>>::Output>
33where
34 I: AbstractPtrSliceIndex<[T]> + SliceIndex<[()]> + Clone,
35{
36 NonNull::new(index.abstract_ptr_slice_index(p.as_ptr())).unwrap()
37}
38
39pub(crate) fn range<R>(range: R, bounds: RangeTo<usize>) -> Range<usize>
40where
41 R: RangeBounds<usize>,
42{
43 let len = bounds.end;
44
45 let start = match range.start_bound() {
46 Bound::Included(&start) => start,
47 Bound::Excluded(start) => start
48 .checked_add(1)
49 .unwrap_or_else(|| panic!("attempted to index slice from after maximum usize")),
50 Bound::Unbounded => 0,
51 };
52
53 let end = match range.end_bound() {
54 Bound::Included(end) => end
55 .checked_add(1)
56 .unwrap_or_else(|| panic!("attempted to index slice up to maximum usize")),
57 Bound::Excluded(&end) => end,
58 Bound::Unbounded => len,
59 };
60
61 if start > end {
62 panic!("slice index starts at {start} but ends at {end}",)
63 }
64 if end > len {
65 panic!("range end index {end} out of range for slice of length {len}",)
66 }
67
68 Range { start, end }
69}
70
71#[allow(private_bounds)]
72pub trait AbstractPtrSliceIndex<T: ?Sized>:
73 SliceIndex<T> + AbstractPtrSliceIndexInternal<T>
74{
75}
76
77pub(crate) trait AbstractPtrSliceIndexInternal<T: ?Sized>: SliceIndex<T> {
78 fn abstract_ptr_slice_index(self, slice: *mut T) -> *mut Self::Output;
79}
80
81impl<T> AbstractPtrSliceIndex<[T]> for usize {}
82
83impl<T> AbstractPtrSliceIndexInternal<[T]> for usize {
84 fn abstract_ptr_slice_index(self, slice: *mut [T]) -> *mut Self::Output {
85 bounds_check(mut_ptr_slice_len(slice), self);
86 mut_ptr_slice_as_mut_ptr(slice).wrapping_offset(self.try_into().unwrap())
87 }
88}
89
90impl<T> AbstractPtrSliceIndex<[T]> for Range<usize> {}
91
92impl<T> AbstractPtrSliceIndexInternal<[T]> for Range<usize> {
93 fn abstract_ptr_slice_index(self, slice: *mut [T]) -> *mut Self::Output {
94 bounds_check(mut_ptr_slice_len(slice), self.clone());
95 ptr::slice_from_raw_parts_mut(self.start.abstract_ptr_slice_index(slice), self.len())
96 }
97}
98
99macro_rules! slice_index_impl {
100 ($t:ty) => {
101 impl<T> AbstractPtrSliceIndex<[T]> for $t {}
102
103 impl<T> AbstractPtrSliceIndexInternal<[T]> for $t {
104 fn abstract_ptr_slice_index(self, slice: *mut [T]) -> *mut Self::Output {
105 range(self, ..mut_ptr_slice_len(slice)).abstract_ptr_slice_index(slice)
106 }
107 }
108 };
109}
110
111slice_index_impl!((Bound<usize>, Bound<usize>));
112slice_index_impl!(ops::RangeFrom<usize>);
113slice_index_impl!(ops::RangeFull);
114slice_index_impl!(ops::RangeInclusive<usize>);
115slice_index_impl!(ops::RangeTo<usize>);
116slice_index_impl!(ops::RangeToInclusive<usize>);
117
118fn bounds_check(len: usize, index: impl SliceIndex<[()]>) {
119 const MAX_ARRAY: [(); usize::MAX] = [(); usize::MAX];
120
121 let bound_check_slice = &MAX_ARRAY[..len];
122 let _ = &bound_check_slice[index];
123}