From f7838761923f3db964197bdff12b043a8b6d35c0 Mon Sep 17 00:00:00 2001 From: Ryan Levick Date: Fri, 23 Feb 2018 14:17:53 +0100 Subject: [PATCH] Support C-Style enums with custom int values --- crates/wasm-bindgen-cli-support/src/js.rs | 4 +--- crates/wasm-bindgen-macro/src/ast.rs | 21 ++++++++++++++++++--- crates/wasm-bindgen-macro/src/lib.rs | 21 +++++++++++---------- crates/wasm-bindgen-shared/src/lib.rs | 3 ++- 4 files changed, 32 insertions(+), 17 deletions(-) diff --git a/crates/wasm-bindgen-cli-support/src/js.rs b/crates/wasm-bindgen-cli-support/src/js.rs index c37ab978..b19767e2 100644 --- a/crates/wasm-bindgen-cli-support/src/js.rs +++ b/crates/wasm-bindgen-cli-support/src/js.rs @@ -1434,10 +1434,8 @@ impl<'a, 'b> SubContext<'a, 'b> { pub fn generate_enum(&mut self, enum_: &shared::Enum) { let mut variants = String::new(); - let mut value = 0; for variant in enum_.variants.iter() { - variants.push_str(&format!("{}:{},", variant.name, value)); - value = value + 1; + variants.push_str(&format!("{}:{},", variant.name, variant.value)); } self.cx.globals.push_str(&format!("export const {} = {{", enum_.name)); self.cx.globals.push_str(&variants); diff --git a/crates/wasm-bindgen-macro/src/ast.rs b/crates/wasm-bindgen-macro/src/ast.rs index bde31d8d..7e7ee196 100644 --- a/crates/wasm-bindgen-macro/src/ast.rs +++ b/crates/wasm-bindgen-macro/src/ast.rs @@ -50,7 +50,7 @@ pub struct Struct { pub struct Enum { pub name: syn::Ident, - pub variants: Vec + pub variants: Vec<(syn::Ident, u32)> } pub enum Type { @@ -212,12 +212,25 @@ impl Program { _ => panic!("only public enums are allowed"), } + let mut i = 0; let variants = item.variants.iter().map(|ref v| { match v.fields { syn::Fields::Unit => (), _ => panic!("Only C-Style enums allowed") } - v.ident + let value = match v.discriminant { + Some((_, syn::Expr::Lit(syn::ExprLit {attrs: _, lit: syn::Lit::Int(ref int_lit)}))) => { + if int_lit.value() > ::max_value() as u64 { + panic!("Enums can only support numbers that can be represented as u32"); + } + int_lit.value() as u32 + }, + None => i, + _ => panic!("Enums may only have number literal values") + }; + + i = i + 1; + (v.ident, value) }).collect(); self.enums.push(Enum { name: item.ident, @@ -670,7 +683,9 @@ impl Enum { a.fields(&[ ("name", &|a| a.str(self.name.as_ref())), ("variants", &|a| a.list(&self.variants, |v, a| { - a.fields(&[("name", &|a| a.str(v.as_ref()))]) + let &(name, value) = v; + a.fields(&[("name", &|a| a.str(name.as_ref())), + ("value", &|a| a.append(&format!("{}", value)))]) })), ]); } diff --git a/crates/wasm-bindgen-macro/src/lib.rs b/crates/wasm-bindgen-macro/src/lib.rs index c47d362e..13544e5b 100644 --- a/crates/wasm-bindgen-macro/src/lib.rs +++ b/crates/wasm-bindgen-macro/src/lib.rs @@ -515,27 +515,28 @@ fn bindgen_import(import: &ast::Import, tokens: &mut Tokens) { } fn bindgen_enum(e: &ast::Enum, into: &mut Tokens) { - let name = &e.name; + let enum_name = &e.name; 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| { + let enum_name_as_string = enum_name.to_string(); + let cast_clauses = e.variants.iter().map(|variant| { + let &(variant_name, _) = variant; quote! { - if #incoming_u32 == #name::#ident as u32 { - #name::#ident + if #incoming_u32 == #enum_name::#variant_name as u32 { + #enum_name::#variant_name } } }); (my_quote! { - impl #name { - fn from_u32(#incoming_u32: u32) -> #name { + impl #enum_name { + fn from_u32(#incoming_u32: u32) -> #enum_name { #(#cast_clauses else)* { - wasm_bindgen::throw(&format!("Could not cast {} as {}", #incoming_u32, #name_as_string)); + wasm_bindgen::throw(&format!("Could not cast {} as {}", #incoming_u32, #enum_name_as_string)); } } } - impl ::wasm_bindgen::convert::WasmBoundary for #name { + impl ::wasm_bindgen::convert::WasmBoundary for #enum_name { type Js = u32; const DESCRIPTOR: u32 = #c; @@ -544,7 +545,7 @@ fn bindgen_enum(e: &ast::Enum, into: &mut Tokens) { } unsafe fn from_js(js: u32) -> Self { - #name::from_u32(js) + #enum_name::from_u32(js) } } }).to_tokens(into); diff --git a/crates/wasm-bindgen-shared/src/lib.rs b/crates/wasm-bindgen-shared/src/lib.rs index 7d85eeeb..62d0d220 100644 --- a/crates/wasm-bindgen-shared/src/lib.rs +++ b/crates/wasm-bindgen-shared/src/lib.rs @@ -41,7 +41,8 @@ pub struct Enum { #[derive(Deserialize)] pub struct EnumVariant { - pub name: String + pub name: String, + pub value: u32 } #[derive(Deserialize)]