i think the memory model is fixed now? at least until arrays....
This commit is contained in:
@@ -105,12 +105,16 @@ fn define_enum(names: &Names, name: &witx::Id, e: &witx::EnumDatatype) -> TokenS
|
||||
|
||||
impl ::memory::GuestTypeCopy for #ident {}
|
||||
impl ::memory::GuestTypeClone for #ident {
|
||||
fn from_guest(location: &::memory::GuestPtr<#ident>) -> Result<#ident, ::memory::GuestError> {
|
||||
fn read_from_guest(location: &::memory::GuestPtr<#ident>) -> Result<#ident, ::memory::GuestError> {
|
||||
use ::std::convert::TryFrom;
|
||||
let raw: #repr = unsafe { (location.as_raw() as *const #repr).read() };
|
||||
let val = #ident::try_from(raw)?;
|
||||
Ok(val)
|
||||
}
|
||||
fn write_to_guest(&self, location: &::memory::GuestPtrMut<#ident>) {
|
||||
let val: #repr = #repr::from(*self);
|
||||
unsafe { (location.as_raw() as *mut #repr).write(val) };
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use crate::{GuestError, GuestPtr};
|
||||
use crate::{GuestError, GuestPtr, GuestPtrMut};
|
||||
|
||||
pub trait GuestType: Sized {
|
||||
// These are morally the same as Rust ::std::mem::size_of / align_of, but they return
|
||||
@@ -12,11 +12,12 @@ pub trait GuestType: Sized {
|
||||
|
||||
pub trait GuestTypeCopy: GuestType + Copy {}
|
||||
pub trait GuestTypeClone: GuestType + Clone {
|
||||
fn from_guest<'a>(location: &GuestPtr<'a, Self>) -> Result<Self, GuestError>;
|
||||
fn read_from_guest<'a>(location: &GuestPtr<'a, Self>) -> Result<Self, GuestError>;
|
||||
fn write_to_guest<'a>(&self, location: &GuestPtrMut<'a, Self>);
|
||||
}
|
||||
pub trait GuestTypeRef<'a>: GuestType {
|
||||
type Ref;
|
||||
fn from_guest(location: &GuestPtr<'a, Self>) -> Result<Self::Ref, GuestError>;
|
||||
pub trait GuestTypePtr<'a>: GuestType {
|
||||
fn read_from_guest(location: &GuestPtr<'a, Self>) -> Result<Self, GuestError>;
|
||||
fn write_to_guest(&self, location: &GuestPtrMut<'a, Self>);
|
||||
}
|
||||
|
||||
macro_rules! builtin_type {
|
||||
|
||||
@@ -5,6 +5,6 @@ mod memory;
|
||||
mod region;
|
||||
|
||||
pub use error::GuestError;
|
||||
pub use guest_type::{GuestErrorType, GuestType, GuestTypeClone, GuestTypeCopy, GuestTypeRef};
|
||||
pub use guest_type::{GuestErrorType, GuestType, GuestTypeClone, GuestTypeCopy, GuestTypePtr};
|
||||
pub use memory::{GuestMemory, GuestPtr, GuestPtrMut, GuestRef, GuestRefMut};
|
||||
pub use region::Region;
|
||||
|
||||
@@ -3,7 +3,7 @@ use std::marker::PhantomData;
|
||||
use std::rc::Rc;
|
||||
|
||||
use crate::borrow::{BorrowHandle, GuestBorrows};
|
||||
use crate::{GuestError, GuestType, GuestTypeCopy, GuestTypeRef, Region};
|
||||
use crate::{GuestError, GuestType, GuestTypeClone, GuestTypeCopy, GuestTypePtr, Region};
|
||||
|
||||
pub struct GuestMemory<'a> {
|
||||
ptr: *mut u8,
|
||||
@@ -67,6 +67,9 @@ impl<'a, T: GuestType> GuestPtr<'a, T> {
|
||||
pub fn as_raw(&self) -> *const u8 {
|
||||
(self.mem.ptr as usize + self.region.start as usize) as *const u8
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T: GuestTypeCopy> GuestPtr<'a, T> {
|
||||
pub fn as_ref(&self) -> Result<GuestRef<'a, T>, GuestError> {
|
||||
T::validate(&self)?;
|
||||
let handle = {
|
||||
@@ -84,6 +87,18 @@ impl<'a, T: GuestType> GuestPtr<'a, T> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T: GuestTypeClone> GuestPtr<'a, T> {
|
||||
pub fn clone_from_guest(&self) -> Result<T, GuestError> {
|
||||
T::read_from_guest(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T: GuestTypePtr<'a>> GuestPtr<'a, T> {
|
||||
pub fn read_ptr_from_guest(&self) -> Result<T, GuestError> {
|
||||
T::read_from_guest(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T> GuestType for GuestPtr<'a, T>
|
||||
where
|
||||
T: GuestType,
|
||||
@@ -106,17 +121,24 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T> GuestTypeRef<'a> for GuestPtr<'a, T>
|
||||
// Operations for reading and writing Ptrs to memory:
|
||||
impl<'a, T> GuestTypePtr<'a> for GuestPtr<'a, T>
|
||||
where
|
||||
T: GuestType,
|
||||
{
|
||||
type Ref = GuestRef<'a, T>;
|
||||
fn from_guest(location: &GuestPtr<'a, Self>) -> Result<Self::Ref, GuestError> {
|
||||
fn read_from_guest(location: &GuestPtr<'a, Self>) -> Result<Self, GuestError> {
|
||||
// location is guaranteed to be in GuestMemory and aligned to 4
|
||||
let raw_ptr: u32 = unsafe { *(location.as_raw() as *const u32) };
|
||||
// GuestMemory can validate that the raw pointer contents are legal for T:
|
||||
let guest_ptr: GuestPtr<'a, T> = location.mem.ptr(raw_ptr)?;
|
||||
Ok(guest_ptr.as_ref()?)
|
||||
Ok(guest_ptr)
|
||||
}
|
||||
fn write_to_guest(&self, location: &GuestPtrMut<'a, Self>) {
|
||||
// location is guaranteed to be in GuestMemory and aligned to 4
|
||||
unsafe {
|
||||
let raw_ptr: *mut u32 = location.as_raw() as *mut u32;
|
||||
raw_ptr.write(self.region.start);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -139,7 +161,9 @@ impl<'a, T: GuestType> GuestPtrMut<'a, T> {
|
||||
pub fn as_raw(&self) -> *const u8 {
|
||||
self.as_immut().as_raw()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T: GuestTypeCopy> GuestPtrMut<'a, T> {
|
||||
pub fn as_ref(&self) -> Result<GuestRef<'a, T>, GuestError> {
|
||||
self.as_immut().as_ref()
|
||||
}
|
||||
@@ -161,6 +185,25 @@ impl<'a, T: GuestType> GuestPtrMut<'a, T> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T: GuestTypePtr<'a>> GuestPtrMut<'a, T> {
|
||||
pub fn read_ptr_from_guest(&self) -> Result<T, GuestError> {
|
||||
T::read_from_guest(&self.as_immut())
|
||||
}
|
||||
pub fn write_ptr_to_guest(&self, ptr: &T) {
|
||||
T::write_to_guest(ptr, &self);
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T: GuestTypeClone> GuestPtrMut<'a, T> {
|
||||
pub fn clone_from_guest(&self) -> Result<T, GuestError> {
|
||||
T::read_from_guest(&self.as_immut())
|
||||
}
|
||||
|
||||
pub fn clone_to_guest(&self, val: &T) {
|
||||
T::write_to_guest(val, &self)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T> GuestType for GuestPtrMut<'a, T>
|
||||
where
|
||||
T: GuestType,
|
||||
@@ -183,17 +226,24 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T> GuestTypeRef<'a> for GuestPtrMut<'a, T>
|
||||
// Reading and writing GuestPtrMuts to memory:
|
||||
impl<'a, T> GuestTypePtr<'a> for GuestPtrMut<'a, T>
|
||||
where
|
||||
T: GuestType,
|
||||
{
|
||||
type Ref = GuestRefMut<'a, T>;
|
||||
fn from_guest(location: &GuestPtr<'a, Self>) -> Result<Self::Ref, GuestError> {
|
||||
fn read_from_guest(location: &GuestPtr<'a, Self>) -> Result<Self, GuestError> {
|
||||
// location is guaranteed to be in GuestMemory and aligned to 4
|
||||
let raw_ptr: u32 = unsafe { *(location.as_raw() as *const u32) };
|
||||
// GuestMemory can validate that the raw pointer contents are legal for T:
|
||||
let guest_ptr_mut: GuestPtrMut<'a, T> = location.mem.ptr_mut(raw_ptr)?;
|
||||
Ok(guest_ptr_mut.as_ref_mut()?)
|
||||
Ok(guest_ptr_mut)
|
||||
}
|
||||
fn write_to_guest(&self, location: &GuestPtrMut<'a, Self>) {
|
||||
// location is guaranteed to be in GuestMemory and aligned to 4
|
||||
unsafe {
|
||||
let raw_ptr: *mut u32 = location.as_raw() as *mut u32;
|
||||
raw_ptr.write(self.region.start);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -204,6 +254,16 @@ pub struct GuestRef<'a, T> {
|
||||
type_: PhantomData<T>,
|
||||
}
|
||||
|
||||
impl<'a, T> GuestRef<'a, T> {
|
||||
pub fn as_ptr(&self) -> GuestPtr<'a, T> {
|
||||
GuestPtr {
|
||||
mem: self.mem,
|
||||
region: self.region,
|
||||
type_: self.type_,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T> ::std::ops::Deref for GuestRef<'a, T>
|
||||
where
|
||||
T: GuestTypeCopy,
|
||||
@@ -218,20 +278,6 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T> GuestRef<'a, T>
|
||||
where
|
||||
T: GuestTypeRef<'a>,
|
||||
{
|
||||
pub fn from_guest(&self) -> Result<T::Ref, GuestError> {
|
||||
let ptr = GuestPtr {
|
||||
mem: self.mem,
|
||||
region: self.region,
|
||||
type_: self.type_,
|
||||
};
|
||||
GuestTypeRef::from_guest(&ptr)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T> Drop for GuestRef<'a, T> {
|
||||
fn drop(&mut self) {
|
||||
let mut borrows = self.mem.borrows.borrow_mut();
|
||||
@@ -246,6 +292,23 @@ pub struct GuestRefMut<'a, T> {
|
||||
type_: PhantomData<T>,
|
||||
}
|
||||
|
||||
impl<'a, T> GuestRefMut<'a, T> {
|
||||
pub fn as_ptr(&self) -> GuestPtr<'a, T> {
|
||||
GuestPtr {
|
||||
mem: self.mem,
|
||||
region: self.region,
|
||||
type_: self.type_,
|
||||
}
|
||||
}
|
||||
pub fn as_ptr_mut(&self) -> GuestPtrMut<'a, T> {
|
||||
GuestPtrMut {
|
||||
mem: self.mem,
|
||||
region: self.region,
|
||||
type_: self.type_,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T> ::std::ops::Deref for GuestRefMut<'a, T>
|
||||
where
|
||||
T: GuestTypeCopy,
|
||||
@@ -273,20 +336,6 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T> GuestRefMut<'a, T>
|
||||
where
|
||||
T: GuestTypeRef<'a>,
|
||||
{
|
||||
pub fn from_guest(&self) -> Result<T::Ref, GuestError> {
|
||||
let ptr = GuestPtr {
|
||||
mem: self.mem,
|
||||
region: self.region,
|
||||
type_: self.type_,
|
||||
};
|
||||
GuestTypeRef::from_guest(&ptr)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T> Drop for GuestRefMut<'a, T> {
|
||||
fn drop(&mut self) {
|
||||
let mut borrows = self.mem.borrows.borrow_mut();
|
||||
|
||||
10
src/lib.rs
10
src/lib.rs
@@ -36,22 +36,20 @@ pub mod test {
|
||||
*a_better_excuse_ref = a_lamer_excuse;
|
||||
|
||||
// Read ptr value from mutable ptr:
|
||||
let mut one_layer_down: ::memory::GuestRefMut<::memory::GuestPtr<types::Excuse>> =
|
||||
two_layers_of_excuses.as_ref_mut().map_err(|e| {
|
||||
let one_layer_down: ::memory::GuestPtr<types::Excuse> =
|
||||
two_layers_of_excuses.read_ptr_from_guest().map_err(|e| {
|
||||
eprintln!("one_layer_down error: {}", e);
|
||||
types::Errno::InvalidArg
|
||||
})?;
|
||||
|
||||
// Read enum value from that ptr:
|
||||
let two_layers_down: ::memory::GuestRef<types::Excuse> =
|
||||
one_layer_down.from_guest().map_err(|e| {
|
||||
let two_layers_down: types::Excuse = *one_layer_down.as_ref().map_err(|e| {
|
||||
eprintln!("two_layers_down error: {}", e);
|
||||
types::Errno::InvalidArg
|
||||
})?;
|
||||
|
||||
// Write ptr value to mutable ptr:
|
||||
// FIXME this is still impossible...
|
||||
// two_layers_of_excuses.write_guest(&a_better_excuse_by_reference)
|
||||
two_layers_of_excuses.write_ptr_to_guest(&a_better_excuse_by_reference.as_immut());
|
||||
|
||||
println!(
|
||||
"BAZ: excuse: {:?}, better excuse: {:?}, lamer excuse: {:?}, two layers down: {:?}",
|
||||
|
||||
Reference in New Issue
Block a user