diff --git a/crates/wiggle/generate/src/funcs.rs b/crates/wiggle/generate/src/funcs.rs index a12910c914..d9f59acf6b 100644 --- a/crates/wiggle/generate/src/funcs.rs +++ b/crates/wiggle/generate/src/funcs.rs @@ -58,9 +58,10 @@ pub fn define_func(names: &Names, func: &witx::InterfaceFunc) -> TokenStream { _ => unreachable!("err should always be passed by value"), }; let err_typename = names.type_ref(&tref, anon_lifetime()); + let err_method = names.guest_error_conversion_method(&tref); quote! { let e = wiggle::GuestError::InFunc { funcname: #funcname, location: #location, err: Box::new(e.into()) }; - let err: #err_typename = wiggle::GuestErrorType::from_error(e, ctx); // XXX replace with conversion method on trait! + let err: #err_typename = GuestErrorConversion::#err_method(ctx, e); // XXX replace with conversion method on trait! return #abi_ret::from(err); } } else { diff --git a/crates/wiggle/generate/src/lib.rs b/crates/wiggle/generate/src/lib.rs index f67761850a..de140c52dd 100644 --- a/crates/wiggle/generate/src/lib.rs +++ b/crates/wiggle/generate/src/lib.rs @@ -8,6 +8,8 @@ mod types; use proc_macro2::TokenStream; use quote::quote; +use lifetimes::anon_lifetime; + pub use config::Config; pub use funcs::define_func; pub use module_trait::define_module_trait; @@ -19,6 +21,17 @@ pub fn generate(doc: &witx::Document, config: &Config) -> TokenStream { let types = doc.typenames().map(|t| define_datatype(&names, &t)); + let guest_error_methods = doc.error_types().map(|t| { + let typename = names.type_ref(&t, anon_lifetime()); + let err_method = names.guest_error_conversion_method(&t); + quote!(fn #err_method(&self, e: wiggle::GuestError) -> #typename;) + }); + let guest_error_conversion = quote! { + pub trait GuestErrorConversion { + #(#guest_error_methods)* + } + }; + let modules = doc.modules().map(|module| { let modname = names.module(&module.name); let fs = module.funcs().map(|f| define_func(&names, &f)); @@ -52,6 +65,7 @@ pub fn generate(doc: &witx::Document, config: &Config) -> TokenStream { quote!( pub mod types { #(#types)* + #guest_error_conversion } #(#modules)* #metadata diff --git a/crates/wiggle/generate/src/names.rs b/crates/wiggle/generate/src/names.rs index 5879f6605b..dd080368d8 100644 --- a/crates/wiggle/generate/src/names.rs +++ b/crates/wiggle/generate/src/names.rs @@ -1,7 +1,7 @@ use heck::{CamelCase, ShoutySnakeCase, SnakeCase}; use proc_macro2::{Ident, TokenStream}; use quote::{format_ident, quote}; -use witx::{AtomType, BuiltinType, Id, TypeRef}; +use witx::{AtomType, BuiltinType, Id, Type, TypeRef}; use crate::lifetimes::LifetimeExt; use crate::Config; @@ -61,12 +61,12 @@ impl Names { } } TypeRef::Value(ty) => match &**ty { - witx::Type::Builtin(builtin) => self.builtin_type(*builtin, lifetime.clone()), - witx::Type::Pointer(pointee) | witx::Type::ConstPointer(pointee) => { + Type::Builtin(builtin) => self.builtin_type(*builtin, lifetime.clone()), + Type::Pointer(pointee) | Type::ConstPointer(pointee) => { let pointee_type = self.type_ref(&pointee, lifetime.clone()); quote!(wiggle::GuestPtr<#lifetime, #pointee_type>) } - witx::Type::Array(pointee) => { + Type::Array(pointee) => { let pointee_type = self.type_ref(&pointee, lifetime.clone()); quote!(wiggle::GuestPtr<#lifetime, [#pointee_type]>) } @@ -141,4 +141,28 @@ impl Names { pub fn func_len_binding(&self, id: &Id) -> Ident { format_ident!("{}_len", id.as_str().to_snake_case()) } + + pub fn guest_error_conversion_method(&self, tref: &TypeRef) -> Ident { + match tref { + TypeRef::Name(nt) => format_ident!("into_{}", nt.name.as_str().to_snake_case()), + TypeRef::Value(ty) => match &**ty { + Type::Builtin(b) => match b { + BuiltinType::String => unreachable!("error type must be atom"), + BuiltinType::U8 => format_ident!("into_u8"), + BuiltinType::U16 => format_ident!("into_u16"), + BuiltinType::U32 => format_ident!("into_u32"), + BuiltinType::U64 => format_ident!("into_u64"), + BuiltinType::S8 => format_ident!("into_i8"), + BuiltinType::S16 => format_ident!("into_i16"), + BuiltinType::S32 => format_ident!("into_i32"), + BuiltinType::S64 => format_ident!("into_i64"), + BuiltinType::F32 => format_ident!("into_f32"), + BuiltinType::F64 => format_ident!("into_f64"), + BuiltinType::Char8 => format_ident!("into_char8"), + BuiltinType::USize => format_ident!("into_usize"), + }, + _ => panic!("unexpected anonymous error type: {:?}", ty), + }, + } + } } diff --git a/crates/wiggle/test-helpers/src/lib.rs b/crates/wiggle/test-helpers/src/lib.rs index f41515be52..42719672b2 100644 --- a/crates/wiggle/test-helpers/src/lib.rs +++ b/crates/wiggle/test-helpers/src/lib.rs @@ -313,11 +313,17 @@ impl<'a> WasiCtx<'a> { // with these errors. We just push them to vecs. #[macro_export] macro_rules! impl_errno { - ( $errno:ty ) => { + ( $errno:ty, $convert:path ) => { impl wiggle::GuestErrorType for $errno { fn success() -> $errno { <$errno>::Ok } } + impl<'a> $convert for WasiCtx<'a> { + fn into_errno(&self, e: wiggle::GuestError) -> $errno { + eprintln!("GuestError: {:?}", e); + <$errno>::InvalidArg + } + } }; } diff --git a/crates/wiggle/tests/arrays.rs b/crates/wiggle/tests/arrays.rs index 49bbc1fdb9..52d6c4b345 100644 --- a/crates/wiggle/tests/arrays.rs +++ b/crates/wiggle/tests/arrays.rs @@ -1,5 +1,5 @@ use proptest::prelude::*; -use wiggle::{GuestError, GuestMemory, GuestPtr}; +use wiggle::{GuestMemory, GuestPtr}; use wiggle_test::{impl_errno, HostMemory, MemArea, WasiCtx}; wiggle::from_witx!({ @@ -7,7 +7,7 @@ wiggle::from_witx!({ ctx: WasiCtx, }); -impl_errno!(types::Errno); +impl_errno!(types::Errno, types::GuestErrorConversion); impl<'a> arrays::Arrays for WasiCtx<'a> { fn reduce_excuses( diff --git a/crates/wiggle/tests/atoms.rs b/crates/wiggle/tests/atoms.rs index e366ef291f..5407828fa9 100644 --- a/crates/wiggle/tests/atoms.rs +++ b/crates/wiggle/tests/atoms.rs @@ -1,5 +1,5 @@ use proptest::prelude::*; -use wiggle::{GuestError, GuestMemory}; +use wiggle::GuestMemory; use wiggle_test::{impl_errno, HostMemory, MemArea, WasiCtx}; wiggle::from_witx!({ @@ -7,7 +7,7 @@ wiggle::from_witx!({ ctx: WasiCtx, }); -impl_errno!(types::Errno); +impl_errno!(types::Errno, types::GuestErrorConversion); impl<'a> atoms::Atoms for WasiCtx<'a> { fn int_float_args(&self, an_int: u32, an_float: f32) -> Result<(), types::Errno> { diff --git a/crates/wiggle/tests/flags.rs b/crates/wiggle/tests/flags.rs index dd4a6283bf..fcb07e7a7d 100644 --- a/crates/wiggle/tests/flags.rs +++ b/crates/wiggle/tests/flags.rs @@ -1,6 +1,6 @@ use proptest::prelude::*; use std::convert::TryFrom; -use wiggle::{GuestError, GuestMemory, GuestPtr}; +use wiggle::{GuestMemory, GuestPtr}; use wiggle_test::{impl_errno, HostMemory, MemArea, WasiCtx}; wiggle::from_witx!({ @@ -8,7 +8,7 @@ wiggle::from_witx!({ ctx: WasiCtx, }); -impl_errno!(types::Errno); +impl_errno!(types::Errno, types::GuestErrorConversion); impl<'a> flags::Flags for WasiCtx<'a> { fn configure_car( diff --git a/crates/wiggle/tests/handles.rs b/crates/wiggle/tests/handles.rs index dff979fb56..93e3b54d18 100644 --- a/crates/wiggle/tests/handles.rs +++ b/crates/wiggle/tests/handles.rs @@ -1,5 +1,5 @@ use proptest::prelude::*; -use wiggle::{GuestError, GuestMemory, GuestType}; +use wiggle::{GuestMemory, GuestType}; use wiggle_test::{impl_errno, HostMemory, MemArea, WasiCtx}; const FD_VAL: u32 = 123; @@ -9,7 +9,7 @@ wiggle::from_witx!({ ctx: WasiCtx, }); -impl_errno!(types::Errno); +impl_errno!(types::Errno, types::GuestErrorConversion); impl<'a> handle_examples::HandleExamples for WasiCtx<'a> { fn fd_create(&self) -> Result { diff --git a/crates/wiggle/tests/ints.rs b/crates/wiggle/tests/ints.rs index 3a192b09a4..36d7933e62 100644 --- a/crates/wiggle/tests/ints.rs +++ b/crates/wiggle/tests/ints.rs @@ -1,6 +1,6 @@ use proptest::prelude::*; use std::convert::TryFrom; -use wiggle::{GuestError, GuestMemory}; +use wiggle::GuestMemory; use wiggle_test::{impl_errno, HostMemory, MemArea, WasiCtx}; wiggle::from_witx!({ @@ -8,7 +8,7 @@ wiggle::from_witx!({ ctx: WasiCtx, }); -impl_errno!(types::Errno); +impl_errno!(types::Errno, types::GuestErrorConversion); impl<'a> ints::Ints for WasiCtx<'a> { fn cookie_cutter(&self, init_cookie: types::Cookie) -> Result { diff --git a/crates/wiggle/tests/pointers.rs b/crates/wiggle/tests/pointers.rs index 2c8841c4e6..c39988d115 100644 --- a/crates/wiggle/tests/pointers.rs +++ b/crates/wiggle/tests/pointers.rs @@ -1,5 +1,5 @@ use proptest::prelude::*; -use wiggle::{GuestError, GuestMemory, GuestPtr}; +use wiggle::{GuestMemory, GuestPtr}; use wiggle_test::{impl_errno, HostMemory, MemArea, WasiCtx}; wiggle::from_witx!({ @@ -7,7 +7,7 @@ wiggle::from_witx!({ ctx: WasiCtx, }); -impl_errno!(types::Errno); +impl_errno!(types::Errno, types::GuestErrorConversion); impl<'a> pointers::Pointers for WasiCtx<'a> { fn pointers_and_enums<'b>( diff --git a/crates/wiggle/tests/strings.rs b/crates/wiggle/tests/strings.rs index c494cf63fc..f14920ca75 100644 --- a/crates/wiggle/tests/strings.rs +++ b/crates/wiggle/tests/strings.rs @@ -1,5 +1,5 @@ use proptest::prelude::*; -use wiggle::{GuestBorrows, GuestError, GuestMemory, GuestPtr}; +use wiggle::{GuestBorrows, GuestMemory, GuestPtr}; use wiggle_test::{impl_errno, HostMemory, MemArea, MemAreas, WasiCtx}; wiggle::from_witx!({ @@ -7,7 +7,7 @@ wiggle::from_witx!({ ctx: WasiCtx, }); -impl_errno!(types::Errno); +impl_errno!(types::Errno, types::GuestErrorConversion); impl<'a> strings::Strings for WasiCtx<'a> { fn hello_string(&self, a_string: &GuestPtr) -> Result { diff --git a/crates/wiggle/tests/structs.rs b/crates/wiggle/tests/structs.rs index 7a38c00aa6..b98cf66163 100644 --- a/crates/wiggle/tests/structs.rs +++ b/crates/wiggle/tests/structs.rs @@ -1,5 +1,5 @@ use proptest::prelude::*; -use wiggle::{GuestError, GuestMemory, GuestPtr}; +use wiggle::{GuestMemory, GuestPtr}; use wiggle_test::{impl_errno, HostMemory, MemArea, WasiCtx}; wiggle::from_witx!({ @@ -7,7 +7,7 @@ wiggle::from_witx!({ ctx: WasiCtx, }); -impl_errno!(types::Errno); +impl_errno!(types::Errno, types::GuestErrorConversion); impl<'a> structs::Structs for WasiCtx<'a> { fn sum_of_pair(&self, an_pair: &types::PairInts) -> Result { diff --git a/crates/wiggle/tests/union.rs b/crates/wiggle/tests/union.rs index d0935fd0eb..ab3dada99c 100644 --- a/crates/wiggle/tests/union.rs +++ b/crates/wiggle/tests/union.rs @@ -1,5 +1,5 @@ use proptest::prelude::*; -use wiggle::{GuestError, GuestMemory, GuestType}; +use wiggle::{GuestMemory, GuestType}; use wiggle_test::{impl_errno, HostMemory, MemArea, WasiCtx}; wiggle::from_witx!({ @@ -7,7 +7,7 @@ wiggle::from_witx!({ ctx: WasiCtx, }); -impl_errno!(types::Errno); +impl_errno!(types::Errno, types::GuestErrorConversion); // Avoid panics on overflow fn mult_lose_overflow(a: i32, b: u32) -> i32 { diff --git a/crates/wiggle/tests/wasi.rs b/crates/wiggle/tests/wasi.rs index c605be9c3f..5985d4b16b 100644 --- a/crates/wiggle/tests/wasi.rs +++ b/crates/wiggle/tests/wasi.rs @@ -29,6 +29,13 @@ impl GuestErrorType for types::Errno { } } +impl<'a> types::GuestErrorConversion for WasiCtx<'a> { + fn into_errno(&self, e: GuestError) -> types::Errno { + eprintln!("GuestError {:?}", e); + types::Errno::Badf + } +} + impl<'a> crate::wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx<'a> { fn args_get(&self, _argv: &GuestPtr>, _argv_buf: &GuestPtr) -> Result<()> { unimplemented!("args_get")