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::GuestTypeCopy for #ident {}
|
||||||
impl ::memory::GuestTypeClone 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;
|
use ::std::convert::TryFrom;
|
||||||
let raw: #repr = unsafe { (location.as_raw() as *const #repr).read() };
|
let raw: #repr = unsafe { (location.as_raw() as *const #repr).read() };
|
||||||
let val = #ident::try_from(raw)?;
|
let val = #ident::try_from(raw)?;
|
||||||
Ok(val)
|
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 {
|
pub trait GuestType: Sized {
|
||||||
// These are morally the same as Rust ::std::mem::size_of / align_of, but they return
|
// 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 GuestTypeCopy: GuestType + Copy {}
|
||||||
pub trait GuestTypeClone: GuestType + Clone {
|
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 {
|
pub trait GuestTypePtr<'a>: GuestType {
|
||||||
type Ref;
|
fn read_from_guest(location: &GuestPtr<'a, Self>) -> Result<Self, GuestError>;
|
||||||
fn from_guest(location: &GuestPtr<'a, Self>) -> Result<Self::Ref, GuestError>;
|
fn write_to_guest(&self, location: &GuestPtrMut<'a, Self>);
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! builtin_type {
|
macro_rules! builtin_type {
|
||||||
|
|||||||
@@ -5,6 +5,6 @@ mod memory;
|
|||||||
mod region;
|
mod region;
|
||||||
|
|
||||||
pub use error::GuestError;
|
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 memory::{GuestMemory, GuestPtr, GuestPtrMut, GuestRef, GuestRefMut};
|
||||||
pub use region::Region;
|
pub use region::Region;
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ use std::marker::PhantomData;
|
|||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
use crate::borrow::{BorrowHandle, GuestBorrows};
|
use crate::borrow::{BorrowHandle, GuestBorrows};
|
||||||
use crate::{GuestError, GuestType, GuestTypeCopy, GuestTypeRef, Region};
|
use crate::{GuestError, GuestType, GuestTypeClone, GuestTypeCopy, GuestTypePtr, Region};
|
||||||
|
|
||||||
pub struct GuestMemory<'a> {
|
pub struct GuestMemory<'a> {
|
||||||
ptr: *mut u8,
|
ptr: *mut u8,
|
||||||
@@ -67,6 +67,9 @@ impl<'a, T: GuestType> GuestPtr<'a, T> {
|
|||||||
pub fn as_raw(&self) -> *const u8 {
|
pub fn as_raw(&self) -> *const u8 {
|
||||||
(self.mem.ptr as usize + self.region.start as usize) as *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> {
|
pub fn as_ref(&self) -> Result<GuestRef<'a, T>, GuestError> {
|
||||||
T::validate(&self)?;
|
T::validate(&self)?;
|
||||||
let handle = {
|
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>
|
impl<'a, T> GuestType for GuestPtr<'a, T>
|
||||||
where
|
where
|
||||||
T: GuestType,
|
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
|
where
|
||||||
T: GuestType,
|
T: GuestType,
|
||||||
{
|
{
|
||||||
type Ref = GuestRef<'a, T>;
|
fn read_from_guest(location: &GuestPtr<'a, Self>) -> Result<Self, GuestError> {
|
||||||
fn from_guest(location: &GuestPtr<'a, Self>) -> Result<Self::Ref, GuestError> {
|
|
||||||
// location is guaranteed to be in GuestMemory and aligned to 4
|
// location is guaranteed to be in GuestMemory and aligned to 4
|
||||||
let raw_ptr: u32 = unsafe { *(location.as_raw() as *const u32) };
|
let raw_ptr: u32 = unsafe { *(location.as_raw() as *const u32) };
|
||||||
// GuestMemory can validate that the raw pointer contents are legal for T:
|
// GuestMemory can validate that the raw pointer contents are legal for T:
|
||||||
let guest_ptr: GuestPtr<'a, T> = location.mem.ptr(raw_ptr)?;
|
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 {
|
pub fn as_raw(&self) -> *const u8 {
|
||||||
self.as_immut().as_raw()
|
self.as_immut().as_raw()
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, T: GuestTypeCopy> GuestPtrMut<'a, T> {
|
||||||
pub fn as_ref(&self) -> Result<GuestRef<'a, T>, GuestError> {
|
pub fn as_ref(&self) -> Result<GuestRef<'a, T>, GuestError> {
|
||||||
self.as_immut().as_ref()
|
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>
|
impl<'a, T> GuestType for GuestPtrMut<'a, T>
|
||||||
where
|
where
|
||||||
T: GuestType,
|
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
|
where
|
||||||
T: GuestType,
|
T: GuestType,
|
||||||
{
|
{
|
||||||
type Ref = GuestRefMut<'a, T>;
|
fn read_from_guest(location: &GuestPtr<'a, Self>) -> Result<Self, GuestError> {
|
||||||
fn from_guest(location: &GuestPtr<'a, Self>) -> Result<Self::Ref, GuestError> {
|
|
||||||
// location is guaranteed to be in GuestMemory and aligned to 4
|
// location is guaranteed to be in GuestMemory and aligned to 4
|
||||||
let raw_ptr: u32 = unsafe { *(location.as_raw() as *const u32) };
|
let raw_ptr: u32 = unsafe { *(location.as_raw() as *const u32) };
|
||||||
// GuestMemory can validate that the raw pointer contents are legal for T:
|
// 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)?;
|
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>,
|
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>
|
impl<'a, T> ::std::ops::Deref for GuestRef<'a, T>
|
||||||
where
|
where
|
||||||
T: GuestTypeCopy,
|
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> {
|
impl<'a, T> Drop for GuestRef<'a, T> {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
let mut borrows = self.mem.borrows.borrow_mut();
|
let mut borrows = self.mem.borrows.borrow_mut();
|
||||||
@@ -246,6 +292,23 @@ pub struct GuestRefMut<'a, T> {
|
|||||||
type_: PhantomData<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>
|
impl<'a, T> ::std::ops::Deref for GuestRefMut<'a, T>
|
||||||
where
|
where
|
||||||
T: GuestTypeCopy,
|
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> {
|
impl<'a, T> Drop for GuestRefMut<'a, T> {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
let mut borrows = self.mem.borrows.borrow_mut();
|
let mut borrows = self.mem.borrows.borrow_mut();
|
||||||
|
|||||||
16
src/lib.rs
16
src/lib.rs
@@ -36,22 +36,20 @@ pub mod test {
|
|||||||
*a_better_excuse_ref = a_lamer_excuse;
|
*a_better_excuse_ref = a_lamer_excuse;
|
||||||
|
|
||||||
// Read ptr value from mutable ptr:
|
// Read ptr value from mutable ptr:
|
||||||
let mut one_layer_down: ::memory::GuestRefMut<::memory::GuestPtr<types::Excuse>> =
|
let one_layer_down: ::memory::GuestPtr<types::Excuse> =
|
||||||
two_layers_of_excuses.as_ref_mut().map_err(|e| {
|
two_layers_of_excuses.read_ptr_from_guest().map_err(|e| {
|
||||||
eprintln!("one_layer_down error: {}", e);
|
eprintln!("one_layer_down error: {}", e);
|
||||||
types::Errno::InvalidArg
|
types::Errno::InvalidArg
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
// Read enum value from that ptr:
|
// Read enum value from that ptr:
|
||||||
let two_layers_down: ::memory::GuestRef<types::Excuse> =
|
let two_layers_down: types::Excuse = *one_layer_down.as_ref().map_err(|e| {
|
||||||
one_layer_down.from_guest().map_err(|e| {
|
eprintln!("two_layers_down error: {}", e);
|
||||||
eprintln!("two_layers_down error: {}", e);
|
types::Errno::InvalidArg
|
||||||
types::Errno::InvalidArg
|
})?;
|
||||||
})?;
|
|
||||||
|
|
||||||
// Write ptr value to mutable ptr:
|
// Write ptr value to mutable ptr:
|
||||||
// FIXME this is still impossible...
|
two_layers_of_excuses.write_ptr_to_guest(&a_better_excuse_by_reference.as_immut());
|
||||||
// two_layers_of_excuses.write_guest(&a_better_excuse_by_reference)
|
|
||||||
|
|
||||||
println!(
|
println!(
|
||||||
"BAZ: excuse: {:?}, better excuse: {:?}, lamer excuse: {:?}, two layers down: {:?}",
|
"BAZ: excuse: {:?}, better excuse: {:?}, lamer excuse: {:?}, two layers down: {:?}",
|
||||||
|
|||||||
Reference in New Issue
Block a user