diff --git a/crates/generate/src/types.rs b/crates/generate/src/types.rs index 4ee337bbc0..a49995b260 100644 --- a/crates/generate/src/types.rs +++ b/crates/generate/src/types.rs @@ -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) }; + } } } diff --git a/crates/memory/src/guest_type.rs b/crates/memory/src/guest_type.rs index 2b4b3f387a..1d71e72477 100644 --- a/crates/memory/src/guest_type.rs +++ b/crates/memory/src/guest_type.rs @@ -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; + fn read_from_guest<'a>(location: &GuestPtr<'a, Self>) -> Result; + 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; +pub trait GuestTypePtr<'a>: GuestType { + fn read_from_guest(location: &GuestPtr<'a, Self>) -> Result; + fn write_to_guest(&self, location: &GuestPtrMut<'a, Self>); } macro_rules! builtin_type { diff --git a/crates/memory/src/lib.rs b/crates/memory/src/lib.rs index 5aceb413b3..6f2b17ecfc 100644 --- a/crates/memory/src/lib.rs +++ b/crates/memory/src/lib.rs @@ -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; diff --git a/crates/memory/src/memory.rs b/crates/memory/src/memory.rs index 3b6897b8cd..c24a272d6c 100644 --- a/crates/memory/src/memory.rs +++ b/crates/memory/src/memory.rs @@ -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, 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::read_from_guest(self) + } +} + +impl<'a, T: GuestTypePtr<'a>> GuestPtr<'a, T> { + pub fn read_ptr_from_guest(&self) -> Result { + 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 { + fn read_from_guest(location: &GuestPtr<'a, Self>) -> Result { // 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, 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::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::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 { + fn read_from_guest(location: &GuestPtr<'a, Self>) -> Result { // 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, } +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 { - 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, } +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 { - 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(); diff --git a/src/lib.rs b/src/lib.rs index 6fa441546d..b907f0cb1e 100644 --- a/src/lib.rs +++ b/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> = - two_layers_of_excuses.as_ref_mut().map_err(|e| { + let one_layer_down: ::memory::GuestPtr = + 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 = - one_layer_down.from_guest().map_err(|e| { - eprintln!("two_layers_down error: {}", e); - types::Errno::InvalidArg - })?; + 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: {:?}",