Create Rust wrapping code for enums

This commit is contained in:
Ryan Levick 2018-02-22 00:55:11 +01:00
parent 0f8524da3c
commit 01c31cb33d
3 changed files with 65 additions and 1 deletions

View File

@ -9,6 +9,7 @@ use syn;
pub struct Program {
pub exports: Vec<Export>,
pub imports: Vec<Import>,
pub enums: Vec<Enum>,
pub imported_types: Vec<(syn::Visibility, syn::Ident)>,
pub structs: Vec<Struct>,
}
@ -47,6 +48,10 @@ pub struct Struct {
pub name: syn::Ident,
}
pub struct Enum {
pub name: syn::Ident
}
pub enum Type {
// special
Vector(VectorType, bool),
@ -110,8 +115,13 @@ impl Program {
let opts = opts.unwrap_or_else(|| BindgenAttrs::find(&mut f.attrs));
self.push_foreign_mod(f, opts);
}
syn::Item::Enum(mut e) => {
let opts = opts.unwrap_or_else(|| BindgenAttrs::find(&mut e.attrs));
e.to_tokens(tokens);
self.push_enum(e, opts);
}
_ => panic!("#[wasm_bindgen] can only be applied to a function, \
struct, impl, or extern block"),
struct, enum, impl, or extern block"),
}
}
@ -195,6 +205,28 @@ impl Program {
}
}
pub fn push_enum(&mut self, item: syn::ItemEnum, opts: BindgenAttrs) {
match item.vis {
syn::Visibility::Public(_) => {}
_ => panic!("only public enums are allowed"),
}
let all_fields_unit = item.variants.iter().all(|ref v| {
match v.fields {
syn::Fields::Unit => true,
_ => false
}
});
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,
mut f: syn::ForeignItemFn,
module_opts: &BindgenAttrs) {
@ -301,6 +333,7 @@ impl Program {
let names = self.exports.iter()
.filter_map(|e| e.class)
.chain(self.structs.iter().map(|s| s.name))
.chain(self.enums.iter().map(|s| s.name))
.collect::<BTreeSet<_>>();
a.list(&names, |s, a| {
let val = shared::name_to_descriptor(s.as_ref());

View File

@ -50,6 +50,9 @@ fn generate_wrappers(program: ast::Program, tokens: &mut Tokens) {
for i in program.imports.iter() {
bindgen_import(i, tokens);
}
for e in program.enums.iter() {
bindgen_enum(e, tokens);
}
for &(ref vis, ref t) in program.imported_types.iter() {
bindgen_imported_type(vis, t, tokens);
}
@ -510,3 +513,30 @@ fn bindgen_import(import: &ast::Import, tokens: &mut Tokens) {
invocation.to_tokens(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
}
}
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
}
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)
}
}
}).to_tokens(into);
}

View File

@ -77,6 +77,7 @@ pub fn mangled_import_name(struct_: Option<&str>, f: &str) -> String {
pub type Type = char;
pub const TYPE_ENUM: char = '\u{5d}';
pub const TYPE_NUMBER: char = '\u{5e}';
pub const TYPE_BORROWED_STR: char = '\u{5f}';
pub const TYPE_STRING: char = '\u{60}';