diff --git a/crates/generate/src/errors.rs b/crates/generate/src/errors.rs deleted file mode 100644 index 2dc2f243b0..0000000000 --- a/crates/generate/src/errors.rs +++ /dev/null @@ -1,57 +0,0 @@ -use crate::names::Names; -use heck::SnakeCase; -use proc_macro2::TokenStream; -use quote::{format_ident, quote}; -use std::collections::HashSet; -use witx::{Document, TypeRef}; - -/// The context struct needs to implement a trait for converting memory and value errors into the -/// witx doc's error types. -/// -// XXX im rethinking this. maybe each error type should impl -// pub trait WitxErrorType { -// type Context; -// fn is_success(&self) -> bool; -// fn from_memory_error(memory_error: MemoryError, ctx: &mut Context) -> Self; -// fn from_value_error(value_error: GuestValueError, ctx: &mut Context) -> Self; -// } -// -// where Context is mapped to their wasi ctx. -// It seems less "magic" to leave that impl up to the user, and the error message may be simpler? -// -pub fn define_error_trait(names: &Names, doc: &Document) -> TokenStream { - // All non-anonymous first return types are used to pass errors. - let error_typenames = doc - .modules() - .flat_map(|m| { - m.funcs() - .filter_map(|f| { - f.results.get(0).and_then(|r| match &r.tref { - TypeRef::Name(nt) => Some(nt.name.clone()), - _ => None, - }) - }) - .collect::>() - }) - .collect::>(); - - let methods = error_typenames.iter().map(|typename| { - let tname = names.type_(typename); - let methodfragment = typename.as_str().to_snake_case(); - let success = format_ident!("success_to_{}", methodfragment); - let memory_error = format_ident!("memory_error_to_{}", methodfragment); - let value_error = format_ident!("value_error_to_{}", methodfragment); - - quote! { - fn #success(&mut self) -> #tname; - fn #memory_error(&mut self, err: ::memory::MemoryError) -> #tname; - fn #value_error(&mut self, err: ::memory::GuestValueError) -> #tname; - } - }); - - quote!( - pub trait WitxErrorConversion { - #(#methods)* - } - ) -} diff --git a/crates/generate/src/lib.rs b/crates/generate/src/lib.rs index 830e92e900..76e1014c7e 100644 --- a/crates/generate/src/lib.rs +++ b/crates/generate/src/lib.rs @@ -1,6 +1,5 @@ extern crate proc_macro; -mod errors; mod funcs; mod names; mod parse; @@ -10,7 +9,6 @@ use proc_macro::TokenStream; use proc_macro2::TokenStream as TokenStream2; use quote::quote; -use errors::define_error_trait; use funcs::define_func; use names::Names; use types::define_datatype; @@ -39,12 +37,9 @@ pub fn from_witx(args: TokenStream) -> TokenStream { ) }); - let error_trait = define_error_trait(&names, &doc); - TokenStream::from(quote!( mod types { #(#types)* - #error_trait } #(#modules)* )) diff --git a/crates/memory/src/guest_type.rs b/crates/memory/src/guest_type.rs index 820e3b28f2..933b11c33e 100644 --- a/crates/memory/src/guest_type.rs +++ b/crates/memory/src/guest_type.rs @@ -1,4 +1,4 @@ -use crate::{GuestPtr, GuestPtrMut}; +use crate::{GuestPtr, GuestPtrMut, MemoryError}; use thiserror::Error; pub trait GuestType: Sized { @@ -66,3 +66,10 @@ macro_rules! builtin_copy { // 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); + +pub trait GuestError { + type Context; + fn is_success(&self) -> bool; + fn from_memory_error(memory_error: MemoryError, ctx: &mut Self::Context) -> Self; + fn from_value_error(value_error: GuestValueError, ctx: &mut Self::Context) -> Self; +} diff --git a/crates/memory/src/lib.rs b/crates/memory/src/lib.rs index efc2317a47..872c556b15 100644 --- a/crates/memory/src/lib.rs +++ b/crates/memory/src/lib.rs @@ -3,6 +3,6 @@ mod guest_type; mod memory; mod region; -pub use guest_type::{GuestType, GuestTypeClone, GuestTypeCopy, GuestValueError}; +pub use guest_type::{GuestError, GuestType, GuestTypeClone, GuestTypeCopy, GuestValueError}; pub use memory::{GuestMemory, GuestPtr, GuestPtrMut, MemoryError}; pub use region::Region; diff --git a/src/lib.rs b/src/lib.rs index a146077675..cdb98b3dd4 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,18 +1,30 @@ pub mod test { + // FIXME: parameterize macro on what ctx type is used here generate::from_witx!("test.witx"); - pub struct WasiCtx {} // FIXME: parameterize macro on what ctx type is used here + pub struct WasiCtx { + mem_errors: Vec<::memory::MemoryError>, + value_errors: Vec<::memory::GuestValueError>, + } - impl types::WitxErrorConversion for WasiCtx { - fn success_to_errno(&mut self) -> types::Errno { - types::Errno::Ok + // Errno is used as a first return value in the functions above, therefore + // it must implement GuestError with type Context = WasiCtx. + // The context type should let you do logging or debugging or whatever you need + // with these errors. We just push them to vecs. + impl ::memory::GuestError for types::Errno { + type Context = WasiCtx; + fn is_success(&self) -> bool { + match self { + types::Errno::Ok => true, + _ => false, + } } - fn memory_error_to_errno(&mut self, e: ::memory::MemoryError) -> types::Errno { - eprintln!("memory error: {:?}", e); + fn from_memory_error(e: ::memory::MemoryError, ctx: &mut WasiCtx) -> types::Errno { + ctx.mem_errors.push(e); types::Errno::InvalidArg } - fn value_error_to_errno(&mut self, e: ::memory::GuestValueError) -> types::Errno { - eprintln!("guest value error: {:?}", e); + fn from_value_error(e: ::memory::GuestValueError, ctx: &mut WasiCtx) -> types::Errno { + ctx.value_errors.push(e); types::Errno::InvalidArg } }