flesh out the guest type traits a bit further

This commit is contained in:
Pat Hickey
2020-01-22 16:38:25 -08:00
parent b8feffe6e1
commit aa5c5f7018
5 changed files with 126 additions and 77 deletions

View File

@@ -1,75 +1,68 @@
pub trait GuestType {
fn len() -> u32;
use crate::{GuestPtr, GuestPtrMut};
use thiserror::Error;
pub trait GuestType: Sized {
fn size() -> u32;
fn name() -> &'static str;
}
impl GuestType for u8 {
fn len() -> u32 {
1
#[derive(Debug, Error)]
pub enum GuestValueError {
#[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 {
fn len() -> u32 {
1
}
macro_rules! builtin_copy {
( $( $t:ident ), * ) => {
$(
impl GuestType for $t {
fn size() -> u32 {
::std::mem::size_of::<$t>() as u32
}
fn name() -> &'static str {
::std::stringify!($t)
}
}
impl GuestTypeCopy for $t {
fn read_val(src: GuestPtr<$t>) -> Result<$t, GuestValueError> {
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 u16 {
fn len() -> u32 {
2
}
}
impl GuestType for i16 {
fn len() -> u32 {
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
}
}
// These definitions correspond to all the witx BuiltinType variants that are Copy:
builtin_copy!(u8, i8, u16, i16, u32, i32, u64, i64, f32, f64, usize, char);

View File

@@ -3,6 +3,6 @@ mod guest_type;
mod memory;
mod region;
pub use guest_type::GuestType;
pub use guest_type::{GuestType, GuestTypeClone, GuestTypeCopy, GuestValueError};
pub use memory::{GuestMemory, GuestPtr, GuestPtrMut};
pub use region::Region;

View File

@@ -33,7 +33,7 @@ impl<'a> GuestMemory<'a> {
pub fn ptr<T: GuestType>(&'a self, at: u32) -> Result<GuestPtr<'a, T>, MemoryError> {
let r = Region {
start: at,
len: T::len(),
len: T::size(),
};
let mut borrows = self.borrows.borrow_mut();
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> {
let r = Region {
start: at,
len: T::len(),
len: T::size(),
};
let mut borrows = self.borrows.borrow_mut();
if !self.contains(r) {
@@ -77,10 +77,19 @@ pub struct GuestPtr<'a, T> {
type_: PhantomData<T>,
}
impl<'a, T> GuestPtr<'a, T> {
impl<'a, T: GuestType> GuestPtr<'a, T> {
pub fn ptr(&self) -> *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> {