diff --git a/crates/generate/src/types.rs b/crates/generate/src/types.rs index 9fb8cea87a..ebdb7d3567 100644 --- a/crates/generate/src/types.rs +++ b/crates/generate/src/types.rs @@ -125,7 +125,7 @@ fn define_int(names: &Names, name: &witx::Id, i: &witx::IntDatatype) -> TokenStr } } - impl wiggle_runtime::GuestTypeCopy for #ident {} + 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> { Ok(*location.as_ref()?) @@ -278,7 +278,7 @@ fn define_flags(names: &Names, name: &witx::Id, f: &witx::FlagsDatatype) -> Toke } } - impl wiggle_runtime::GuestTypeCopy for #ident {} + 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> { Ok(*location.as_ref()?) @@ -381,7 +381,7 @@ fn define_enum(names: &Names, name: &witx::Id, e: &witx::EnumDatatype) -> TokenS } } - impl wiggle_runtime::GuestTypeCopy for #ident {} + 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> { use ::std::convert::TryFrom; @@ -496,7 +496,15 @@ fn define_copy_struct(names: &Names, name: &witx::Id, s: &witx::StructDatatype) Ok(()) } } - impl wiggle_runtime::GuestTypeCopy for #ident {} + impl<'a> wiggle_runtime::GuestTypeClone<'a> for #ident { + fn read_from_guest(location: &wiggle_runtime::GuestPtr<'a, #ident>) -> Result<#ident, wiggle_runtime::GuestError> { + Ok(*location.as_ref()?) + } + fn write_to_guest(&self, location: &wiggle_runtime::GuestPtrMut<'a, Self>) { + unsafe { (location.as_raw() as *mut #ident).write(*self) }; + } + } + impl<'a> wiggle_runtime::GuestTypeCopy<'a> for #ident {} } } @@ -567,14 +575,14 @@ 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_ = *location.cast(#offset)?.as_ref()?; + let #name = #type_::read_from_guest(&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_ = *location.cast(#offset)?.as_ref()?; + let #name = #type_::read_from_guest(&location.cast(#offset)?)?; } } witx::Type::Pointer(pointee) => { @@ -597,30 +605,8 @@ fn define_ptr_struct(names: &Names, name: &witx::Id, s: &witx::StructDatatype) - let member_writes = s.member_layout().into_iter().map(|ml| { let name = names.struct_member(&ml.member.name); let offset = ml.offset as u32; - match &ml.member.tref { - witx::TypeRef::Name(_) => { - quote! { - *location.cast(#offset).expect("cast to inner member").as_ref_mut().expect("inner member as ref mut") = self.#name; - } - } - witx::TypeRef::Value(ty) => match &**ty { - witx::Type::Builtin(_) => { - quote! { - *location.cast(#offset).expect("cast to inner member").as_ref_mut().expect("inner member as ref mut") = self.#name; - } - } - witx::Type::Pointer(_) => { - quote! { - self.#name.write_to_guest(&location.cast(#offset).expect("cast to inner member")); - } - } - witx::Type::ConstPointer(_) => { - quote! { - self.#name.write_to_guest(&location.cast(#offset).expect("cast to inner member")); - } - } - _ => unimplemented!("other anonymous struct members"), - }, + quote! { + self.#name.write_to_guest(&location.cast(#offset).expect("cast to inner member")); } }); diff --git a/crates/runtime/src/guest_type.rs b/crates/runtime/src/guest_type.rs index 83eacaa0ce..6cf0972f2b 100644 --- a/crates/runtime/src/guest_type.rs +++ b/crates/runtime/src/guest_type.rs @@ -10,11 +10,12 @@ pub trait GuestType: Sized { fn validate<'a>(location: &GuestPtr<'a, Self>) -> Result<(), GuestError>; } -pub trait GuestTypeCopy: GuestType + Copy {} 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 {} macro_rules! builtin_type { ( $( $t:ident ), * ) => { @@ -33,7 +34,15 @@ macro_rules! builtin_type { Ok(()) } } - impl GuestTypeCopy for $t {} + impl<'a> GuestTypeClone<'a> for $t { + fn read_from_guest(location: &GuestPtr<'a, Self>) -> Result { + Ok(*location.as_ref()?) + } + fn write_to_guest(&self, location: &GuestPtrMut<'a, Self>) { + unsafe { (location.as_raw() as *mut $t).write(*self) }; + } + } + impl<'a> GuestTypeCopy<'a> for $t {} )* }; } diff --git a/crates/runtime/src/memory/array.rs b/crates/runtime/src/memory/array.rs index c9615b1e2f..d55da51e2f 100644 --- a/crates/runtime/src/memory/array.rs +++ b/crates/runtime/src/memory/array.rs @@ -79,7 +79,7 @@ where impl<'a, T> GuestArray<'a, T> where - T: GuestTypeCopy, + T: GuestTypeCopy<'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, + T: GuestTypeCopy<'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 + fmt::Debug, + T: GuestTypeCopy<'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, + T: GuestTypeCopy<'a>, { type Target = [T]; diff --git a/crates/runtime/src/memory/ptr.rs b/crates/runtime/src/memory/ptr.rs index afebb6c332..f6a164fbd1 100644 --- a/crates/runtime/src/memory/ptr.rs +++ b/crates/runtime/src/memory/ptr.rs @@ -57,7 +57,7 @@ impl<'a, T: GuestType> GuestPtr<'a, T> { impl<'a, T> GuestPtr<'a, T> where - T: GuestTypeCopy, + T: GuestTypeCopy<'a>, { pub fn as_ref(&self) -> Result, GuestError> { T::validate(&self)?; @@ -183,7 +183,7 @@ where impl<'a, T> GuestPtrMut<'a, T> where - T: GuestTypeCopy, + T: GuestTypeCopy<'a>, { pub fn as_ref(&self) -> Result, GuestError> { self.as_immut().as_ref() @@ -298,7 +298,7 @@ impl<'a, T> GuestRef<'a, T> { impl<'a, T> Deref for GuestRef<'a, T> where - T: GuestTypeCopy, + T: GuestTypeCopy<'a>, { type Target = T; @@ -357,7 +357,7 @@ impl<'a, T> GuestRefMut<'a, T> { impl<'a, T> ::std::ops::Deref for GuestRefMut<'a, T> where - T: GuestTypeCopy, + T: GuestTypeCopy<'a>, { type Target = T; @@ -372,7 +372,7 @@ where impl<'a, T> DerefMut for GuestRefMut<'a, T> where - T: GuestTypeCopy, + T: GuestTypeCopy<'a>, { fn deref_mut(&mut self) -> &mut Self::Target { unsafe {