sel4_abstract_ptr/abstract_ptr/
slice_operations.rs
1use core::{
9 ops::{Range, RangeBounds},
10 ptr::{self, NonNull},
11 slice::SliceIndex,
12};
13
14use crate::{
15 access::{Access, Readable, Writable},
16 core_ext::{
17 non_null_index, non_null_slice_as_mut_ptr, non_null_slice_len, range, AbstractPtrSliceIndex,
18 },
19 memory_type::BulkOps,
20 AbstractPtr,
21};
22
23impl<'a, M, T, A> AbstractPtr<'a, M, [T], A> {
24 pub fn len(self) -> usize {
25 non_null_slice_len(self.pointer)
26 }
27
28 pub fn is_empty(self) -> bool {
29 self.len() == 0
30 }
31
32 pub fn index<I>(self, index: I) -> AbstractPtr<'a, M, <I as SliceIndex<[T]>>::Output, A>
33 where
34 I: AbstractPtrSliceIndex<[T]> + SliceIndex<[()]> + Clone,
35 A: Access,
36 {
37 unsafe { self.map(|slice| non_null_index(slice, index)) }
38 }
39
40 pub fn iter(self) -> impl Iterator<Item = AbstractPtr<'a, M, T, A>>
41 where
42 A: Access,
43 {
44 let ptr = non_null_slice_as_mut_ptr(self.pointer);
45 let len = self.len();
46 (0..len)
47 .map(move |i| unsafe { AbstractPtr::new_generic(NonNull::new_unchecked(ptr.add(i))) })
48 }
49
50 pub fn copy_into_slice(self, dst: &mut [T])
51 where
52 M: BulkOps<T>,
53 A: Readable,
54 {
55 let len = self.len();
56 assert_eq!(
57 len,
58 dst.len(),
59 "destination and source slices have different lengths"
60 );
61 unsafe {
62 M::memcpy_from(
63 dst.as_mut_ptr(),
64 non_null_slice_as_mut_ptr(self.pointer),
65 len,
66 );
67 }
68 }
69
70 pub fn copy_from_slice(self, src: &[T])
71 where
72 M: BulkOps<T>,
73 A: Writable,
74 {
75 let len = self.len();
76 assert_eq!(
77 len,
78 src.len(),
79 "destination and source slices have different lengths"
80 );
81 unsafe {
82 M::memcpy_into(non_null_slice_as_mut_ptr(self.pointer), src.as_ptr(), len);
83 }
84 }
85
86 pub fn copy_within(self, src: impl RangeBounds<usize>, dest: usize)
87 where
88 M: BulkOps<T>,
89 A: Readable + Writable,
90 {
91 let len = self.pointer.len();
92 let Range {
94 start: src_start,
95 end: src_end,
96 } = range(src, ..len);
97 let count = src_end - src_start;
98 assert!(dest <= len - count, "dest is out of bounds");
99 unsafe {
100 M::memmove(
101 non_null_slice_as_mut_ptr(self.pointer).add(dest),
102 non_null_slice_as_mut_ptr(self.pointer).add(src_start),
103 count,
104 );
105 }
106 }
107
108 #[allow(clippy::type_complexity)]
109 pub fn split_at(self, mid: usize) -> (AbstractPtr<'a, M, [T], A>, AbstractPtr<'a, M, [T], A>)
110 where
111 A: Access,
112 {
113 assert!(mid <= self.pointer.len());
114 unsafe { self.split_at_unchecked(mid) }
117 }
118
119 #[allow(clippy::type_complexity)]
120 unsafe fn split_at_unchecked(
121 self,
122 mid: usize,
123 ) -> (AbstractPtr<'a, M, [T], A>, AbstractPtr<'a, M, [T], A>)
124 where
125 A: Access,
126 {
127 unsafe {
129 (
130 AbstractPtr::new_generic(non_null_index(self.pointer, ..mid)),
131 AbstractPtr::new_generic(non_null_index(self.pointer, mid..)),
132 )
133 }
134 }
135
136 #[allow(clippy::type_complexity)]
137 pub fn as_chunks<const N: usize>(
138 self,
139 ) -> (AbstractPtr<'a, M, [[T; N]], A>, AbstractPtr<'a, M, [T], A>)
140 where
141 A: Access,
142 {
143 assert_ne!(N, 0);
144 let len = self.pointer.len() / N;
145 let (multiple_of_n, remainder) = self.split_at(len * N);
146 let array_slice = unsafe { multiple_of_n.as_chunks_unchecked() };
149 (array_slice, remainder)
150 }
151
152 pub unsafe fn as_chunks_unchecked<const N: usize>(self) -> AbstractPtr<'a, M, [[T; N]], A>
153 where
154 A: Access,
155 {
156 debug_assert_ne!(N, 0);
157 debug_assert_eq!(self.pointer.len() % N, 0);
158 let new_len = self.pointer.len() / N;
159 let pointer = NonNull::new(ptr::slice_from_raw_parts_mut(
162 non_null_slice_as_mut_ptr(self.pointer).cast(),
163 new_len,
164 ))
165 .unwrap();
166 unsafe { AbstractPtr::new_generic(pointer) }
167 }
168}
169
170impl<M, A> AbstractPtr<'_, M, [u8], A> {
171 pub fn fill(self, value: u8)
172 where
173 M: BulkOps<u8>,
174 A: Writable,
175 {
176 unsafe {
177 M::memset(
178 non_null_slice_as_mut_ptr(self.pointer),
179 value,
180 non_null_slice_len(self.pointer),
181 );
182 }
183 }
184}
185
186impl<'a, M, T, A, const N: usize> AbstractPtr<'a, M, [T; N], A> {
188 pub fn as_slice(self) -> AbstractPtr<'a, M, [T], A>
189 where
190 A: Access,
191 {
192 unsafe {
193 self.map(|array| {
194 NonNull::new(ptr::slice_from_raw_parts_mut(array.as_ptr() as *mut T, N)).unwrap()
195 })
196 }
197 }
198}