kernel_api/ptr/
user_local.rs1use alloc::boxed::Box;
2use core::cmp::min;
3use core::fmt;
4use core::fmt::Formatter;
5use core::mem::MaybeUninit;
6use crate::memory::VirtualAddress;
7use crate::ptr::{impls, PointerError};
8
9#[derive(Clone, Copy)]
10pub struct LocalUser<T> {
11 pub(super) ptr: T,
12}
13
14impl<T> !Send for LocalUser<T> {}
16impl<T> !Sync for LocalUser<T> {}
17
18impl<T: fmt::Pointer> fmt::Pointer for LocalUser<T> {
19 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
20 fmt::Pointer::fmt(&self.ptr, f)
21 }
22}
23
24impl<T: fmt::Pointer> fmt::Debug for LocalUser<T> {
25 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
26 fmt::Pointer::fmt(&self.ptr, f)
27 }
28}
29
30impl<T: ?Sized> LocalUser<*const T> {
31 pub unsafe fn new(addr: usize) -> Self where T: Sized {
42 Self {
43 ptr: addr as *const T,
44 }
45 }
46
47 pub const fn is_null(&self) -> bool {
49 self.ptr.is_null()
50 }
51
52 pub const unsafe fn offset(self, count: isize) -> Self where T: Sized {
61 Self {
62 ptr: unsafe { self.ptr.offset(count) },
64 }
65 }
66
67 pub const unsafe fn byte_offset(self, count: isize) -> Self {
73 Self {
74 ptr: unsafe { self.ptr.byte_offset(count) },
76 }
77 }
78
79 pub const unsafe fn add(self, count: usize) -> Self where T: Sized {
88 Self {
89 ptr: unsafe { self.ptr.add(count) },
91 }
92 }
93
94 pub const unsafe fn byte_add(self, count: usize) -> Self {
100 Self {
101 ptr: unsafe { self.ptr.byte_add(count) },
103 }
104 }
105
106 pub const unsafe fn sub(self, count: usize) -> Self where T: Sized {
115 Self {
116 ptr: unsafe { self.ptr.sub(count) },
118 }
119 }
120
121 pub const unsafe fn byte_sub(self, count: usize) -> Self {
127 Self {
128 ptr: unsafe { self.ptr.byte_sub(count) },
130 }
131 }
132
133 pub fn read(self) -> Result<T, PointerError> where T: Sized + Copy {
140 match size_of::<T>() {
141 1 => unsafe {
142 impls::checked_read_1(self.ptr.cast())
143 .map(|val| (&val as *const MaybeUninit<u8>).cast::<T>().read())
144 },
145 2 => unsafe {
146 impls::checked_read_2(self.ptr.cast())
147 .map(|val| (&val as *const MaybeUninit<u16>).cast::<T>().read())
148 },
149 4 => unsafe {
150 impls::checked_read_4(self.ptr.cast())
151 .map(|val| (&val as *const MaybeUninit<u32>).cast::<T>().read())
152 },
153 #[cfg(target_pointer_width = "64")] 8 => unsafe {
154 impls::checked_read_8(self.ptr.cast())
155 .map(|val| (&val as *const MaybeUninit<u64>).cast::<T>().read())
156 },
157 size => {
158 let mut buf = MaybeUninit::<T>::uninit();
159 impls::checked_memcpy(self.ptr.cast(), buf.as_mut_ptr().cast(), size)
160 .map(|_| unsafe { buf.assume_init() })
161 }
162 }.ok_or(PointerError {})
163 }
164
165 pub const unsafe fn cast<U>(self) -> LocalUser<*const U> {
177 LocalUser {
178 ptr: self.ptr.cast(),
179 }
180 }
181
182 pub const fn cast_mut(self) -> LocalUser<*mut T> {
184 LocalUser {
185 ptr: self.ptr.cast_mut(),
186 }
187 }
188
189 pub fn is_aligned_to(self, align: usize) -> bool {
190 self.ptr.is_aligned_to(align)
191 }
192
193 pub fn addr(self) -> VirtualAddress {
194 VirtualAddress::new(self.ptr.addr())
195 }
196
197 pub fn align_offset(self, align: usize) -> usize where T: Sized {
198 self.ptr.align_offset(align)
199 }
200}
201
202impl<T: ?Sized> LocalUser<*mut T> {
203 pub fn new(addr: usize) -> Self where T: Sized {
205 Self {
206 ptr: addr as *mut T,
207 }
208 }
209
210 pub const fn is_null(&self) -> bool {
212 self.ptr.is_null()
213 }
214
215 pub const unsafe fn offset(self, count: isize) -> Self where T: Sized {
224 Self {
225 ptr: self.ptr.offset(count),
226 }
227 }
228
229 pub const unsafe fn byte_offset(self, count: isize) -> Self {
235 Self {
236 ptr: self.ptr.byte_offset(count),
237 }
238 }
239
240 pub const unsafe fn add(self, count: usize) -> Self where T: Sized {
249 Self {
250 ptr: self.ptr.add(count),
251 }
252 }
253
254 pub const unsafe fn byte_add(self, count: usize) -> Self {
260 Self {
261 ptr: self.ptr.byte_add(count),
262 }
263 }
264
265 pub const unsafe fn sub(self, count: usize) -> Self where T: Sized {
274 Self {
275 ptr: self.ptr.sub(count),
276 }
277 }
278
279 pub const unsafe fn byte_sub(self, count: usize) -> Self {
285 Self {
286 ptr: self.ptr.byte_sub(count),
287 }
288 }
289
290 pub fn write(self, value: T) -> Result<(), PointerError> where T: Sized {
296 match size_of::<T>() {
297 1 => unsafe {
298 impls::checked_write_1(self.ptr.cast(), (&value as *const T).cast::<MaybeUninit<u8>>().read())
299 },
300 2 => unsafe {
301 impls::checked_write_2(self.ptr.cast(), (&value as *const T).cast::<MaybeUninit<u16>>().read())
302 },
303 4 => unsafe {
304 impls::checked_write_4(self.ptr.cast(), (&value as *const T).cast::<MaybeUninit<u32>>().read())
305 },
306 #[cfg(target_pointer_width = "64")] 8 => unsafe {
307 impls::checked_write_8(self.ptr.cast(), (&value as *const T).cast::<MaybeUninit<u64>>().read())
308 },
309 size => {
310 impls::checked_memcpy((&value as *const T).cast(), self.ptr.cast(), size)
311 }
312 }.ok_or(PointerError {})
313 }
314
315 pub const fn cast<U>(self) -> LocalUser<*mut U> {
317 LocalUser {
318 ptr: self.ptr.cast(),
319 }
320 }
321
322 pub const unsafe fn cast_const(self) -> LocalUser<*const T> {
333 LocalUser {
334 ptr: self.ptr.cast_const(),
335 }
336 }
337
338 pub fn is_aligned_to(self, align: usize) -> bool {
339 self.ptr.is_aligned_to(align)
340 }
341
342 pub fn addr(self) -> VirtualAddress {
343 VirtualAddress::new(self.ptr.addr())
344 }
345
346 pub fn align_offset(self, align: usize) -> usize where T: Sized {
347 self.ptr.align_offset(align)
348 }
349}
350
351impl<T> LocalUser<*const [T]> {
352 pub const fn len(self) -> usize { self.ptr.len() }
353
354 pub const fn is_empty(self) -> bool { self.ptr.is_empty() }
355
356 pub const fn as_ptr(self) -> LocalUser<*const T> {
357 LocalUser {
358 ptr: self.ptr.as_ptr(),
359 }
360 }
361
362 pub fn read_to_box(self) -> Result<Box<[T]>, PointerError> {
363 let mut buf = Box::new_uninit_slice(self.len());
364 let size = self.read_to_buffer(&mut buf)?;
365 assert_eq!(size, buf.len(), "box should be big enough");
366 Ok(unsafe { buf.assume_init() })
367 }
368
369 pub fn read_to_buffer(self, buffer: &mut [MaybeUninit<T>]) -> Result<usize, PointerError> {
370 let count = min(buffer.len(), self.len());
371
372 impls::checked_memcpy(
373 self.ptr.cast(),
374 buffer.as_mut_ptr().cast(),
375 size_of::<T>() * count
376 ).ok_or(PointerError {})?;
377
378 Ok(count)
379 }
380}
381
382impl<T> LocalUser<*mut [T]> {
383 pub const fn len(self) -> usize { self.ptr.len() }
384
385 pub const fn is_empty(self) -> bool { self.ptr.is_empty() }
386
387 pub const fn as_mut_ptr(self) -> LocalUser<*mut T> {
388 LocalUser {
389 ptr: self.ptr.as_mut_ptr(),
390 }
391 }
392
393 pub fn write_from_slice(self, slice: &[T]) -> Result<usize, PointerError> {
394 let count = min(slice.len(), self.len());
395
396 impls::checked_memcpy(
397 slice.as_ptr().cast(),
398 self.ptr.cast(),
399 size_of::<T>() * count
400 ).ok_or(PointerError {})?;
401
402 Ok(count)
403 }
404}
405
406pub unsafe fn local_slice_from_raw_parts<T>(data: LocalUser<*const T>, len: usize) -> LocalUser<*const [T]> {
407 let ptr = core::ptr::slice_from_raw_parts(data.ptr, len);
408 LocalUser {
409 ptr,
410 }
411}
412
413pub fn local_slice_from_raw_parts_mut<T>(data: LocalUser<*mut T>, len: usize) -> LocalUser<*mut [T]> {
414 let ptr = core::ptr::slice_from_raw_parts_mut(data.ptr, len);
415 LocalUser {
416 ptr,
417 }
418}