From 45543c545e772dc5c4040b9fdfe821f0ab6a0a71 Mon Sep 17 00:00:00 2001 From: Ryan Levick Date: Thu, 22 Feb 2018 10:55:44 +0100 Subject: [PATCH] Pass numbers in js as enums to Rust successfully --- crates/wasm-bindgen-cli-support/src/js.rs | 3 ++- crates/wasm-bindgen-macro/src/ast.rs | 22 ++++++++--------- crates/wasm-bindgen-macro/src/lib.rs | 29 +++++++++++++++-------- 3 files changed, 31 insertions(+), 23 deletions(-) diff --git a/crates/wasm-bindgen-cli-support/src/js.rs b/crates/wasm-bindgen-cli-support/src/js.rs index 3108beb6..37ec69fc 100644 --- a/crates/wasm-bindgen-cli-support/src/js.rs +++ b/crates/wasm-bindgen-cli-support/src/js.rs @@ -1051,7 +1051,8 @@ impl<'a, 'b> SubContext<'a, 'b> { passed_args.push_str(arg); }; match *arg { - shared::TYPE_NUMBER => { + shared::TYPE_ENUM | shared::TYPE_NUMBER => { + // TODO: TS for Enum dst_ts.push_str(": number"); if self.cx.config.debug { self.cx.expose_assert_num(); diff --git a/crates/wasm-bindgen-macro/src/ast.rs b/crates/wasm-bindgen-macro/src/ast.rs index 1899a6dc..2904ed0c 100644 --- a/crates/wasm-bindgen-macro/src/ast.rs +++ b/crates/wasm-bindgen-macro/src/ast.rs @@ -49,7 +49,8 @@ pub struct Struct { } pub struct Enum { - pub name: syn::Ident + pub name: syn::Ident, + pub variants: Vec } pub enum Type { @@ -211,20 +212,17 @@ impl Program { _ => panic!("only public enums are allowed"), } - let all_fields_unit = item.variants.iter().all(|ref v| { + let variants = item.variants.iter().map(|ref v| { match v.fields { - syn::Fields::Unit => true, - _ => false + syn::Fields::Unit => (), + _ => panic!("Only C-Style enums allowed") } + v.ident + }).collect(); + self.enums.push(Enum { + name: item.ident, + variants }); - if all_fields_unit { - self.enums.push(Enum { - name: item.ident - }); - - } else { - panic!("Only C-Style enums allowed") - } } pub fn push_foreign_fn(&mut self, diff --git a/crates/wasm-bindgen-macro/src/lib.rs b/crates/wasm-bindgen-macro/src/lib.rs index 039d23ff..c47d362e 100644 --- a/crates/wasm-bindgen-macro/src/lib.rs +++ b/crates/wasm-bindgen-macro/src/lib.rs @@ -516,26 +516,35 @@ fn bindgen_import(import: &ast::Import, tokens: &mut Tokens) { fn bindgen_enum(e: &ast::Enum, into: &mut Tokens) { let name = &e.name; - let c = shared::name_to_descriptor(name.as_ref()) as u32; - (my_quote! { - impl #name { - fn from_usize(n: usize) -> #name { - #name::Blue + let c = shared::TYPE_ENUM as u32; + let incoming_u32 = quote! { n }; + let name_as_string = name.to_string(); + let cast_clauses = e.variants.iter().map(|ident| { + quote! { + if #incoming_u32 == #name::#ident as u32 { + #name::#ident } } + }); + (my_quote! { + impl #name { + fn from_u32(#incoming_u32: u32) -> #name { + #(#cast_clauses else)* { + wasm_bindgen::throw(&format!("Could not cast {} as {}", #incoming_u32, #name_as_string)); + } + } + } + impl ::wasm_bindgen::convert::WasmBoundary for #name { type Js = u32; const DESCRIPTOR: u32 = #c; fn into_js(self) -> u32 { - Box::into_raw(Box::new(self as u32)) as u32 + self as u32 } unsafe fn from_js(js: u32) -> Self { - let js = js as *mut usize; - ::wasm_bindgen::__rt::assert_not_null(js); - let js = Box::from_raw(js); - #name::from_usize(*js) + #name::from_u32(js) } } }).to_tokens(into);