From ec75f874eea6ff5450d8d4a98b9ed9b1d4e3bad5 Mon Sep 17 00:00:00 2001 From: Jakub Konka Date: Thu, 27 Feb 2020 14:25:39 +0100 Subject: [PATCH] Unify GuestType and GuestTypeClone, rename GuestTypeCopy to GuestTypeTransparent This commit refactors trait system for guest types. Namely, as discussed offline on zulip, `GuestType` now includes `GuestTypeClone`, whereas `GuestTypeCopy` has been renamed to `GuestTypeTransparent`. --- crates/generate/src/types.rs | 146 +++++++++++++++++------------ crates/runtime/src/guest_type.rs | 28 +++--- crates/runtime/src/lib.rs | 2 +- crates/runtime/src/memory/array.rs | 24 ++--- crates/runtime/src/memory/mod.rs | 4 +- crates/runtime/src/memory/ptr.rs | 67 ++++++------- tests/arrays.rs | 14 ++- tests/pointers.rs | 14 ++- 8 files changed, 152 insertions(+), 147 deletions(-) diff --git a/crates/generate/src/types.rs b/crates/generate/src/types.rs index 05154ded3e..a049a72a6d 100644 --- a/crates/generate/src/types.rs +++ b/crates/generate/src/types.rs @@ -105,7 +105,7 @@ fn define_int(names: &Names, name: &witx::Id, i: &witx::IntDatatype) -> TokenStr } } - impl wiggle_runtime::GuestType for #ident { + impl<'a> wiggle_runtime::GuestType<'a> for #ident { fn size() -> u32 { ::std::mem::size_of::<#repr>() as u32 } @@ -118,24 +118,24 @@ fn define_int(names: &Names, name: &witx::Id, i: &witx::IntDatatype) -> TokenStr stringify!(#ident).to_owned() } - fn validate<'a>(location: &wiggle_runtime::GuestPtr<'a, #ident>) -> Result<(), wiggle_runtime::GuestError> { + fn validate(location: &wiggle_runtime::GuestPtr<'a, #ident>) -> Result<(), wiggle_runtime::GuestError> { use ::std::convert::TryFrom; let raw: #repr = unsafe { (location.as_raw() as *const #repr).read() }; let _ = #ident::try_from(raw)?; Ok(()) } - } - impl<'a> wiggle_runtime::GuestTypeCopy<'a> for #ident {} - impl<'a> wiggle_runtime::GuestTypeClone<'a> for #ident { - fn read_from_guest(location: &wiggle_runtime::GuestPtr<#ident>) -> Result<#ident, wiggle_runtime::GuestError> { + fn read(location: &wiggle_runtime::GuestPtr<#ident>) -> Result<#ident, wiggle_runtime::GuestError> { Ok(*location.as_ref()?) } - fn write_to_guest(&self, location: &wiggle_runtime::GuestPtrMut<#ident>) { + + fn write(&self, location: &wiggle_runtime::GuestPtrMut<#ident>) { let val: #repr = #repr::from(*self); unsafe { (location.as_raw() as *mut #repr).write(val) }; } } + + impl<'a> wiggle_runtime::GuestTypeTransparent<'a> for #ident {} } } @@ -258,7 +258,7 @@ fn define_flags(names: &Names, name: &witx::Id, f: &witx::FlagsDatatype) -> Toke } } - impl wiggle_runtime::GuestType for #ident { + impl<'a> wiggle_runtime::GuestType<'a> for #ident { fn size() -> u32 { ::std::mem::size_of::<#repr>() as u32 } @@ -271,24 +271,24 @@ fn define_flags(names: &Names, name: &witx::Id, f: &witx::FlagsDatatype) -> Toke stringify!(#ident).to_owned() } - fn validate<'a>(location: &wiggle_runtime::GuestPtr<'a, #ident>) -> Result<(), wiggle_runtime::GuestError> { + fn validate(location: &wiggle_runtime::GuestPtr<'a, #ident>) -> Result<(), wiggle_runtime::GuestError> { use ::std::convert::TryFrom; let raw: #repr = unsafe { (location.as_raw() as *const #repr).read() }; let _ = #ident::try_from(raw)?; Ok(()) } - } - impl<'a> wiggle_runtime::GuestTypeCopy<'a> for #ident {} - impl<'a> wiggle_runtime::GuestTypeClone<'a> for #ident { - fn read_from_guest(location: &wiggle_runtime::GuestPtr<#ident>) -> Result<#ident, wiggle_runtime::GuestError> { + fn read(location: &wiggle_runtime::GuestPtr<#ident>) -> Result<#ident, wiggle_runtime::GuestError> { Ok(*location.as_ref()?) } - fn write_to_guest(&self, location: &wiggle_runtime::GuestPtrMut<#ident>) { + + fn write(&self, location: &wiggle_runtime::GuestPtrMut<#ident>) { let val: #repr = #repr::from(*self); unsafe { (location.as_raw() as *mut #repr).write(val) }; } } + + impl<'a> wiggle_runtime::GuestTypeTransparent<'a> for #ident {} } } @@ -364,37 +364,39 @@ fn define_enum(names: &Names, name: &witx::Id, e: &witx::EnumDatatype) -> TokenS } } - impl wiggle_runtime::GuestType for #ident { + impl<'a> wiggle_runtime::GuestType<'a> for #ident { fn size() -> u32 { ::std::mem::size_of::<#repr>() as u32 } + fn align() -> u32 { ::std::mem::align_of::<#repr>() as u32 } + fn name() -> String { stringify!(#ident).to_owned() } - fn validate<'a>(location: &wiggle_runtime::GuestPtr<'a, #ident>) -> Result<(), wiggle_runtime::GuestError> { + + fn validate(location: &wiggle_runtime::GuestPtr<'a, #ident>) -> Result<(), wiggle_runtime::GuestError> { use ::std::convert::TryFrom; let raw: #repr = unsafe { (location.as_raw() as *const #repr).read() }; let _ = #ident::try_from(raw)?; Ok(()) } - } - impl<'a> wiggle_runtime::GuestTypeCopy<'a> for #ident {} - impl<'a> wiggle_runtime::GuestTypeClone<'a> for #ident { - fn read_from_guest(location: &wiggle_runtime::GuestPtr<#ident>) -> Result<#ident, wiggle_runtime::GuestError> { + fn read(location: &wiggle_runtime::GuestPtr<#ident>) -> Result<#ident, wiggle_runtime::GuestError> { // Perform validation as part of as_ref: let r = location.as_ref()?; Ok(*r) } - fn write_to_guest(&self, location: &wiggle_runtime::GuestPtrMut<#ident>) { + + fn write(&self, location: &wiggle_runtime::GuestPtrMut<#ident>) { let val: #repr = #repr::from(*self); unsafe { (location.as_raw() as *mut #repr).write(val) }; } } + impl<'a> wiggle_runtime::GuestTypeTransparent<'a> for #ident {} } } @@ -434,30 +436,35 @@ fn define_handle(names: &Names, name: &witx::Id, h: &witx::HandleDatatype) -> To write!(f, "{}({})", stringify!(#ident), self.0) } } - impl wiggle_runtime::GuestType for #ident { + + impl<'a> wiggle_runtime::GuestType<'a> for #ident { fn size() -> u32 { #size } + fn align() -> u32 { #align } + fn name() -> String { stringify!(#ident).to_owned() } + fn validate(ptr: &wiggle_runtime::GuestPtr<#ident>) -> Result<(), wiggle_runtime::GuestError> { Ok(()) } - } - impl<'a> wiggle_runtime::GuestTypeClone<'a> for #ident { - fn read_from_guest(location: &wiggle_runtime::GuestPtr<'a, #ident>) -> Result<#ident, wiggle_runtime::GuestError> { + + fn read(location: &wiggle_runtime::GuestPtr<'a, #ident>) -> Result<#ident, wiggle_runtime::GuestError> { let r = location.as_ref()?; Ok(*r) } - fn write_to_guest(&self, location: &wiggle_runtime::GuestPtrMut<'a, Self>) { + + fn write(&self, location: &wiggle_runtime::GuestPtrMut<'a, Self>) { unsafe { (location.as_raw() as *mut #ident).write(*self) }; } } - impl<'a> wiggle_runtime::GuestTypeCopy<'a> for #ident {} + + impl<'a> wiggle_runtime::GuestTypeTransparent<'a> for #ident {} } } @@ -509,31 +516,35 @@ fn define_copy_struct(names: &Names, name: &witx::Id, s: &witx::StructDatatype) #(#member_decls),* } - impl wiggle_runtime::GuestType for #ident { + impl<'a> wiggle_runtime::GuestType<'a> for #ident { fn size() -> u32 { #size } + fn align() -> u32 { #align } + fn name() -> String { stringify!(#ident).to_owned() } + fn validate(ptr: &wiggle_runtime::GuestPtr<#ident>) -> Result<(), wiggle_runtime::GuestError> { #(#member_valids)* Ok(()) } - } - impl<'a> wiggle_runtime::GuestTypeClone<'a> for #ident { - fn read_from_guest(location: &wiggle_runtime::GuestPtr<'a, #ident>) -> Result<#ident, wiggle_runtime::GuestError> { + + fn read(location: &wiggle_runtime::GuestPtr<'a, #ident>) -> Result<#ident, wiggle_runtime::GuestError> { let r = location.as_ref()?; Ok(*r) } - fn write_to_guest(&self, location: &wiggle_runtime::GuestPtrMut<'a, Self>) { + + fn write(&self, location: &wiggle_runtime::GuestPtrMut<'a, Self>) { unsafe { (location.as_raw() as *mut #ident).write(*self) }; } } - impl<'a> wiggle_runtime::GuestTypeCopy<'a> for #ident {} + + impl<'a> wiggle_runtime::GuestTypeTransparent<'a> for #ident {} } } @@ -604,26 +615,26 @@ fn define_ptr_struct(names: &Names, name: &witx::Id, s: &witx::StructDatatype) - witx::TypeRef::Name(nt) => { let type_ = names.type_(&nt.name); quote! { - let #name = #type_::read_from_guest(&location.cast(#offset)?)?; + let #name = <#type_ as wiggle_runtime::GuestType>::read(&location.cast(#offset)?)?; } } witx::TypeRef::Value(ty) => match &**ty { witx::Type::Builtin(builtin) => { let type_ = names.builtin_type(*builtin, anon_lifetime()); quote! { - let #name = #type_::read_from_guest(&location.cast(#offset)?)?; + let #name = <#type_ as wiggle_runtime::GuestType>::read(&location.cast(#offset)?)?; } } witx::Type::Pointer(pointee) => { let pointee_type = names.type_ref(&pointee, anon_lifetime()); quote! { - let #name = wiggle_runtime::GuestPtrMut::<#pointee_type>::read_from_guest(&location.cast(#offset)?)?; + let #name = as wiggle_runtime::GuestType>::read(&location.cast(#offset)?)?; } } witx::Type::ConstPointer(pointee) => { let pointee_type = names.type_ref(&pointee, anon_lifetime()); quote! { - let #name = wiggle_runtime::GuestPtr::<#pointee_type>::read_from_guest(&location.cast(#offset)?)?; + let #name = as wiggle_runtime::GuestType>::read(&location.cast(#offset)?)?; } } _ => unimplemented!("other anonymous struct members"), @@ -635,7 +646,7 @@ fn define_ptr_struct(names: &Names, name: &witx::Id, s: &witx::StructDatatype) - let name = names.struct_member(&ml.member.name); let offset = ml.offset as u32; quote! { - self.#name.write_to_guest(&location.cast(#offset).expect("cast to inner member")); + self.#name.write(&location.cast(#offset).expect("cast to inner member")); } }); @@ -645,27 +656,30 @@ fn define_ptr_struct(names: &Names, name: &witx::Id, s: &witx::StructDatatype) - #(#member_decls),* } - impl<'a> wiggle_runtime::GuestType for #ident<'a> { + impl<'a> wiggle_runtime::GuestType<'a> for #ident<'a> { fn size() -> u32 { #size } + fn align() -> u32 { #align } + fn name() -> String { stringify!(#ident).to_owned() } - fn validate(ptr: &wiggle_runtime::GuestPtr<#ident>) -> Result<(), wiggle_runtime::GuestError> { + + fn validate(ptr: &wiggle_runtime::GuestPtr<'a, #ident<'a>>) -> Result<(), wiggle_runtime::GuestError> { #(#member_valids)* Ok(()) } - } - impl<'a> wiggle_runtime::GuestTypeClone<'a> for #ident<'a> { - fn read_from_guest(location: &wiggle_runtime::GuestPtr<'a, #ident<'a>>) -> Result<#ident<'a>, wiggle_runtime::GuestError> { + + fn read(location: &wiggle_runtime::GuestPtr<'a, #ident<'a>>) -> Result<#ident<'a>, wiggle_runtime::GuestError> { #(#member_reads)* Ok(#ident { #(#member_names),* }) } - fn write_to_guest(&self, location: &wiggle_runtime::GuestPtrMut<'a, Self>) { + + fn write(&self, location: &wiggle_runtime::GuestPtrMut<'a, Self>) { #(#member_writes)* } } @@ -694,11 +708,12 @@ fn union_validate( let err = with_err(v.name.as_str()); let variantname = names.enum_variant(&v.name); if let Some(tref) = &v.tref { - let varianttype = names.type_ref(tref, anon_lifetime()); + let lifetime = anon_lifetime(); + let varianttype = names.type_ref(tref, lifetime.clone()); quote! { #tagname::#variantname => { let variant_ptr = ptr.cast::<#varianttype>(#contents_offset).map_err(#err)?; - wiggle_runtime::GuestType::validate(&variant_ptr).map_err(#err)?; + <#varianttype as wiggle_runtime::GuestType>::validate(&variant_ptr).map_err(#err)?; } } } else { @@ -743,7 +758,7 @@ fn define_union(names: &Names, name: &witx::Id, u: &witx::UnionDatatype) -> Toke quote! { #tagname::#variantname => { let variant_ptr = location.cast::<#varianttype>(#contents_offset).expect("union variant ptr validated"); - let variant_val = wiggle_runtime::GuestTypeClone::read_from_guest(&variant_ptr)?; + let variant_val = <#varianttype as wiggle_runtime::GuestType>::read(&variant_ptr)?; Ok(#ident::#variantname(variant_val)) } } @@ -765,7 +780,7 @@ fn define_union(names: &Names, name: &witx::Id, u: &witx::UnionDatatype) -> Toke #ident::#variantname(contents) => { #write_tag let variant_ptr = location.cast::<#varianttype>(#contents_offset).expect("union variant ptr validated"); - contents.write_to_guest(&variant_ptr); + <#varianttype as wiggle_runtime::GuestType>::write(&contents, &variant_ptr); } } } else { @@ -785,31 +800,35 @@ fn define_union(names: &Names, name: &witx::Id, u: &witx::UnionDatatype) -> Toke pub enum #ident { #(#variants),* } - impl wiggle_runtime::GuestType for #ident { + + impl<'a> wiggle_runtime::GuestType<'a> for #ident { fn size() -> u32 { #size } + fn align() -> u32 { #align } + fn name() -> String { stringify!(#ident).to_owned() } - fn validate(ptr: &wiggle_runtime::GuestPtr<#ident>) -> Result<(), wiggle_runtime::GuestError> { + + fn validate(ptr: &wiggle_runtime::GuestPtr<'a, #ident>) -> Result<(), wiggle_runtime::GuestError> { #validate } - } - impl<#lifetime> wiggle_runtime::GuestTypeClone<#lifetime> for #ident { - fn read_from_guest(location: &wiggle_runtime::GuestPtr<'a, #ident>) + + fn read(location: &wiggle_runtime::GuestPtr<'a, #ident>) -> Result { - wiggle_runtime::GuestType::validate(location)?; + <#ident as wiggle_runtime::GuestType>::validate(location)?; let tag = *location.cast::<#tagname>(0).expect("validated tag ptr").as_ref().expect("validated tag ref"); match tag { #(#read_variant)* } } - fn write_to_guest(&self, location: &wiggle_runtime::GuestPtrMut<'a, #ident>) { + + fn write(&self, location: &wiggle_runtime::GuestPtrMut<'a, #ident>) { match self { #(#write_variant)* } @@ -823,31 +842,34 @@ fn define_union(names: &Names, name: &witx::Id, u: &witx::UnionDatatype) -> Toke #(#variants),* } - impl<#lifetime> wiggle_runtime::GuestType for #ident<#lifetime> { + impl<#lifetime> wiggle_runtime::GuestType<#lifetime> for #ident<#lifetime> { fn size() -> u32 { #size } + fn align() -> u32 { #align } + fn name() -> String { stringify!(#ident).to_owned() } - fn validate(ptr: &wiggle_runtime::GuestPtr<#ident>) -> Result<(), wiggle_runtime::GuestError> { + + fn validate(ptr: &wiggle_runtime::GuestPtr<#lifetime, #ident<#lifetime>>) -> Result<(), wiggle_runtime::GuestError> { #validate } - } - impl<#lifetime> wiggle_runtime::GuestTypeClone<#lifetime> for #ident<#lifetime> { - fn read_from_guest(location: &wiggle_runtime::GuestPtr<'a, #ident>) + + fn read(location: &wiggle_runtime::GuestPtr<#lifetime, #ident<#lifetime>>) -> Result { - wiggle_runtime::GuestType::validate(location)?; + <#ident as wiggle_runtime::GuestType>::validate(location)?; let tag = *location.cast::<#tagname>(0).expect("validated tag ptr").as_ref().expect("validated tag ref"); match tag { #(#read_variant)* } } - fn write_to_guest(&self, location: &wiggle_runtime::GuestPtrMut<'a, #ident>) { + + fn write(&self, location: &wiggle_runtime::GuestPtrMut<#lifetime, #ident<#lifetime>>) { match self { #(#write_variant)* } diff --git a/crates/runtime/src/guest_type.rs b/crates/runtime/src/guest_type.rs index 6cf0972f2b..2a9eadc59c 100644 --- a/crates/runtime/src/guest_type.rs +++ b/crates/runtime/src/guest_type.rs @@ -1,26 +1,25 @@ use crate::{GuestError, GuestPtr, GuestPtrMut}; -pub trait GuestType: Sized { +pub trait GuestType<'a>: Sized + Clone { // These are morally the same as Rust ::std::mem::size_of / align_of, but they return // a u32 because the wasm memory space is 32 bits. They have a different names so they // don't collide with the std::mem methods. fn size() -> u32; fn align() -> u32; fn name() -> String; - fn validate<'a>(location: &GuestPtr<'a, Self>) -> Result<(), GuestError>; + fn validate(location: &GuestPtr<'a, Self>) -> Result<(), GuestError>; + fn read(location: &GuestPtr<'a, Self>) -> Result; + fn write(&self, location: &GuestPtrMut<'a, Self>); } -pub trait GuestTypeClone<'a>: GuestType + Clone { - fn read_from_guest(location: &GuestPtr<'a, Self>) -> Result; - fn write_to_guest(&self, location: &GuestPtrMut<'a, Self>); -} -// Following trait system in Rust, Copy implies Clone -pub trait GuestTypeCopy<'a>: GuestTypeClone<'a> + Copy {} +/// Represents any guest type which can transparently be represented +/// as a host type. +pub trait GuestTypeTransparent<'a>: GuestType<'a> + Copy {} macro_rules! builtin_type { ( $( $t:ident ), * ) => { $( - impl GuestType for $t { + impl<'a> GuestType<'a> for $t { fn size() -> u32 { ::std::mem::size_of::<$t>() as u32 } @@ -33,16 +32,14 @@ macro_rules! builtin_type { fn validate(_ptr: &GuestPtr<$t>) -> Result<(), GuestError> { Ok(()) } - } - impl<'a> GuestTypeClone<'a> for $t { - fn read_from_guest(location: &GuestPtr<'a, Self>) -> Result { + fn read(location: &GuestPtr<'a, Self>) -> Result { Ok(*location.as_ref()?) } - fn write_to_guest(&self, location: &GuestPtrMut<'a, Self>) { + fn write(&self, location: &GuestPtrMut<'a, Self>) { unsafe { (location.as_raw() as *mut $t).write(*self) }; } } - impl<'a> GuestTypeCopy<'a> for $t {} + impl<'a> GuestTypeTransparent<'a> for $t {} )* }; } @@ -50,9 +47,6 @@ macro_rules! builtin_type { // These definitions correspond to all the witx BuiltinType variants that are Copy: builtin_type!(u8, i8, u16, i16, u32, i32, u64, i64, f32, f64, usize); -// FIXME implement GuestType for char. needs to validate that its a code point. what is the sizeof a char? -// FIXME implement GuestType for String. how does validate work for array types? - pub trait GuestErrorType { type Context; fn success() -> Self; diff --git a/crates/runtime/src/lib.rs b/crates/runtime/src/lib.rs index 839c646b0b..99648c4b1a 100644 --- a/crates/runtime/src/lib.rs +++ b/crates/runtime/src/lib.rs @@ -5,7 +5,7 @@ mod memory; mod region; pub use error::GuestError; -pub use guest_type::{GuestErrorType, GuestType, GuestTypeClone, GuestTypeCopy}; +pub use guest_type::{GuestErrorType, GuestType, GuestTypeTransparent}; pub use memory::{ GuestArray, GuestMemory, GuestPtr, GuestPtrMut, GuestRef, GuestRefMut, GuestString, GuestStringRef, diff --git a/crates/runtime/src/memory/array.rs b/crates/runtime/src/memory/array.rs index db3408cc3f..3c7815536b 100644 --- a/crates/runtime/src/memory/array.rs +++ b/crates/runtime/src/memory/array.rs @@ -1,11 +1,11 @@ use super::ptr::{GuestPtr, GuestRef}; -use crate::{GuestError, GuestType, GuestTypeCopy}; +use crate::{GuestError, GuestType, GuestTypeTransparent}; use std::{fmt, ops::Deref}; #[derive(Clone)] pub struct GuestArray<'a, T> where - T: GuestType, + T: GuestType<'a>, { pub(super) ptr: GuestPtr<'a, T>, pub(super) num_elems: u32, @@ -13,7 +13,7 @@ where impl<'a, T> fmt::Debug for GuestArray<'a, T> where - T: GuestType + fmt::Debug, + T: GuestType<'a> + fmt::Debug, { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!( @@ -26,7 +26,7 @@ where impl<'a, T> GuestArray<'a, T> where - T: GuestType, + T: GuestType<'a>, { pub fn iter(&self) -> GuestArrayIter<'a, T> { let next = GuestPtr { @@ -44,7 +44,7 @@ where pub struct GuestArrayIter<'a, T> where - T: GuestType, + T: GuestType<'a>, { next: GuestPtr<'a, T>, num_elems: u32, @@ -53,7 +53,7 @@ where impl<'a, T> Iterator for GuestArrayIter<'a, T> where - T: GuestType, + T: GuestType<'a>, { type Item = Result, GuestError>; @@ -79,7 +79,7 @@ where impl<'a, T> GuestArray<'a, T> where - T: GuestTypeCopy<'a>, + T: GuestTypeTransparent<'a>, { pub fn as_ref(&self) -> Result, GuestError> { let mut next = self.ptr.elem(0)?; @@ -109,7 +109,7 @@ where pub struct GuestArrayRef<'a, T> where - T: GuestTypeCopy<'a>, + T: GuestTypeTransparent<'a>, { ref_: GuestRef<'a, T>, num_elems: u32, @@ -117,7 +117,7 @@ where impl<'a, T> fmt::Debug for GuestArrayRef<'a, T> where - T: GuestTypeCopy<'a> + fmt::Debug, + T: GuestTypeTransparent<'a> + fmt::Debug, { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!( @@ -130,7 +130,7 @@ where impl<'a, T> Deref for GuestArrayRef<'a, T> where - T: GuestTypeCopy<'a>, + T: GuestTypeTransparent<'a>, { type Target = [T]; @@ -148,7 +148,7 @@ where mod test { use crate::{ memory::ptr::{GuestPtr, GuestPtrMut}, - GuestError, GuestMemory, GuestTypeClone, Region, + GuestError, GuestMemory, GuestType, Region, }; #[repr(align(4096))] @@ -249,7 +249,7 @@ mod test { let contents = arr .iter() .map(|ptr_ptr| { - *GuestTypeClone::read_from_guest(&ptr_ptr.expect("valid ptr to ptr")) + *GuestType::read(&ptr_ptr.expect("valid ptr to ptr")) .expect("valid ptr to some value") .as_ref() .expect("deref ptr to some value") diff --git a/crates/runtime/src/memory/mod.rs b/crates/runtime/src/memory/mod.rs index 2800da56f1..9fd8f907fe 100644 --- a/crates/runtime/src/memory/mod.rs +++ b/crates/runtime/src/memory/mod.rs @@ -43,7 +43,7 @@ impl<'a> GuestMemory<'a> { && r.start <= (self.len - r.len) } - pub fn ptr(&'a self, at: u32) -> Result, GuestError> { + pub fn ptr>(&'a self, at: u32) -> Result, GuestError> { let region = Region { start: at, len: T::size(), @@ -61,7 +61,7 @@ impl<'a> GuestMemory<'a> { }) } - pub fn ptr_mut(&'a self, at: u32) -> Result, GuestError> { + pub fn ptr_mut>(&'a self, at: u32) -> Result, GuestError> { let ptr = self.ptr(at)?; Ok(GuestPtrMut { mem: ptr.mem, diff --git a/crates/runtime/src/memory/ptr.rs b/crates/runtime/src/memory/ptr.rs index 9e853c3742..a09068ae25 100644 --- a/crates/runtime/src/memory/ptr.rs +++ b/crates/runtime/src/memory/ptr.rs @@ -1,5 +1,5 @@ use super::{array::GuestArray, GuestMemory}; -use crate::{borrow::BorrowHandle, GuestError, GuestType, GuestTypeClone, GuestTypeCopy, Region}; +use crate::{borrow::BorrowHandle, GuestError, GuestType, GuestTypeTransparent, Region}; use std::{ fmt, marker::PhantomData, @@ -26,7 +26,7 @@ where } } -impl<'a, T: GuestType> GuestPtr<'a, T> { +impl<'a, T: GuestType<'a>> GuestPtr<'a, T> { pub fn as_raw(&self) -> *const u8 { (self.mem.ptr as usize + self.region.start as usize) as *const u8 } @@ -36,7 +36,10 @@ impl<'a, T: GuestType> GuestPtr<'a, T> { .ptr(self.region.start + (elements * self.region.len as i32) as u32) } - pub fn cast(&self, offset: u32) -> Result, GuestError> { + pub fn cast>( + &self, + offset: u32, + ) -> Result, GuestError> { self.mem.ptr(self.region.start + offset) } @@ -57,7 +60,7 @@ impl<'a, T: GuestType> GuestPtr<'a, T> { impl<'a, T> GuestPtr<'a, T> where - T: GuestTypeCopy<'a>, + T: GuestTypeTransparent<'a>, { pub fn as_ref(&self) -> Result, GuestError> { T::validate(&self)?; @@ -78,16 +81,16 @@ where impl<'a, T> GuestPtr<'a, T> where - T: GuestTypeClone<'a>, + T: GuestType<'a>, { pub fn read(&self) -> Result { - T::read_from_guest(self) + T::read(self) } } -impl<'a, T> GuestType for GuestPtr<'a, T> +impl<'a, T> GuestType<'a> for GuestPtr<'a, T> where - T: GuestType, + T: GuestType<'a>, { fn size() -> u32 { 4 @@ -101,21 +104,16 @@ where format!("GuestPtr<{}>", T::name()) } - fn validate<'b>(location: &GuestPtr<'b, GuestPtr<'b, T>>) -> Result<(), GuestError> { + fn validate(location: &GuestPtr<'a, GuestPtr<'a, T>>) -> Result<(), 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 = location.mem.ptr(raw_ptr)?; Ok(()) } -} -// Operations for reading and writing Ptrs to memory: -impl<'a, T> GuestTypeClone<'a> for GuestPtr<'a, T> -where - T: GuestType + Clone, -{ - fn read_from_guest(location: &GuestPtr<'a, Self>) -> Result { + // Operations for reading and writing Ptrs to memory: + fn read(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: @@ -123,7 +121,7 @@ where Ok(guest_ptr) } - fn write_to_guest(&self, location: &GuestPtrMut<'a, Self>) { + fn write(&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; @@ -154,7 +152,7 @@ where impl<'a, T> GuestPtrMut<'a, T> where - T: GuestType, + T: GuestType<'a>, { pub fn as_immut(&self) -> GuestPtr<'a, T> { GuestPtr { @@ -173,7 +171,7 @@ where .ptr_mut(self.region.start + (elements * self.region.len as i32) as u32) } - pub fn cast( + pub fn cast>( &self, offset: u32, ) -> Result, GuestError> { @@ -183,7 +181,7 @@ where impl<'a, T> GuestPtrMut<'a, T> where - T: GuestTypeCopy<'a>, + T: GuestTypeTransparent<'a>, { pub fn as_ref(&self) -> Result, GuestError> { self.as_immut().as_ref() @@ -208,20 +206,20 @@ where impl<'a, T> GuestPtrMut<'a, T> where - T: GuestTypeClone<'a>, + T: GuestType<'a>, { pub fn read(&self) -> Result { - T::read_from_guest(&self.as_immut()) + T::read(&self.as_immut()) } pub fn write(&self, ptr: &T) { - T::write_to_guest(ptr, &self); + T::write(ptr, &self); } } -impl<'a, T> GuestType for GuestPtrMut<'a, T> +impl<'a, T> GuestType<'a> for GuestPtrMut<'a, T> where - T: GuestType, + T: GuestType<'a>, { fn size() -> u32 { 4 @@ -235,21 +233,16 @@ where format!("GuestPtrMut<{}>", T::name()) } - fn validate<'b>(location: &GuestPtr<'b, GuestPtrMut<'b, T>>) -> Result<(), GuestError> { + fn validate(location: &GuestPtr<'a, GuestPtrMut<'a, T>>) -> Result<(), 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 = location.mem.ptr(raw_ptr)?; Ok(()) } -} -// Reading and writing GuestPtrMuts to memory: -impl<'a, T> GuestTypeClone<'a> for GuestPtrMut<'a, T> -where - T: GuestType + Clone, -{ - fn read_from_guest(location: &GuestPtr<'a, Self>) -> Result { + // Reading and writing GuestPtrMuts to memory: + fn read(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: @@ -257,7 +250,7 @@ where Ok(guest_ptr_mut) } - fn write_to_guest(&self, location: &GuestPtrMut<'a, Self>) { + fn write(&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; @@ -298,7 +291,7 @@ impl<'a, T> GuestRef<'a, T> { impl<'a, T> Deref for GuestRef<'a, T> where - T: GuestTypeCopy<'a>, + T: GuestTypeTransparent<'a>, { type Target = T; @@ -357,7 +350,7 @@ impl<'a, T> GuestRefMut<'a, T> { impl<'a, T> ::std::ops::Deref for GuestRefMut<'a, T> where - T: GuestTypeCopy<'a>, + T: GuestTypeTransparent<'a>, { type Target = T; @@ -372,7 +365,7 @@ where impl<'a, T> DerefMut for GuestRefMut<'a, T> where - T: GuestTypeCopy<'a>, + T: GuestTypeTransparent<'a>, { fn deref_mut(&mut self) -> &mut Self::Target { unsafe { diff --git a/tests/arrays.rs b/tests/arrays.rs index a5acfdbd45..0a5e0641fa 100644 --- a/tests/arrays.rs +++ b/tests/arrays.rs @@ -1,5 +1,5 @@ use proptest::prelude::*; -use wiggle_runtime::{GuestArray, GuestError, GuestPtr, GuestPtrMut}; +use wiggle_runtime::{GuestArray, GuestError, GuestPtr, GuestPtrMut, GuestType}; use wiggle_test::{impl_errno, HostMemory, MemArea, WasiCtx}; wiggle_generate::from_witx!({ @@ -14,7 +14,7 @@ impl arrays::Arrays for WasiCtx { &mut self, excuses: &types::ConstExcuseArray, ) -> Result { - let last = wiggle_runtime::GuestTypeClone::read_from_guest( + let last = GuestType::read( &excuses .iter() .last() @@ -27,9 +27,8 @@ impl arrays::Arrays for WasiCtx { fn populate_excuses(&mut self, excuses: &types::ExcuseArray) -> Result<(), types::Errno> { for excuse in excuses.iter() { - let ptr_to_ptr = - wiggle_runtime::GuestTypeClone::read_from_guest(&excuse.expect("valid ptr to ptr")) - .expect("valid ptr to some Excuse value"); + let ptr_to_ptr = GuestType::read(&excuse.expect("valid ptr to ptr")) + .expect("valid ptr to some Excuse value"); let mut ptr = ptr_to_ptr .as_ref_mut() .expect("dereferencing mut ptr should succeed"); @@ -226,9 +225,8 @@ impl PopulateExcusesExcercise { .array(self.elements.len() as u32) .expect("as array"); for el in arr.iter() { - let ptr_to_ptr = - wiggle_runtime::GuestTypeClone::read_from_guest(&el.expect("valid ptr to ptr")) - .expect("valid ptr to some Excuse value"); + let ptr_to_ptr = GuestType::read(&el.expect("valid ptr to ptr")) + .expect("valid ptr to some Excuse value"); assert_eq!( *ptr_to_ptr .as_ref() diff --git a/tests/pointers.rs b/tests/pointers.rs index e22e1d67f2..e086c59061 100644 --- a/tests/pointers.rs +++ b/tests/pointers.rs @@ -1,5 +1,5 @@ use proptest::prelude::*; -use wiggle_runtime::{GuestError, GuestPtr, GuestPtrMut, GuestRefMut}; +use wiggle_runtime::{GuestError, GuestPtr, GuestPtrMut, GuestRefMut, GuestType}; use wiggle_test::{impl_errno, HostMemory, MemArea, WasiCtx}; wiggle_generate::from_witx!({ @@ -38,13 +38,11 @@ impl pointers::Pointers for WasiCtx { println!("wrote to input2_ref {:?}", input3); // Read ptr value from mutable ptr: - let input4_ptr: GuestPtr = wiggle_runtime::GuestTypeClone::read_from_guest( - &input4_ptr_ptr.as_immut(), - ) - .map_err(|e| { - eprintln!("input4_ptr_ptr error: {}", e); - types::Errno::InvalidArg - })?; + let input4_ptr: GuestPtr = GuestType::read(&input4_ptr_ptr.as_immut()) + .map_err(|e| { + eprintln!("input4_ptr_ptr error: {}", e); + types::Errno::InvalidArg + })?; // Read enum value from that ptr: let input4: types::Excuse = *input4_ptr.as_ref().map_err(|e| {