flesh out the guest type traits a bit further
This commit is contained in:
@@ -41,6 +41,7 @@ impl Names {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(unused)]
|
||||||
pub fn type_ref(&self, tref: &TypeRef) -> TokenStream {
|
pub fn type_ref(&self, tref: &TypeRef) -> TokenStream {
|
||||||
match tref {
|
match tref {
|
||||||
TypeRef::Name(nt) => {
|
TypeRef::Name(nt) => {
|
||||||
|
|||||||
@@ -36,15 +36,61 @@ fn define_enum(names: &Names, name: &witx::Id, e: &witx::EnumDatatype) -> TokenS
|
|||||||
output.extend(quote!(#[repr(#repr)]));
|
output.extend(quote!(#[repr(#repr)]));
|
||||||
output.extend(quote!(#[derive(Copy, Clone, Debug, std::hash::Hash, Eq, PartialEq)]));
|
output.extend(quote!(#[derive(Copy, Clone, Debug, std::hash::Hash, Eq, PartialEq)]));
|
||||||
|
|
||||||
let mut inner = TokenStream::new();
|
let mut variants = TokenStream::new();
|
||||||
for variant in &e.variants {
|
let mut to_repr_cases = TokenStream::new();
|
||||||
|
let mut tryfrom_repr_cases = TokenStream::new();
|
||||||
|
for (n, variant) in e.variants.iter().enumerate() {
|
||||||
|
let n = n as u32;
|
||||||
let variant_name = names.enum_variant(&variant.name);
|
let variant_name = names.enum_variant(&variant.name);
|
||||||
inner.extend(quote!(#variant_name,));
|
variants.extend(quote!(#variant_name,));
|
||||||
|
tryfrom_repr_cases.extend(quote!(#n => Ok(#ident::#variant_name),));
|
||||||
|
to_repr_cases.extend(quote!(#ident::#variant_name => #n,));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tryfrom_repr_cases
|
||||||
|
.extend(quote!(_ => Err(::memory::GuestValueError::InvalidEnum(stringify!(#ident)))));
|
||||||
|
|
||||||
output.extend(quote!(pub enum #ident {
|
output.extend(quote!(pub enum #ident {
|
||||||
#inner
|
#variants
|
||||||
}));
|
}
|
||||||
|
|
||||||
|
impl ::std::convert::TryFrom<#repr> for #ident {
|
||||||
|
type Error = ::memory::GuestValueError;
|
||||||
|
fn try_from(value: #repr) -> Result<#ident, ::memory::GuestValueError> {
|
||||||
|
match value {
|
||||||
|
#tryfrom_repr_cases
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<#ident> for #repr {
|
||||||
|
fn from(e: #ident) -> #repr {
|
||||||
|
match e {
|
||||||
|
#to_repr_cases
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ::memory::GuestType for #ident {
|
||||||
|
fn size() -> u32 {
|
||||||
|
::std::mem::size_of::<#repr>() as u32
|
||||||
|
}
|
||||||
|
fn name() -> &'static str {
|
||||||
|
stringify!(#ident)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ::memory::GuestTypeCopy for #ident {
|
||||||
|
fn read_val(src: ::memory::GuestPtr<#ident>) -> Result<#ident, ::memory::GuestValueError> {
|
||||||
|
// Get the pointer to memory, cast it to *const #repr, read_unaligned, then use the tryinto
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
fn write_val(val: #ident, dest: ::memory::GuestPtrMut<#ident>) {
|
||||||
|
// use the into<#repr>, get pointer to memory, write_unaligned
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
));
|
||||||
|
|
||||||
output
|
output
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,75 +1,68 @@
|
|||||||
pub trait GuestType {
|
use crate::{GuestPtr, GuestPtrMut};
|
||||||
fn len() -> u32;
|
use thiserror::Error;
|
||||||
|
|
||||||
|
pub trait GuestType: Sized {
|
||||||
|
fn size() -> u32;
|
||||||
|
fn name() -> &'static str;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl GuestType for u8 {
|
#[derive(Debug, Error)]
|
||||||
fn len() -> u32 {
|
pub enum GuestValueError {
|
||||||
1
|
#[error("Invalid enum {0}")]
|
||||||
|
InvalidEnum(&'static str),
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait GuestTypeCopy: GuestType + Copy {
|
||||||
|
fn read_val(src: GuestPtr<Self>) -> Result<Self, GuestValueError>;
|
||||||
|
fn write_val(val: Self, dest: GuestPtrMut<Self>);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait GuestTypeClone: GuestType + Clone {
|
||||||
|
fn read_ref(src: GuestPtr<Self>, dest: &mut Self) -> Result<(), GuestValueError>;
|
||||||
|
fn write_ref(val: &Self, dest: GuestPtrMut<Self>);
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> GuestTypeClone for T
|
||||||
|
where
|
||||||
|
T: GuestTypeCopy,
|
||||||
|
{
|
||||||
|
fn read_ref(src: GuestPtr<T>, dest: &mut T) -> Result<(), GuestValueError> {
|
||||||
|
let val = GuestTypeCopy::read_val(src)?;
|
||||||
|
*dest = val;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
fn write_ref(val: &T, dest: GuestPtrMut<T>) {
|
||||||
|
GuestTypeCopy::write_val(*val, dest)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl GuestType for i8 {
|
macro_rules! builtin_copy {
|
||||||
fn len() -> u32 {
|
( $( $t:ident ), * ) => {
|
||||||
1
|
$(
|
||||||
|
impl GuestType for $t {
|
||||||
|
fn size() -> u32 {
|
||||||
|
::std::mem::size_of::<$t>() as u32
|
||||||
|
}
|
||||||
|
fn name() -> &'static str {
|
||||||
|
::std::stringify!($t)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl GuestType for u16 {
|
impl GuestTypeCopy for $t {
|
||||||
fn len() -> u32 {
|
fn read_val(src: GuestPtr<$t>) -> Result<$t, GuestValueError> {
|
||||||
2
|
Ok(unsafe {
|
||||||
|
::std::ptr::read_unaligned(src.ptr() as *const $t)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
fn write_val(val: $t, dest: GuestPtrMut<$t>) {
|
||||||
|
unsafe {
|
||||||
|
::std::ptr::write_unaligned(dest.ptr_mut() as *mut $t, val)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)*
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
impl GuestType for i16 {
|
// These definitions correspond to all the witx BuiltinType variants that are Copy:
|
||||||
fn len() -> u32 {
|
builtin_copy!(u8, i8, u16, i16, u32, i32, u64, i64, f32, f64, usize, char);
|
||||||
2
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl GuestType for u32 {
|
|
||||||
fn len() -> u32 {
|
|
||||||
4
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl GuestType for i32 {
|
|
||||||
fn len() -> u32 {
|
|
||||||
4
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl GuestType for f32 {
|
|
||||||
fn len() -> u32 {
|
|
||||||
4
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl GuestType for u64 {
|
|
||||||
fn len() -> u32 {
|
|
||||||
8
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl GuestType for i64 {
|
|
||||||
fn len() -> u32 {
|
|
||||||
8
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl GuestType for f64 {
|
|
||||||
fn len() -> u32 {
|
|
||||||
8
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl GuestType for char {
|
|
||||||
fn len() -> u32 {
|
|
||||||
1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl GuestType for usize {
|
|
||||||
fn len() -> u32 {
|
|
||||||
4
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -3,6 +3,6 @@ mod guest_type;
|
|||||||
mod memory;
|
mod memory;
|
||||||
mod region;
|
mod region;
|
||||||
|
|
||||||
pub use guest_type::GuestType;
|
pub use guest_type::{GuestType, GuestTypeClone, GuestTypeCopy, GuestValueError};
|
||||||
pub use memory::{GuestMemory, GuestPtr, GuestPtrMut};
|
pub use memory::{GuestMemory, GuestPtr, GuestPtrMut};
|
||||||
pub use region::Region;
|
pub use region::Region;
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ impl<'a> GuestMemory<'a> {
|
|||||||
pub fn ptr<T: GuestType>(&'a self, at: u32) -> Result<GuestPtr<'a, T>, MemoryError> {
|
pub fn ptr<T: GuestType>(&'a self, at: u32) -> Result<GuestPtr<'a, T>, MemoryError> {
|
||||||
let r = Region {
|
let r = Region {
|
||||||
start: at,
|
start: at,
|
||||||
len: T::len(),
|
len: T::size(),
|
||||||
};
|
};
|
||||||
let mut borrows = self.borrows.borrow_mut();
|
let mut borrows = self.borrows.borrow_mut();
|
||||||
if !self.contains(r) {
|
if !self.contains(r) {
|
||||||
@@ -53,7 +53,7 @@ impl<'a> GuestMemory<'a> {
|
|||||||
pub fn ptr_mut<T: GuestType>(&'a self, at: u32) -> Result<GuestPtrMut<'a, T>, MemoryError> {
|
pub fn ptr_mut<T: GuestType>(&'a self, at: u32) -> Result<GuestPtrMut<'a, T>, MemoryError> {
|
||||||
let r = Region {
|
let r = Region {
|
||||||
start: at,
|
start: at,
|
||||||
len: T::len(),
|
len: T::size(),
|
||||||
};
|
};
|
||||||
let mut borrows = self.borrows.borrow_mut();
|
let mut borrows = self.borrows.borrow_mut();
|
||||||
if !self.contains(r) {
|
if !self.contains(r) {
|
||||||
@@ -77,10 +77,19 @@ pub struct GuestPtr<'a, T> {
|
|||||||
type_: PhantomData<T>,
|
type_: PhantomData<T>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, T> GuestPtr<'a, T> {
|
impl<'a, T: GuestType> GuestPtr<'a, T> {
|
||||||
pub fn ptr(&self) -> *const u8 {
|
pub fn ptr(&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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub unsafe fn downcast<Q: GuestType>(self) -> GuestPtr<'a, Q> {
|
||||||
|
debug_assert!(T::size() == Q::size(), "downcast to type of same size");
|
||||||
|
GuestPtr {
|
||||||
|
mem: self.mem,
|
||||||
|
region: self.region,
|
||||||
|
type_: PhantomData,
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, T> Drop for GuestPtr<'a, T> {
|
impl<'a, T> Drop for GuestPtr<'a, T> {
|
||||||
|
|||||||
Reference in New Issue
Block a user