webidl: initial enum support

Add enum support to the WebIDL interface generator.
This commit is contained in:
Stephan Wolski
2018-07-08 22:09:00 -04:00
parent 94d939f4da
commit a981dfd507
10 changed files with 239 additions and 12 deletions

View File

@ -41,6 +41,7 @@ pub enum ImportKind {
Function(ImportFunction),
Static(ImportStatic),
Type(ImportType),
Enum(ImportEnum),
}
#[cfg_attr(feature = "extra-traits", derive(Debug, PartialEq, Eq))]
@ -99,6 +100,18 @@ pub struct ImportType {
pub attrs: Vec<syn::Attribute>,
}
#[cfg_attr(feature = "extra-traits", derive(Debug, PartialEq, Eq))]
pub struct ImportEnum {
/// The Rust enum's visibility
pub vis: syn::Visibility,
/// The Rust enum's identifiers
pub name: Ident,
/// The Rust identifiers for the variants
pub variants: Vec<Ident>,
/// The JS string values of the variants
pub variant_values: Vec<String>,
}
#[cfg_attr(feature = "extra-traits", derive(Debug, PartialEq, Eq))]
pub struct Function {
pub name: Ident,
@ -279,6 +292,7 @@ impl ImportKind {
ImportKind::Function(_) => true,
ImportKind::Static(_) => false,
ImportKind::Type(_) => false,
ImportKind::Enum(_) => false,
}
}
@ -287,6 +301,7 @@ impl ImportKind {
ImportKind::Function(ref f) => shared::ImportKind::Function(f.shared()),
ImportKind::Static(ref f) => shared::ImportKind::Static(f.shared()),
ImportKind::Type(ref f) => shared::ImportKind::Type(f.shared()),
ImportKind::Enum(ref f) => shared::ImportKind::Enum(f.shared()),
}
}
}
@ -364,6 +379,12 @@ impl ImportType {
}
}
impl ImportEnum {
fn shared(&self) -> shared::ImportEnum {
shared::ImportEnum {}
}
}
impl Struct {
fn shared(&self) -> shared::Struct {
shared::Struct {

View File

@ -4,7 +4,7 @@ use std::env;
use std::sync::atomic::{AtomicUsize, Ordering, ATOMIC_USIZE_INIT};
use ast;
use proc_macro2::{Ident, Span, TokenStream};
use proc_macro2::{Ident, Literal, Span, TokenStream};
use quote::ToTokens;
use serde_json;
use shared;
@ -500,6 +500,7 @@ impl ToTokens for ast::ImportKind {
ast::ImportKind::Function(ref f) => f.to_tokens(tokens),
ast::ImportKind::Static(ref s) => s.to_tokens(tokens),
ast::ImportKind::Type(ref t) => t.to_tokens(tokens),
ast::ImportKind::Enum(ref e) => e.to_tokens(tokens),
}
}
}
@ -586,6 +587,98 @@ impl ToTokens for ast::ImportType {
}
}
impl ToTokens for ast::ImportEnum {
fn to_tokens(&self, tokens: &mut TokenStream) {
let vis = &self.vis;
let name = &self.name;
let name_string = &self.name.to_string();
let variants = &self.variants;
let variant_strings = &self.variant_values;
let mut current_idx: usize = 0;
let variant_indexes: Vec<Literal> = variants
.iter()
.map(|_| {
let this_index = current_idx;
current_idx += 1;
Literal::usize_unsuffixed(this_index)
})
.collect();
// Borrow variant_indexes because we need to use it multiple times inside the quote! macro
let variant_indexes_ref = &variant_indexes;
// A vector of EnumName::VariantName tokens for this enum
let variant_paths: Vec<TokenStream> = self
.variants
.iter()
.map(|v| quote!(#name::#v).into_token_stream())
.collect();
// Borrow variant_paths because we need to use it multiple times inside the quote! macro
let variant_paths_ref = &variant_paths;
(quote! {
#[allow(bad_style)]
#[derive(Copy, Clone, Debug)]
#vis enum #name {
#(#variants = #variant_indexes_ref,)*
}
impl ::wasm_bindgen::describe::WasmDescribe for #name {
fn describe() {
::wasm_bindgen::JsValue::describe()
}
}
impl ::wasm_bindgen::convert::IntoWasmAbi for #name {
type Abi = <::wasm_bindgen::JsValue as
::wasm_bindgen::convert::IntoWasmAbi>::Abi;
fn into_abi(self, extra: &mut ::wasm_bindgen::convert::Stack) -> Self::Abi {
match self {
#(#variant_paths_ref => ::wasm_bindgen::JsValue::from_str(#variant_strings).into_abi(extra),)*
}
}
}
impl ::wasm_bindgen::convert::FromWasmAbi for #name {
type Abi = <::wasm_bindgen::JsValue as
::wasm_bindgen::convert::FromWasmAbi>::Abi;
unsafe fn from_abi(
js: Self::Abi,
extra: &mut ::wasm_bindgen::convert::Stack,
) -> Self {
#name::from(::wasm_bindgen::JsValue::from_abi(js, extra))
}
}
impl From<::wasm_bindgen::JsValue> for #name {
fn from(obj: ::wasm_bindgen::JsValue) -> #name {
let obj_str = match obj.as_string() {
Some(string_value) => string_value,
None => panic!("Can't convert a non-string into {}", #name_string),
};
match obj_str.as_str() {
#(#variant_strings => #variant_paths_ref,)*
unknown_value => panic!("Can't convert \"{}\" into {}", unknown_value, #name_string),
}
}
}
impl From<#name> for ::wasm_bindgen::JsValue {
fn from(obj: #name) -> ::wasm_bindgen::JsValue {
match obj {
#(#variant_paths_ref => ::wasm_bindgen::JsValue::from_str(#variant_strings)),*
}
}
}
}).to_tokens(tokens);
}
}
impl ToTokens for ast::ImportFunction {
fn to_tokens(&self, tokens: &mut TokenStream) {
let mut class_ty = None;
@ -755,6 +848,7 @@ impl<'a> ToTokens for DescribeImport<'a> {
ast::ImportKind::Function(ref f) => f,
ast::ImportKind::Static(_) => return,
ast::ImportKind::Type(_) => return,
ast::ImportKind::Enum(_) => return,
};
let describe_name = format!("__wbindgen_describe_{}", f.shim);
let describe_name = Ident::new(&describe_name, Span::call_site());

View File

@ -105,6 +105,7 @@ impl ImportedTypes for ast::ImportKind {
ast::ImportKind::Static(s) => s.imported_types(f),
ast::ImportKind::Function(fun) => fun.imported_types(f),
ast::ImportKind::Type(ty) => ty.imported_types(f),
ast::ImportKind::Enum(enm) => enm.imported_types(f),
}
}
}
@ -210,6 +211,15 @@ impl ImportedTypes for ast::ImportType {
}
}
impl ImportedTypes for ast::ImportEnum {
fn imported_types<F>(&self, f: &mut F)
where
F: FnMut(&Ident, ImportedTypeKind),
{
f(&self.name, ImportedTypeKind::Definition);
}
}
impl ImportedTypes for ast::TypeAlias {
fn imported_types<F>(&self, f: &mut F)
where