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 {
|
||||
match tref {
|
||||
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!(#[derive(Copy, Clone, Debug, std::hash::Hash, Eq, PartialEq)]));
|
||||
|
||||
let mut inner = TokenStream::new();
|
||||
for variant in &e.variants {
|
||||
let mut variants = TokenStream::new();
|
||||
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);
|
||||
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 {
|
||||
#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
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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> {
|
||||
|
||||
Reference in New Issue
Block a user