use core::{mem::MaybeUninit, ptr::NonNull, slice};
use bytemuck::AnyBitPattern;
use crate::{VmResult, vm_read_slice, vm_write_slice};
pub trait VmPtr: Copy {
type Target;
#[doc(hidden)]
fn as_ptr(self) -> *const Self::Target;
fn nullable(self) -> Option<Self> {
if self.as_ptr().is_null() {
None
} else {
Some(self)
}
}
fn vm_read_uninit(self) -> VmResult<MaybeUninit<Self::Target>> {
let mut uninit = MaybeUninit::<Self::Target>::uninit();
vm_read_slice(self.as_ptr(), slice::from_mut(&mut uninit))?;
Ok(uninit)
}
fn vm_read(self) -> VmResult<Self::Target>
where
Self::Target: AnyBitPattern,
{
let uninit = self.vm_read_uninit()?;
Ok(unsafe { uninit.assume_init() })
}
}
impl<T> VmPtr for *const T {
type Target = T;
fn as_ptr(self) -> *const T {
self
}
}
impl<T> VmPtr for *mut T {
type Target = T;
fn as_ptr(self) -> *const T {
self
}
}
impl<T> VmPtr for NonNull<T> {
type Target = T;
fn as_ptr(self) -> *const T {
self.as_ptr()
}
}
pub trait VmMutPtr: VmPtr {
fn vm_write(self, value: Self::Target) -> VmResult {
vm_write_slice(self.as_ptr().cast_mut(), slice::from_ref(&value))
}
}
impl<T> VmMutPtr for *mut T {}
impl<T> VmMutPtr for NonNull<T> {}