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)]
22pub struct LocalUser<T> {
23 pub(super) ptr: T,
24}
25
26impl<T> !Send for LocalUser<T> {}
28impl<T> !Sync for LocalUser<T> {}
29
30impl<T: fmt::Pointer> fmt::Pointer for LocalUser<T> {
31 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
32 fmt::Pointer::fmt(&self.ptr, f)
33 }
34}
35
36impl<T: fmt::Pointer> fmt::Debug for LocalUser<T> {
37 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
38 fmt::Pointer::fmt(&self.ptr, f)
39 }
40}
41
42impl<T: ?Sized> LocalUser<*const T> {
43 pub unsafe fn new(addr: usize) -> Self where T: Sized {
54 Self {
55 ptr: addr as *const T,
56 }
57 }
58
59 pub const fn is_null(&self) -> bool {
61 self.ptr.is_null()
62 }
63
64 pub const unsafe fn offset(self, count: isize) -> Self where T: Sized {
73 Self {
74 ptr: unsafe { self.ptr.offset(count) },
76 }
77 }
78
79 pub const unsafe fn byte_offset(self, count: isize) -> Self {
85 Self {
86 ptr: unsafe { self.ptr.byte_offset(count) },
88 }
89 }
90
91 pub const unsafe fn add(self, count: usize) -> Self where T: Sized {
100 Self {
101 ptr: unsafe { self.ptr.add(count) },
103 }
104 }
105
106 pub const unsafe fn byte_add(self, count: usize) -> Self {
112 Self {
113 ptr: unsafe { self.ptr.byte_add(count) },
115 }
116 }
117
118 pub const unsafe fn sub(self, count: usize) -> Self where T: Sized {
127 Self {
128 ptr: unsafe { self.ptr.sub(count) },
130 }
131 }
132
133 pub const unsafe fn byte_sub(self, count: usize) -> Self {
139 Self {
140 ptr: unsafe { self.ptr.byte_sub(count) },
142 }
143 }
144
145 pub fn read(self) -> Result<T, PointerError> where T: Sized + Copy {
152 match size_of::<T>() {
153 1 => unsafe {
154 impls::checked_read_1(self.ptr.cast())
155 .map(|val| (&val as *const MaybeUninit<u8>).cast::<T>().read())
156 },
157 2 => unsafe {
158 impls::checked_read_2(self.ptr.cast())
159 .map(|val| (&val as *const MaybeUninit<u16>).cast::<T>().read())
160 },
161 4 => unsafe {
162 impls::checked_read_4(self.ptr.cast())
163 .map(|val| (&val as *const MaybeUninit<u32>).cast::<T>().read())
164 },
165 #[cfg(target_pointer_width = "64")] 8 => unsafe {
166 impls::checked_read_8(self.ptr.cast())
167 .map(|val| (&val as *const MaybeUninit<u64>).cast::<T>().read())
168 },
169 size => {
170 let mut buf = MaybeUninit::<T>::uninit();
171 impls::checked_memcpy(self.ptr.cast(), buf.as_mut_ptr().cast(), size)
172 .map(|_| unsafe { buf.assume_init() })
173 }
174 }.ok_or(PointerError {})
175 }
176
177 pub const unsafe fn cast<U>(self) -> LocalUser<*const U> {
189 LocalUser {
190 ptr: self.ptr.cast(),
191 }
192 }
193
194 pub const fn cast_mut(self) -> LocalUser<*mut T> {
196 LocalUser {
197 ptr: self.ptr.cast_mut(),
198 }
199 }
200
201 pub fn is_aligned_to(self, align: usize) -> bool {
202 self.ptr.is_aligned_to(align)
203 }
204
205 pub fn addr(self) -> VirtualAddress {
206 VirtualAddress::new(self.ptr.addr())
207 }
208
209 pub fn align_offset(self, align: usize) -> usize where T: Sized {
210 self.ptr.align_offset(align)
211 }
212}
213
214impl<T: ?Sized> LocalUser<*mut T> {
215 pub fn new(addr: usize) -> Self where T: Sized {
217 Self {
218 ptr: addr as *mut T,
219 }
220 }
221
222 pub const fn is_null(&self) -> bool {
224 self.ptr.is_null()
225 }
226
227 pub const unsafe fn offset(self, count: isize) -> Self where T: Sized {
236 Self {
237 ptr: unsafe { self.ptr.offset(count) },
239 }
240 }
241
242 pub const unsafe fn byte_offset(self, count: isize) -> Self {
248 Self {
249 ptr: unsafe { self.ptr.byte_offset(count) },
251 }
252 }
253
254 pub const unsafe fn add(self, count: usize) -> Self where T: Sized {
263 Self {
264 ptr: unsafe { self.ptr.add(count) },
266 }
267 }
268
269 pub const unsafe fn byte_add(self, count: usize) -> Self {
275 Self {
276 ptr: unsafe { self.ptr.byte_add(count) },
278 }
279 }
280
281 pub const unsafe fn sub(self, count: usize) -> Self where T: Sized {
290 Self {
291 ptr: unsafe { self.ptr.sub(count) },
293 }
294 }
295
296 pub const unsafe fn byte_sub(self, count: usize) -> Self {
302 Self {
303 ptr: unsafe { self.ptr.byte_sub(count) },
305 }
306 }
307
308 pub fn write(self, value: T) -> Result<(), PointerError> where T: Sized {
314 match size_of::<T>() {
315 1 => unsafe {
316 impls::checked_write_1(self.ptr.cast(), (&value as *const T).cast::<MaybeUninit<u8>>().read())
317 },
318 2 => unsafe {
319 impls::checked_write_2(self.ptr.cast(), (&value as *const T).cast::<MaybeUninit<u16>>().read())
320 },
321 4 => unsafe {
322 impls::checked_write_4(self.ptr.cast(), (&value as *const T).cast::<MaybeUninit<u32>>().read())
323 },
324 #[cfg(target_pointer_width = "64")] 8 => unsafe {
325 impls::checked_write_8(self.ptr.cast(), (&value as *const T).cast::<MaybeUninit<u64>>().read())
326 },
327 size => {
328 impls::checked_memcpy((&value as *const T).cast(), self.ptr.cast(), size)
329 }
330 }.ok_or(PointerError {})
331 }
332
333 pub const fn cast<U>(self) -> LocalUser<*mut U> {
335 LocalUser {
336 ptr: self.ptr.cast(),
337 }
338 }
339
340 pub const unsafe fn cast_const(self) -> LocalUser<*const T> {
351 LocalUser {
352 ptr: self.ptr.cast_const(),
353 }
354 }
355
356 pub fn is_aligned_to(self, align: usize) -> bool {
357 self.ptr.is_aligned_to(align)
358 }
359
360 pub fn addr(self) -> VirtualAddress {
361 VirtualAddress::new(self.ptr.addr())
362 }
363
364 pub fn align_offset(self, align: usize) -> usize where T: Sized {
365 self.ptr.align_offset(align)
366 }
367}
368
369impl<T> LocalUser<*const [T]> {
370 pub const fn len(self) -> usize { self.ptr.len() }
371
372 pub const fn is_empty(self) -> bool { self.ptr.is_empty() }
373
374 pub const fn as_ptr(self) -> LocalUser<*const T> {
375 LocalUser {
376 ptr: self.ptr.as_ptr(),
377 }
378 }
379
380 pub fn read_to_box(self) -> Result<Box<[T]>, PointerError> {
381 let mut buf = Box::new_uninit_slice(self.len());
382 let size = self.read_to_buffer(&mut buf)?;
383 assert_eq!(size, buf.len(), "box should be big enough");
384 Ok(unsafe { buf.assume_init() })
385 }
386
387 pub fn read_to_buffer(self, buffer: &mut [MaybeUninit<T>]) -> Result<usize, PointerError> {
388 let count = min(buffer.len(), self.len());
389
390 impls::checked_memcpy(
391 self.ptr.cast(),
392 buffer.as_mut_ptr().cast(),
393 size_of::<T>() * count
394 ).ok_or(PointerError {})?;
395
396 Ok(count)
397 }
398}
399
400impl<T> LocalUser<*mut [T]> {
401 pub const fn len(self) -> usize { self.ptr.len() }
402
403 pub const fn is_empty(self) -> bool { self.ptr.is_empty() }
404
405 pub const fn as_mut_ptr(self) -> LocalUser<*mut T> {
406 LocalUser {
407 ptr: self.ptr.as_mut_ptr(),
408 }
409 }
410
411 pub fn write_from_slice(self, slice: &[T]) -> Result<usize, PointerError> {
412 let count = min(slice.len(), self.len());
413
414 impls::checked_memcpy(
415 slice.as_ptr().cast(),
416 self.ptr.cast(),
417 size_of::<T>() * count
418 ).ok_or(PointerError {})?;
419
420 Ok(count)
421 }
422}
423
424pub unsafe fn local_slice_from_raw_parts<T>(data: LocalUser<*const T>, len: usize) -> LocalUser<*const [T]> {
429 let ptr = core::ptr::slice_from_raw_parts(data.ptr, len);
430 LocalUser {
431 ptr,
432 }
433}
434
435pub fn local_slice_from_raw_parts_mut<T>(data: LocalUser<*mut T>, len: usize) -> LocalUser<*mut [T]> {
436 let ptr = core::ptr::slice_from_raw_parts_mut(data.ptr, len);
437 LocalUser {
438 ptr,
439 }
440}