#![no_std]
#![feature(maybe_uninit_as_bytes)]
#![warn(missing_docs)]
use core::{mem::MaybeUninit, slice};
use ax_errno::AxError;
use extern_trait::extern_trait;
#[derive(Debug, PartialEq, Clone, Copy)]
pub enum VmError {
BadAddress,
AccessDenied,
#[cfg(feature = "alloc")]
TooLong,
}
impl From<VmError> for AxError {
fn from(err: VmError) -> Self {
match err {
VmError::BadAddress | VmError::AccessDenied => AxError::BadAddress,
#[cfg(feature = "alloc")]
VmError::TooLong => AxError::NameTooLong,
}
}
}
pub type VmResult<T = ()> = Result<T, VmError>;
#[extern_trait(VmImpl)]
pub unsafe trait VmIo {
fn new() -> Self;
fn read(&mut self, start: usize, buf: &mut [MaybeUninit<u8>]) -> VmResult;
fn write(&mut self, start: usize, buf: &[u8]) -> VmResult;
}
pub fn vm_read_slice<T>(ptr: *const T, buf: &mut [MaybeUninit<T>]) -> VmResult {
if !ptr.is_aligned() {
return Err(VmError::BadAddress);
}
VmImpl::new().read(ptr.addr(), buf.as_bytes_mut())
}
pub fn vm_write_slice<T>(ptr: *mut T, buf: &[T]) -> VmResult {
if !ptr.is_aligned() {
return Err(VmError::BadAddress);
}
let bytes = unsafe { slice::from_raw_parts(buf.as_ptr().cast::<u8>(), size_of_val(buf)) };
VmImpl::new().write(ptr.addr(), bytes)
}
mod thin;
pub use thin::{VmMutPtr, VmPtr};
#[cfg(feature = "alloc")]
mod alloc;
#[cfg(feature = "alloc")]
pub use alloc::{vm_load, vm_load_any, vm_load_until_nul};