2018-02-07 16:41:33 -08:00
|
|
|
use std::collections::BTreeSet;
|
|
|
|
|
2018-01-08 10:42:01 -08:00
|
|
|
use proc_macro2::Span;
|
2018-02-06 07:56:14 -08:00
|
|
|
use quote::{Tokens, ToTokens};
|
|
|
|
use shared;
|
2017-12-14 19:31:01 -08:00
|
|
|
use syn;
|
|
|
|
|
2018-02-07 16:41:33 -08:00
|
|
|
#[derive(Default)]
|
2017-12-18 12:39:14 -08:00
|
|
|
pub struct Program {
|
2018-02-07 16:41:33 -08:00
|
|
|
pub exports: Vec<Export>,
|
2017-12-18 21:43:16 -08:00
|
|
|
pub imports: Vec<Import>,
|
2018-02-22 00:55:11 +01:00
|
|
|
pub enums: Vec<Enum>,
|
2018-02-07 16:41:33 -08:00
|
|
|
pub imported_types: Vec<(syn::Visibility, syn::Ident)>,
|
|
|
|
pub structs: Vec<Struct>,
|
2017-12-18 12:39:14 -08:00
|
|
|
}
|
|
|
|
|
2018-02-07 16:41:33 -08:00
|
|
|
pub struct Export {
|
|
|
|
pub class: Option<syn::Ident>,
|
|
|
|
pub method: bool,
|
|
|
|
pub mutable: bool,
|
|
|
|
pub function: Function,
|
2017-12-14 19:31:01 -08:00
|
|
|
}
|
|
|
|
|
2017-12-18 21:43:16 -08:00
|
|
|
pub struct Import {
|
2018-02-07 16:41:33 -08:00
|
|
|
pub module: Option<String>,
|
|
|
|
pub kind: ImportKind,
|
|
|
|
pub function: Function,
|
2018-02-05 14:24:25 -08:00
|
|
|
}
|
|
|
|
|
2018-02-07 16:41:33 -08:00
|
|
|
pub enum ImportKind {
|
|
|
|
Method { class: String, ty: syn::Type },
|
|
|
|
Static { class: String, ty: syn::Type },
|
|
|
|
JsConstructor { class: String, ty: syn::Type },
|
|
|
|
Normal,
|
2018-02-05 14:24:25 -08:00
|
|
|
}
|
|
|
|
|
2018-02-07 16:41:33 -08:00
|
|
|
pub struct Function {
|
2018-02-05 14:24:25 -08:00
|
|
|
pub name: syn::Ident,
|
2018-02-07 16:41:33 -08:00
|
|
|
pub arguments: Vec<Type>,
|
|
|
|
pub ret: Option<Type>,
|
|
|
|
pub opts: BindgenAttrs,
|
|
|
|
pub rust_attrs: Vec<syn::Attribute>,
|
|
|
|
pub rust_decl: Box<syn::FnDecl>,
|
|
|
|
pub rust_vis: syn::Visibility,
|
2018-02-06 15:19:47 -08:00
|
|
|
}
|
|
|
|
|
2018-02-07 16:41:33 -08:00
|
|
|
pub struct Struct {
|
|
|
|
pub name: syn::Ident,
|
2017-12-18 21:43:16 -08:00
|
|
|
}
|
|
|
|
|
2018-02-22 00:55:11 +01:00
|
|
|
pub struct Enum {
|
2018-02-22 10:55:44 +01:00
|
|
|
pub name: syn::Ident,
|
2018-02-23 14:17:53 +01:00
|
|
|
pub variants: Vec<(syn::Ident, u32)>
|
2018-02-22 00:55:11 +01:00
|
|
|
}
|
|
|
|
|
2017-12-14 19:31:01 -08:00
|
|
|
pub enum Type {
|
2018-02-06 07:56:14 -08:00
|
|
|
// special
|
2018-02-16 18:58:37 -08:00
|
|
|
Vector(VectorType, bool),
|
2018-02-06 07:56:14 -08:00
|
|
|
|
|
|
|
ByRef(syn::Type),
|
|
|
|
ByMutRef(syn::Type),
|
|
|
|
ByValue(syn::Type),
|
2017-12-18 12:39:14 -08:00
|
|
|
}
|
|
|
|
|
2018-02-16 18:58:37 -08:00
|
|
|
pub enum VectorType {
|
|
|
|
String,
|
|
|
|
I8,
|
|
|
|
U8,
|
|
|
|
I16,
|
|
|
|
U16,
|
|
|
|
I32,
|
|
|
|
U32,
|
|
|
|
F32,
|
|
|
|
F64,
|
2018-02-28 10:56:56 +01:00
|
|
|
JsValue,
|
2018-02-16 18:58:37 -08:00
|
|
|
}
|
|
|
|
|
2017-12-18 12:39:14 -08:00
|
|
|
impl Program {
|
2018-02-07 16:41:33 -08:00
|
|
|
pub fn push_item(&mut self,
|
|
|
|
item: syn::Item,
|
|
|
|
opts: Option<BindgenAttrs>,
|
|
|
|
tokens: &mut Tokens) {
|
|
|
|
match item {
|
|
|
|
syn::Item::Fn(mut f) => {
|
|
|
|
let opts = opts.unwrap_or_else(|| BindgenAttrs::find(&mut f.attrs));
|
|
|
|
|
|
|
|
let no_mangle = f.attrs.iter()
|
|
|
|
.enumerate()
|
|
|
|
.filter_map(|(i, m)| m.interpret_meta().map(|m| (i, m)))
|
|
|
|
.find(|&(_, ref m)| m.name() == "no_mangle");
|
|
|
|
match no_mangle {
|
|
|
|
Some((i, _)) => { f.attrs.remove(i); }
|
2018-03-05 23:25:15 +01:00
|
|
|
_ => {}
|
2018-02-07 16:41:33 -08:00
|
|
|
}
|
|
|
|
f.to_tokens(tokens);
|
|
|
|
self.exports.push(Export {
|
|
|
|
class: None,
|
|
|
|
method: false,
|
|
|
|
mutable: false,
|
|
|
|
function: Function::from(f, opts),
|
|
|
|
});
|
|
|
|
}
|
|
|
|
syn::Item::Struct(mut s) => {
|
|
|
|
let opts = opts.unwrap_or_else(|| BindgenAttrs::find(&mut s.attrs));
|
|
|
|
s.to_tokens(tokens);
|
|
|
|
self.structs.push(Struct::from(s, opts));
|
|
|
|
}
|
|
|
|
syn::Item::Impl(mut i) => {
|
|
|
|
let opts = opts.unwrap_or_else(|| BindgenAttrs::find(&mut i.attrs));
|
|
|
|
i.to_tokens(tokens);
|
|
|
|
self.push_impl(i, opts);
|
|
|
|
}
|
|
|
|
syn::Item::ForeignMod(mut f) => {
|
|
|
|
let opts = opts.unwrap_or_else(|| BindgenAttrs::find(&mut f.attrs));
|
|
|
|
self.push_foreign_mod(f, opts);
|
|
|
|
}
|
2018-02-22 00:55:11 +01:00
|
|
|
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);
|
|
|
|
}
|
2018-02-07 16:41:33 -08:00
|
|
|
_ => panic!("#[wasm_bindgen] can only be applied to a function, \
|
2018-02-22 00:55:11 +01:00
|
|
|
struct, enum, impl, or extern block"),
|
2018-02-07 16:41:33 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn push_impl(&mut self, item: syn::ItemImpl, _opts: BindgenAttrs) {
|
2017-12-31 14:40:57 -08:00
|
|
|
if item.defaultness.is_some() {
|
|
|
|
panic!("default impls are not supported");
|
2017-12-18 12:39:14 -08:00
|
|
|
}
|
2017-12-31 14:40:57 -08:00
|
|
|
if item.unsafety.is_some() {
|
|
|
|
panic!("unsafe impls are not supported");
|
2017-12-18 12:39:14 -08:00
|
|
|
}
|
|
|
|
if item.trait_.is_some() {
|
|
|
|
panic!("trait impls are not supported");
|
|
|
|
}
|
|
|
|
if item.generics.params.len() > 0 {
|
|
|
|
panic!("generic impls aren't supported");
|
|
|
|
}
|
2018-02-06 07:56:14 -08:00
|
|
|
let name = match *item.self_ty {
|
|
|
|
syn::Type::Path(syn::TypePath { qself: None, ref path }) => {
|
|
|
|
match extract_path_ident(path) {
|
|
|
|
Some(ident) => ident,
|
|
|
|
None => panic!("unsupported self type in impl"),
|
|
|
|
}
|
|
|
|
}
|
2017-12-18 12:39:14 -08:00
|
|
|
_ => panic!("unsupported self type in impl"),
|
|
|
|
};
|
2018-02-07 16:41:33 -08:00
|
|
|
for item in item.items.into_iter() {
|
|
|
|
self.push_impl_item(name, item);
|
2017-12-18 12:39:14 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-02-07 16:41:33 -08:00
|
|
|
fn push_impl_item(&mut self, class: syn::Ident, item: syn::ImplItem) {
|
|
|
|
let mut method = match item {
|
|
|
|
syn::ImplItem::Const(_) => panic!("const definitions aren't supported"),
|
|
|
|
syn::ImplItem::Type(_) => panic!("type definitions in impls aren't supported"),
|
|
|
|
syn::ImplItem::Method(m) => m,
|
|
|
|
syn::ImplItem::Macro(_) => panic!("macros in impls aren't supported"),
|
|
|
|
syn::ImplItem::Verbatim(_) => panic!("unparsed impl item?"),
|
|
|
|
};
|
|
|
|
match method.vis {
|
|
|
|
syn::Visibility::Public(_) => {}
|
|
|
|
_ => return,
|
2017-12-18 21:43:16 -08:00
|
|
|
}
|
2018-02-07 16:41:33 -08:00
|
|
|
if method.defaultness.is_some() {
|
|
|
|
panic!("default methods are not supported");
|
|
|
|
}
|
|
|
|
if method.sig.constness.is_some() {
|
|
|
|
panic!("can only bindgen non-const functions");
|
|
|
|
}
|
|
|
|
if method.sig.unsafety.is_some() {
|
|
|
|
panic!("can only bindgen safe functions");
|
2017-12-18 21:43:16 -08:00
|
|
|
}
|
|
|
|
|
2018-02-07 16:41:33 -08:00
|
|
|
let opts = BindgenAttrs::find(&mut method.attrs);
|
|
|
|
|
|
|
|
let (function, mutable) = Function::from_decl(method.sig.ident,
|
|
|
|
Box::new(method.sig.decl),
|
|
|
|
method.attrs,
|
|
|
|
opts,
|
|
|
|
method.vis,
|
|
|
|
true);
|
|
|
|
self.exports.push(Export {
|
|
|
|
class: Some(class),
|
|
|
|
method: mutable.is_some(),
|
|
|
|
mutable: mutable.unwrap_or(false),
|
|
|
|
function,
|
|
|
|
});
|
|
|
|
}
|
2017-12-18 21:43:16 -08:00
|
|
|
|
2018-02-07 16:41:33 -08:00
|
|
|
pub fn push_foreign_mod(&mut self, f: syn::ItemForeignMod, opts: BindgenAttrs) {
|
|
|
|
match f.abi.name {
|
|
|
|
Some(ref l) if l.value() == "C" => {}
|
|
|
|
None => {}
|
|
|
|
_ => panic!("only foreign mods with the `C` ABI are allowed"),
|
|
|
|
}
|
|
|
|
for item in f.items.into_iter() {
|
|
|
|
match item {
|
|
|
|
syn::ForeignItem::Fn(f) => self.push_foreign_fn(f, &opts),
|
|
|
|
syn::ForeignItem::Type(t) => self.push_foreign_ty(t, &opts),
|
|
|
|
_ => panic!("only foreign functions/types allowed for now"),
|
2018-02-05 14:24:25 -08:00
|
|
|
}
|
2018-02-07 16:41:33 -08:00
|
|
|
}
|
|
|
|
}
|
2018-02-06 19:04:12 -08:00
|
|
|
|
2018-02-22 12:08:28 +01:00
|
|
|
pub fn push_enum(&mut self, item: syn::ItemEnum, _opts: BindgenAttrs) {
|
2018-02-22 00:55:11 +01:00
|
|
|
match item.vis {
|
|
|
|
syn::Visibility::Public(_) => {}
|
|
|
|
_ => panic!("only public enums are allowed"),
|
|
|
|
}
|
|
|
|
|
2018-02-23 19:06:23 +01:00
|
|
|
let variants = item.variants.iter().enumerate().map(|(i, v)| {
|
2018-02-22 00:55:11 +01:00
|
|
|
match v.fields {
|
2018-02-22 10:55:44 +01:00
|
|
|
syn::Fields::Unit => (),
|
|
|
|
_ => panic!("Only C-Style enums allowed")
|
2018-02-22 00:55:11 +01:00
|
|
|
}
|
2018-02-23 14:17:53 +01:00
|
|
|
let value = match v.discriminant {
|
|
|
|
Some((_, syn::Expr::Lit(syn::ExprLit {attrs: _, lit: syn::Lit::Int(ref int_lit)}))) => {
|
|
|
|
if int_lit.value() > <u32>::max_value() as u64 {
|
|
|
|
panic!("Enums can only support numbers that can be represented as u32");
|
|
|
|
}
|
|
|
|
int_lit.value() as u32
|
|
|
|
},
|
2018-02-23 19:06:23 +01:00
|
|
|
None => i as u32,
|
2018-02-23 14:17:53 +01:00
|
|
|
_ => panic!("Enums may only have number literal values")
|
|
|
|
};
|
|
|
|
|
|
|
|
(v.ident, value)
|
2018-02-22 10:55:44 +01:00
|
|
|
}).collect();
|
|
|
|
self.enums.push(Enum {
|
|
|
|
name: item.ident,
|
|
|
|
variants
|
2018-02-22 00:55:11 +01:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2018-02-07 16:41:33 -08:00
|
|
|
pub fn push_foreign_fn(&mut self,
|
|
|
|
mut f: syn::ForeignItemFn,
|
|
|
|
module_opts: &BindgenAttrs) {
|
|
|
|
let opts = BindgenAttrs::find(&mut f.attrs);
|
|
|
|
|
|
|
|
let mut wasm = Function::from_decl(f.ident,
|
|
|
|
f.decl,
|
|
|
|
f.attrs,
|
|
|
|
opts,
|
|
|
|
f.vis,
|
|
|
|
false).0;
|
|
|
|
if wasm.opts.catch() {
|
2018-02-06 19:04:12 -08:00
|
|
|
// TODO: this assumes a whole bunch:
|
|
|
|
//
|
|
|
|
// * The outer type is actually a `Result`
|
|
|
|
// * The error type is a `JsValue`
|
|
|
|
// * The actual type is the first type parameter
|
|
|
|
//
|
|
|
|
// should probably fix this one day...
|
|
|
|
wasm.ret = extract_first_ty_param(wasm.ret.as_ref())
|
|
|
|
.expect("can't `catch` without returning a Result");
|
|
|
|
}
|
2018-02-05 14:24:25 -08:00
|
|
|
|
2018-02-07 16:41:33 -08:00
|
|
|
let kind = if wasm.opts.method() {
|
|
|
|
let class = wasm.arguments.get(0)
|
|
|
|
.expect("methods must have at least one argument");
|
|
|
|
let class = match *class {
|
|
|
|
Type::ByRef(ref t) |
|
|
|
|
Type::ByValue(ref t) => t,
|
|
|
|
Type::ByMutRef(_) => {
|
|
|
|
panic!("first method argument cannot be mutable ref")
|
|
|
|
}
|
2018-02-16 18:58:37 -08:00
|
|
|
Type::Vector(..) => {
|
|
|
|
panic!("method receivers cannot be vectors")
|
2018-02-07 16:41:33 -08:00
|
|
|
}
|
|
|
|
};
|
|
|
|
let class_name = match *class {
|
|
|
|
syn::Type::Path(syn::TypePath { qself: None, ref path }) => path,
|
|
|
|
_ => panic!("first argument of method must be a path"),
|
|
|
|
};
|
|
|
|
let class_name = extract_path_ident(class_name)
|
|
|
|
.expect("first argument of method must be a bare type");
|
|
|
|
|
|
|
|
ImportKind::Method {
|
|
|
|
class: class_name.as_ref().to_string(),
|
|
|
|
ty: class.clone(),
|
|
|
|
}
|
|
|
|
} else if wasm.opts.constructor() {
|
|
|
|
let class = match wasm.ret {
|
|
|
|
Some(Type::ByValue(ref t)) => t,
|
|
|
|
_ => panic!("constructor returns must be bare types"),
|
|
|
|
};
|
|
|
|
let class_name = match *class {
|
|
|
|
syn::Type::Path(syn::TypePath { qself: None, ref path }) => path,
|
|
|
|
_ => panic!("first argument of method must be a path"),
|
|
|
|
};
|
|
|
|
let class_name = extract_path_ident(class_name)
|
|
|
|
.expect("first argument of method must be a bare type");
|
|
|
|
|
|
|
|
ImportKind::JsConstructor {
|
|
|
|
class: class_name.as_ref().to_string(),
|
|
|
|
ty: class.clone(),
|
|
|
|
}
|
|
|
|
|
|
|
|
} else if let Some(class) = wasm.opts.static_receiver() {
|
|
|
|
let class_name = match *class {
|
|
|
|
syn::Type::Path(syn::TypePath { qself: None, ref path }) => path,
|
|
|
|
_ => panic!("first argument of method must be a path"),
|
|
|
|
};
|
|
|
|
let class_name = extract_path_ident(class_name)
|
|
|
|
.expect("first argument of method must be a bare type");
|
|
|
|
ImportKind::Static {
|
|
|
|
class: class_name.to_string(),
|
|
|
|
ty: class.clone(),
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
ImportKind::Normal
|
|
|
|
};
|
|
|
|
|
|
|
|
self.imports.push(Import {
|
|
|
|
module: module_opts.module().map(|s| s.to_string()),
|
|
|
|
kind,
|
|
|
|
function: wasm,
|
2017-12-18 21:43:16 -08:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2018-02-07 16:41:33 -08:00
|
|
|
pub fn push_foreign_ty(&mut self,
|
|
|
|
f: syn::ForeignItemType,
|
|
|
|
_module_opts: &BindgenAttrs) {
|
|
|
|
self.imported_types.push((f.vis, f.ident));
|
|
|
|
}
|
|
|
|
|
2018-02-06 07:56:14 -08:00
|
|
|
pub fn wbg_literal(&self, dst: &mut Tokens) -> usize {
|
2018-02-10 10:05:43 -08:00
|
|
|
let mut tmp = Tokens::new();
|
|
|
|
let cnt = {
|
|
|
|
let mut a = LiteralBuilder {
|
|
|
|
dst: &mut tmp,
|
|
|
|
cnt: 0,
|
|
|
|
};
|
|
|
|
a.fields(&[
|
|
|
|
("exports", &|a| a.list(&self.exports, Export::wbg_literal)),
|
|
|
|
("imports", &|a| a.list(&self.imports, Import::wbg_literal)),
|
2018-02-22 12:01:38 +01:00
|
|
|
("enums", &|a| a.list(&self.enums, Enum::wbg_literal)),
|
2018-02-10 10:05:43 -08:00
|
|
|
("custom_type_names", &|a| {
|
2018-02-22 12:08:28 +01:00
|
|
|
let names = self.exports.iter()
|
2018-02-10 10:05:43 -08:00
|
|
|
.filter_map(|e| e.class)
|
2018-02-16 13:49:53 -08:00
|
|
|
.chain(self.structs.iter().map(|s| s.name))
|
2018-02-22 12:08:28 +01:00
|
|
|
.collect::<BTreeSet<_>>();
|
|
|
|
a.list(&names, |s, a| {
|
|
|
|
let val = shared::name_to_descriptor(s.as_ref());
|
2018-02-10 10:05:43 -08:00
|
|
|
a.fields(&[
|
2018-02-22 12:08:28 +01:00
|
|
|
("descriptor", &|a| a.char(val)),
|
2018-02-22 12:11:47 +01:00
|
|
|
("name", &|a| a.str(s.as_ref()))
|
2018-02-10 10:05:43 -08:00
|
|
|
]);
|
|
|
|
})
|
|
|
|
}),
|
2018-03-01 19:32:05 -08:00
|
|
|
("version", &|a| a.str(&shared::version())),
|
2018-02-10 10:05:43 -08:00
|
|
|
]);
|
|
|
|
a.cnt
|
2018-02-06 07:56:14 -08:00
|
|
|
};
|
2018-02-10 10:05:43 -08:00
|
|
|
let cnt = cnt as u32;
|
|
|
|
(quote! {
|
|
|
|
0x30d97887,
|
|
|
|
0xd4182f61,
|
|
|
|
#cnt,
|
|
|
|
}).to_tokens(dst);
|
|
|
|
tmp.to_tokens(dst);
|
|
|
|
(cnt as usize) + 3
|
2017-12-18 12:39:14 -08:00
|
|
|
}
|
2017-12-14 19:31:01 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
impl Function {
|
2018-02-07 16:41:33 -08:00
|
|
|
pub fn from(input: syn::ItemFn, opts: BindgenAttrs) -> Function {
|
2017-12-14 19:31:01 -08:00
|
|
|
match input.vis {
|
|
|
|
syn::Visibility::Public(_) => {}
|
|
|
|
_ => panic!("can only bindgen public functions"),
|
|
|
|
}
|
2017-12-31 14:40:57 -08:00
|
|
|
if input.constness.is_some() {
|
|
|
|
panic!("can only bindgen non-const functions");
|
2017-12-14 19:31:01 -08:00
|
|
|
}
|
2017-12-31 14:40:57 -08:00
|
|
|
if input.unsafety.is_some() {
|
|
|
|
panic!("can only bindgen safe functions");
|
2017-12-14 19:31:01 -08:00
|
|
|
}
|
2017-12-18 12:39:14 -08:00
|
|
|
|
2018-02-07 16:41:33 -08:00
|
|
|
Function::from_decl(input.ident,
|
|
|
|
input.decl,
|
|
|
|
input.attrs,
|
|
|
|
opts,
|
|
|
|
input.vis,
|
|
|
|
false).0
|
2017-12-18 21:43:16 -08:00
|
|
|
}
|
|
|
|
|
2018-02-05 14:24:25 -08:00
|
|
|
pub fn from_decl(name: syn::Ident,
|
2018-02-07 16:41:33 -08:00
|
|
|
decl: Box<syn::FnDecl>,
|
|
|
|
attrs: Vec<syn::Attribute>,
|
|
|
|
opts: BindgenAttrs,
|
|
|
|
vis: syn::Visibility,
|
2018-02-05 14:24:25 -08:00
|
|
|
allow_self: bool) -> (Function, Option<bool>) {
|
2017-12-31 14:40:57 -08:00
|
|
|
if decl.variadic.is_some() {
|
2017-12-14 19:31:01 -08:00
|
|
|
panic!("can't bindgen variadic functions")
|
|
|
|
}
|
2017-12-18 21:43:16 -08:00
|
|
|
if decl.generics.params.len() > 0 {
|
2017-12-14 19:31:01 -08:00
|
|
|
panic!("can't bindgen functions with lifetime or type parameters")
|
|
|
|
}
|
|
|
|
|
2018-02-05 14:24:25 -08:00
|
|
|
let mut mutable = None;
|
2017-12-18 21:43:16 -08:00
|
|
|
let arguments = decl.inputs.iter()
|
2018-02-05 14:24:25 -08:00
|
|
|
.filter_map(|arg| {
|
2017-12-14 19:31:01 -08:00
|
|
|
match *arg {
|
2018-02-05 14:24:25 -08:00
|
|
|
syn::FnArg::Captured(ref c) => Some(c),
|
|
|
|
syn::FnArg::SelfValue(_) => {
|
|
|
|
panic!("by-value `self` not yet supported");
|
|
|
|
}
|
|
|
|
syn::FnArg::SelfRef(ref a) if allow_self => {
|
|
|
|
assert!(mutable.is_none());
|
|
|
|
mutable = Some(a.mutability.is_some());
|
|
|
|
None
|
|
|
|
}
|
2017-12-14 19:31:01 -08:00
|
|
|
_ => panic!("arguments cannot be `self` or ignored"),
|
|
|
|
}
|
|
|
|
})
|
|
|
|
.map(|arg| Type::from(&arg.ty))
|
|
|
|
.collect::<Vec<_>>();
|
|
|
|
|
2017-12-18 21:43:16 -08:00
|
|
|
let ret = match decl.output {
|
2017-12-14 19:31:01 -08:00
|
|
|
syn::ReturnType::Default => None,
|
2017-12-31 14:40:57 -08:00
|
|
|
syn::ReturnType::Type(_, ref t) => Some(Type::from(t)),
|
2017-12-14 19:31:01 -08:00
|
|
|
};
|
|
|
|
|
2018-02-07 16:41:33 -08:00
|
|
|
(Function {
|
|
|
|
name,
|
|
|
|
arguments,
|
|
|
|
ret,
|
|
|
|
opts,
|
|
|
|
rust_vis: vis,
|
|
|
|
rust_decl: decl,
|
|
|
|
rust_attrs: attrs,
|
|
|
|
}, mutable)
|
2017-12-14 19:31:01 -08:00
|
|
|
}
|
|
|
|
|
2018-02-06 07:56:14 -08:00
|
|
|
fn wbg_literal(&self, a: &mut LiteralBuilder) {
|
|
|
|
a.fields(&[
|
|
|
|
("name", &|a| a.str(self.name.as_ref())),
|
|
|
|
("arguments", &|a| a.list(&self.arguments, Type::wbg_literal)),
|
|
|
|
("ret", &|a| {
|
|
|
|
match self.ret {
|
|
|
|
Some(ref s) => s.wbg_literal(a),
|
|
|
|
None => a.append("null"),
|
|
|
|
}
|
|
|
|
}),
|
|
|
|
]);
|
2017-12-14 19:31:01 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-02-06 07:56:14 -08:00
|
|
|
pub fn extract_path_ident(path: &syn::Path) -> Option<syn::Ident> {
|
2017-12-18 21:43:16 -08:00
|
|
|
if path.leading_colon.is_some() {
|
2018-02-06 07:56:14 -08:00
|
|
|
return None
|
2017-12-18 21:43:16 -08:00
|
|
|
}
|
|
|
|
if path.segments.len() != 1 {
|
2018-02-06 07:56:14 -08:00
|
|
|
return None
|
2017-12-18 21:43:16 -08:00
|
|
|
}
|
2018-01-08 10:42:01 -08:00
|
|
|
match path.segments.first().unwrap().value().arguments {
|
2017-12-18 21:43:16 -08:00
|
|
|
syn::PathArguments::None => {}
|
2018-02-06 07:56:14 -08:00
|
|
|
_ => return None,
|
2017-12-18 21:43:16 -08:00
|
|
|
}
|
2018-02-06 07:56:14 -08:00
|
|
|
path.segments.first().map(|v| v.value().ident)
|
2017-12-18 21:43:16 -08:00
|
|
|
}
|
|
|
|
|
2017-12-14 19:31:01 -08:00
|
|
|
impl Type {
|
|
|
|
pub fn from(ty: &syn::Type) -> Type {
|
|
|
|
match *ty {
|
2017-12-14 21:55:21 -08:00
|
|
|
syn::Type::Reference(ref r) => {
|
2017-12-31 14:40:57 -08:00
|
|
|
match *r.elem {
|
2017-12-14 21:55:21 -08:00
|
|
|
syn::Type::Path(syn::TypePath { qself: None, ref path }) => {
|
|
|
|
let ident = extract_path_ident(path);
|
2018-02-06 07:56:14 -08:00
|
|
|
match ident.as_ref().map(|s| s.as_ref()) {
|
2018-02-16 18:58:37 -08:00
|
|
|
Some("str") => return Type::Vector(VectorType::String, false),
|
2018-02-06 07:56:14 -08:00
|
|
|
_ => {}
|
2017-12-14 21:55:21 -08:00
|
|
|
}
|
|
|
|
}
|
2018-02-16 18:58:37 -08:00
|
|
|
syn::Type::Slice(ref slice) => {
|
|
|
|
if let Some(ty) = VectorType::from(&slice.elem) {
|
|
|
|
return Type::Vector(ty, false)
|
|
|
|
}
|
|
|
|
}
|
2018-02-06 07:56:14 -08:00
|
|
|
_ => {}
|
2017-12-14 19:31:01 -08:00
|
|
|
}
|
2018-02-06 07:56:14 -08:00
|
|
|
return if r.mutability.is_some() {
|
|
|
|
Type::ByMutRef((*r.elem).clone())
|
2017-12-20 07:35:14 -08:00
|
|
|
} else {
|
2018-02-06 07:56:14 -08:00
|
|
|
Type::ByRef((*r.elem).clone())
|
2017-12-20 07:35:14 -08:00
|
|
|
}
|
|
|
|
}
|
2018-02-16 18:58:37 -08:00
|
|
|
syn::Type::Path(syn::TypePath { qself: None, ref path })
|
|
|
|
if path.leading_colon.is_none() && path.segments.len() == 1 =>
|
|
|
|
{
|
|
|
|
let seg = path.segments.first().unwrap().into_value();
|
|
|
|
match seg.arguments {
|
|
|
|
syn::PathArguments::None => {
|
|
|
|
match seg.ident.as_ref() {
|
|
|
|
"String" => return Type::Vector(VectorType::String, true),
|
|
|
|
_ => {}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
syn::PathArguments::AngleBracketed(ref t)
|
|
|
|
if seg.ident == "Vec" && t.args.len() == 1 =>
|
|
|
|
{
|
|
|
|
match **t.args.first().unwrap().value() {
|
|
|
|
syn::GenericArgument::Type(ref t) => {
|
|
|
|
if let Some(ty) = VectorType::from(t) {
|
|
|
|
return Type::Vector(ty, true)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
_ => {}
|
|
|
|
}
|
|
|
|
}
|
2018-02-06 07:56:14 -08:00
|
|
|
_ => {}
|
2017-12-14 19:31:01 -08:00
|
|
|
}
|
|
|
|
}
|
2018-02-06 07:56:14 -08:00
|
|
|
_ => {}
|
2017-12-14 19:31:01 -08:00
|
|
|
}
|
2018-02-06 07:56:14 -08:00
|
|
|
|
|
|
|
Type::ByValue(ty.clone())
|
2017-12-14 19:31:01 -08:00
|
|
|
}
|
|
|
|
|
2018-02-06 07:56:14 -08:00
|
|
|
fn wbg_literal(&self, a: &mut LiteralBuilder) {
|
2017-12-14 19:31:01 -08:00
|
|
|
match *self {
|
2018-02-16 18:58:37 -08:00
|
|
|
Type::Vector(VectorType::String, true) => a.char(shared::TYPE_STRING),
|
|
|
|
Type::Vector(VectorType::String, false) => a.char(shared::TYPE_BORROWED_STR),
|
|
|
|
Type::Vector(VectorType::U8, true) => a.char(shared::TYPE_VECTOR_U8),
|
|
|
|
Type::Vector(VectorType::U8, false) => a.char(shared::TYPE_SLICE_U8),
|
|
|
|
Type::Vector(VectorType::I8, true) => a.char(shared::TYPE_VECTOR_I8),
|
|
|
|
Type::Vector(VectorType::I8, false) => a.char(shared::TYPE_SLICE_I8),
|
|
|
|
Type::Vector(VectorType::U16, true) => a.char(shared::TYPE_VECTOR_U16),
|
|
|
|
Type::Vector(VectorType::U16, false) => a.char(shared::TYPE_SLICE_U16),
|
|
|
|
Type::Vector(VectorType::I16, true) => a.char(shared::TYPE_VECTOR_I16),
|
|
|
|
Type::Vector(VectorType::I16, false) => a.char(shared::TYPE_SLICE_I16),
|
|
|
|
Type::Vector(VectorType::U32, true) => a.char(shared::TYPE_VECTOR_U32),
|
|
|
|
Type::Vector(VectorType::U32, false) => a.char(shared::TYPE_SLICE_U32),
|
|
|
|
Type::Vector(VectorType::I32, true) => a.char(shared::TYPE_VECTOR_I32),
|
|
|
|
Type::Vector(VectorType::I32, false) => a.char(shared::TYPE_SLICE_I32),
|
|
|
|
Type::Vector(VectorType::F32, true) => a.char(shared::TYPE_VECTOR_F32),
|
|
|
|
Type::Vector(VectorType::F32, false) => a.char(shared::TYPE_SLICE_F32),
|
|
|
|
Type::Vector(VectorType::F64, true) => a.char(shared::TYPE_VECTOR_F64),
|
|
|
|
Type::Vector(VectorType::F64, false) => a.char(shared::TYPE_SLICE_F64),
|
2018-02-28 10:56:56 +01:00
|
|
|
Type::Vector(VectorType::JsValue, true) => a.char(shared::TYPE_VECTOR_JSVALUE),
|
|
|
|
Type::Vector(VectorType::JsValue, false) => panic!("Slices of JsValues not supported"),
|
2018-02-06 07:56:14 -08:00
|
|
|
Type::ByValue(ref t) => {
|
|
|
|
a.as_char(my_quote! {
|
2018-02-06 16:06:21 -08:00
|
|
|
<#t as ::wasm_bindgen::convert::WasmBoundary>::DESCRIPTOR
|
2018-02-06 07:56:14 -08:00
|
|
|
});
|
|
|
|
}
|
|
|
|
Type::ByRef(ref ty) |
|
|
|
|
Type::ByMutRef(ref ty) => {
|
|
|
|
a.as_char(my_quote! {
|
2018-02-06 16:06:21 -08:00
|
|
|
(<#ty as ::wasm_bindgen::convert::WasmBoundary>::DESCRIPTOR |
|
|
|
|
::wasm_bindgen::convert::DESCRIPTOR_CUSTOM_REF_FLAG)
|
2018-02-06 07:56:14 -08:00
|
|
|
});
|
|
|
|
}
|
2017-12-14 19:31:01 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-02-07 16:41:33 -08:00
|
|
|
impl Export {
|
|
|
|
pub fn rust_symbol(&self) -> syn::Ident {
|
|
|
|
let mut generated_name = format!("__wasm_bindgen_generated");
|
|
|
|
if let Some(class) = self.class {
|
|
|
|
generated_name.push_str("_");
|
|
|
|
generated_name.push_str(class.as_ref());
|
2017-12-18 12:39:14 -08:00
|
|
|
}
|
2018-02-07 16:41:33 -08:00
|
|
|
generated_name.push_str("_");
|
|
|
|
generated_name.push_str(self.function.name.as_ref());
|
|
|
|
syn::Ident::from(generated_name)
|
2017-12-18 12:39:14 -08:00
|
|
|
}
|
|
|
|
|
2018-02-07 16:41:33 -08:00
|
|
|
pub fn export_name(&self) -> syn::LitStr {
|
|
|
|
let name = match self.class {
|
|
|
|
Some(class) => {
|
|
|
|
shared::struct_function_export_name(
|
|
|
|
class.as_ref(),
|
|
|
|
self.function.name.as_ref(),
|
|
|
|
)
|
2017-12-14 21:55:21 -08:00
|
|
|
}
|
2017-12-18 12:39:14 -08:00
|
|
|
None => {
|
2018-02-07 16:41:33 -08:00
|
|
|
shared::free_function_export_name(self.function.name.as_ref())
|
2017-12-14 21:55:21 -08:00
|
|
|
}
|
2018-02-07 16:41:33 -08:00
|
|
|
};
|
|
|
|
syn::LitStr::new(&name, Span::def_site())
|
2017-12-18 12:39:14 -08:00
|
|
|
}
|
|
|
|
|
2018-02-06 07:56:14 -08:00
|
|
|
fn wbg_literal(&self, a: &mut LiteralBuilder) {
|
|
|
|
a.fields(&[
|
2018-02-07 16:41:33 -08:00
|
|
|
("class", &|a| {
|
|
|
|
match self.class {
|
|
|
|
Some(ref s) => a.str(s.as_ref()),
|
|
|
|
None => a.append("null"),
|
|
|
|
}
|
|
|
|
}),
|
|
|
|
("method", &|a| a.bool(self.method)),
|
2018-02-06 07:56:14 -08:00
|
|
|
("function", &|a| self.function.wbg_literal(a)),
|
|
|
|
]);
|
2017-12-18 12:39:14 -08:00
|
|
|
}
|
2017-12-14 19:31:01 -08:00
|
|
|
}
|
2018-02-05 14:24:25 -08:00
|
|
|
|
2018-02-07 16:41:33 -08:00
|
|
|
impl Import {
|
2018-02-06 07:56:14 -08:00
|
|
|
fn wbg_literal(&self, a: &mut LiteralBuilder) {
|
2018-02-07 16:41:33 -08:00
|
|
|
let mut method = false;
|
|
|
|
let mut js_new = false;
|
|
|
|
let mut statik = false;
|
|
|
|
let mut class_name = None;
|
|
|
|
match self.kind {
|
|
|
|
ImportKind::Method { ref class, .. } => {
|
|
|
|
method = true;
|
|
|
|
class_name = Some(class);
|
|
|
|
}
|
|
|
|
ImportKind::JsConstructor { ref class, .. } => {
|
|
|
|
js_new = true;
|
|
|
|
class_name = Some(class);
|
|
|
|
}
|
|
|
|
ImportKind::Static { ref class, .. } => {
|
|
|
|
statik = true;
|
|
|
|
class_name = Some(class);
|
|
|
|
}
|
|
|
|
ImportKind::Normal => {}
|
|
|
|
}
|
2018-02-14 13:16:02 -08:00
|
|
|
|
|
|
|
let mut getter = None;
|
|
|
|
let mut setter = None;
|
|
|
|
|
|
|
|
if self.function.opts.getter() {
|
|
|
|
getter = Some(self.infer_getter_property());
|
|
|
|
}
|
|
|
|
if self.function.opts.setter() {
|
|
|
|
setter = Some(self.infer_setter_property());
|
|
|
|
}
|
2018-02-06 07:56:14 -08:00
|
|
|
a.fields(&[
|
|
|
|
("module", &|a| {
|
|
|
|
match self.module {
|
|
|
|
Some(ref s) => a.str(s),
|
|
|
|
None => a.append("null"),
|
|
|
|
}
|
|
|
|
}),
|
2018-02-07 16:41:33 -08:00
|
|
|
("catch", &|a| a.bool(self.function.opts.catch())),
|
|
|
|
("method", &|a| a.bool(method)),
|
|
|
|
("js_new", &|a| a.bool(js_new)),
|
|
|
|
("statik", &|a| a.bool(statik)),
|
2018-02-14 13:16:02 -08:00
|
|
|
("getter", &|a| {
|
|
|
|
match getter {
|
|
|
|
Some(ref s) => a.str(s),
|
|
|
|
None => a.append("null"),
|
|
|
|
}
|
|
|
|
}),
|
|
|
|
("setter", &|a| {
|
|
|
|
match setter {
|
|
|
|
Some(ref s) => a.str(s),
|
|
|
|
None => a.append("null"),
|
|
|
|
}
|
|
|
|
}),
|
2018-02-07 16:41:33 -08:00
|
|
|
("function", &|a| self.function.wbg_literal(a)),
|
|
|
|
("class", &|a| {
|
|
|
|
match class_name {
|
|
|
|
Some(s) => a.str(s),
|
|
|
|
None => a.append("null"),
|
|
|
|
}
|
2018-02-06 07:56:14 -08:00
|
|
|
}),
|
|
|
|
]);
|
|
|
|
}
|
2018-02-14 13:16:02 -08:00
|
|
|
|
|
|
|
fn infer_getter_property(&self) -> String {
|
|
|
|
self.function.name.as_ref().to_string()
|
|
|
|
}
|
|
|
|
|
|
|
|
fn infer_setter_property(&self) -> String {
|
|
|
|
let name = self.function.name.as_ref();
|
|
|
|
assert!(name.starts_with("set_"), "setters must start with `set_`");
|
|
|
|
name[4..].to_string()
|
|
|
|
}
|
2018-02-06 07:56:14 -08:00
|
|
|
}
|
|
|
|
|
2018-02-22 12:01:38 +01:00
|
|
|
impl Enum {
|
|
|
|
fn wbg_literal(&self, a: &mut LiteralBuilder) {
|
|
|
|
a.fields(&[
|
|
|
|
("name", &|a| a.str(self.name.as_ref())),
|
|
|
|
("variants", &|a| a.list(&self.variants, |v, a| {
|
2018-02-23 14:17:53 +01:00
|
|
|
let &(name, value) = v;
|
|
|
|
a.fields(&[("name", &|a| a.str(name.as_ref())),
|
|
|
|
("value", &|a| a.append(&format!("{}", value)))])
|
2018-02-22 12:01:38 +01:00
|
|
|
})),
|
|
|
|
]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-02-07 16:41:33 -08:00
|
|
|
impl Struct {
|
|
|
|
fn from(s: syn::ItemStruct, _opts: BindgenAttrs) -> Struct {
|
|
|
|
Struct { name: s.ident }
|
2018-02-05 14:24:25 -08:00
|
|
|
}
|
|
|
|
}
|
2018-02-06 07:56:14 -08:00
|
|
|
|
|
|
|
struct LiteralBuilder<'a> {
|
|
|
|
dst: &'a mut Tokens,
|
|
|
|
cnt: usize,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<'a> LiteralBuilder<'a> {
|
2018-02-06 16:06:21 -08:00
|
|
|
fn char_lit(&mut self, c: char) {
|
2018-02-06 07:56:14 -08:00
|
|
|
if self.cnt > 0 {
|
|
|
|
::syn::token::Comma::default().to_tokens(self.dst);
|
|
|
|
}
|
|
|
|
self.cnt += 1;
|
2018-02-06 16:06:21 -08:00
|
|
|
(c as u32).to_tokens(self.dst);
|
2018-02-06 07:56:14 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
fn append(&mut self, s: &str) {
|
2018-02-06 16:06:21 -08:00
|
|
|
for c in s.chars() {
|
|
|
|
self.char_lit(c);
|
2018-02-06 07:56:14 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn str(&mut self, s: &str) {
|
|
|
|
self.append("\"");
|
|
|
|
self.append(s);
|
|
|
|
self.append("\"");
|
|
|
|
}
|
|
|
|
|
|
|
|
fn bool(&mut self, v: bool) {
|
|
|
|
if v {
|
|
|
|
self.append("true")
|
|
|
|
} else {
|
|
|
|
self.append("false")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn char(&mut self, s: char) {
|
|
|
|
self.append("\"");
|
2018-02-06 16:06:21 -08:00
|
|
|
self.char_lit(s);
|
|
|
|
self.append("\"");
|
2018-02-06 07:56:14 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
fn as_char(&mut self, tokens: Tokens) {
|
|
|
|
self.append("\"");
|
|
|
|
::syn::token::Comma::default().to_tokens(self.dst);
|
|
|
|
tokens.to_tokens(self.dst);
|
|
|
|
self.cnt += 1;
|
|
|
|
self.append("\"");
|
|
|
|
}
|
|
|
|
|
|
|
|
fn fields(&mut self, fields: &[(&str, &Fn(&mut Self))]) {
|
|
|
|
self.append("{");
|
|
|
|
for (i, &(field, cb)) in fields.iter().enumerate() {
|
|
|
|
if i > 0 {
|
|
|
|
self.append(",");
|
|
|
|
}
|
|
|
|
self.str(field);
|
|
|
|
self.append(":");
|
|
|
|
cb(self);
|
|
|
|
}
|
|
|
|
self.append("}");
|
|
|
|
}
|
|
|
|
|
|
|
|
fn list<T, F>(&mut self, list: T, mut cb: F)
|
|
|
|
where F: FnMut(T::Item, &mut Self),
|
|
|
|
T: IntoIterator,
|
|
|
|
{
|
|
|
|
self.append("[");
|
|
|
|
for (i, element) in list.into_iter().enumerate() {
|
|
|
|
if i > 0 {
|
|
|
|
self.append(",");
|
|
|
|
}
|
|
|
|
cb(element, self);
|
|
|
|
}
|
|
|
|
self.append("]");
|
|
|
|
}
|
|
|
|
}
|
2018-02-06 19:04:12 -08:00
|
|
|
|
|
|
|
#[derive(Default)]
|
2018-02-07 16:41:33 -08:00
|
|
|
pub struct BindgenAttrs {
|
|
|
|
attrs: Vec<BindgenAttr>,
|
2018-02-06 19:04:12 -08:00
|
|
|
}
|
|
|
|
|
2018-02-07 16:41:33 -08:00
|
|
|
impl BindgenAttrs {
|
|
|
|
pub fn find(attrs: &mut Vec<syn::Attribute>) -> BindgenAttrs {
|
|
|
|
let pos = attrs.iter()
|
|
|
|
.enumerate()
|
|
|
|
.find(|&(_, ref m)| m.path.segments[0].ident == "wasm_bindgen")
|
|
|
|
.map(|a| a.0);
|
|
|
|
let pos = match pos {
|
|
|
|
Some(i) => i,
|
|
|
|
None => return BindgenAttrs::default(),
|
|
|
|
};
|
|
|
|
syn::parse(attrs.remove(pos).tts.into())
|
|
|
|
.expect("malformed #[wasm_bindgen] attribute")
|
|
|
|
}
|
|
|
|
|
|
|
|
fn module(&self) -> Option<&str> {
|
|
|
|
self.attrs.iter()
|
|
|
|
.filter_map(|a| {
|
|
|
|
match *a {
|
|
|
|
BindgenAttr::Module(ref s) => Some(&s[..]),
|
2018-02-06 19:04:12 -08:00
|
|
|
_ => None,
|
|
|
|
}
|
|
|
|
})
|
2018-02-07 16:41:33 -08:00
|
|
|
.next()
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn catch(&self) -> bool {
|
|
|
|
self.attrs.iter()
|
|
|
|
.any(|a| {
|
|
|
|
match *a {
|
|
|
|
BindgenAttr::Catch => true,
|
|
|
|
_ => false,
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
fn constructor(&self) -> bool {
|
|
|
|
self.attrs.iter()
|
|
|
|
.any(|a| {
|
|
|
|
match *a {
|
|
|
|
BindgenAttr::Constructor => true,
|
|
|
|
_ => false,
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
fn method(&self) -> bool {
|
|
|
|
self.attrs.iter()
|
|
|
|
.any(|a| {
|
|
|
|
match *a {
|
|
|
|
BindgenAttr::Method => true,
|
|
|
|
_ => false,
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
fn static_receiver(&self) -> Option<&syn::Type> {
|
|
|
|
self.attrs.iter()
|
2018-02-06 19:04:12 -08:00
|
|
|
.filter_map(|a| {
|
2018-02-07 16:41:33 -08:00
|
|
|
match *a {
|
|
|
|
BindgenAttr::Static(ref s) => Some(s),
|
2018-02-06 19:04:12 -08:00
|
|
|
_ => None,
|
|
|
|
}
|
2018-02-07 16:41:33 -08:00
|
|
|
})
|
|
|
|
.next()
|
2018-02-06 19:04:12 -08:00
|
|
|
}
|
2018-02-14 13:16:02 -08:00
|
|
|
|
|
|
|
fn getter(&self) -> bool {
|
|
|
|
self.attrs.iter()
|
|
|
|
.any(|a| {
|
|
|
|
match *a {
|
|
|
|
BindgenAttr::Getter => true,
|
|
|
|
_ => false,
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
fn setter(&self) -> bool {
|
|
|
|
self.attrs.iter()
|
|
|
|
.any(|a| {
|
|
|
|
match *a {
|
|
|
|
BindgenAttr::Setter => true,
|
|
|
|
_ => false,
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
2018-02-06 19:04:12 -08:00
|
|
|
}
|
|
|
|
|
2018-02-07 16:41:33 -08:00
|
|
|
impl syn::synom::Synom for BindgenAttrs {
|
|
|
|
named!(parse -> Self, alt!(
|
|
|
|
do_parse!(
|
|
|
|
opts: parens!(call!(
|
|
|
|
syn::punctuated::Punctuated::<_, syn::token::Comma>::parse_terminated
|
|
|
|
)) >>
|
|
|
|
(BindgenAttrs {
|
|
|
|
attrs: opts.1.into_iter().collect(),
|
|
|
|
})
|
|
|
|
) => { |s| s }
|
|
|
|
|
|
|
|
|
epsilon!() => { |_| BindgenAttrs { attrs: Vec::new() } }
|
|
|
|
));
|
|
|
|
}
|
|
|
|
|
|
|
|
enum BindgenAttr {
|
|
|
|
Catch,
|
|
|
|
Constructor,
|
|
|
|
Method,
|
|
|
|
Static(syn::Type),
|
|
|
|
Module(String),
|
2018-02-14 13:16:02 -08:00
|
|
|
Getter,
|
|
|
|
Setter,
|
2018-02-07 16:41:33 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
impl syn::synom::Synom for BindgenAttr {
|
|
|
|
named!(parse -> Self, alt!(
|
|
|
|
call!(term, "catch") => { |_| BindgenAttr::Catch }
|
|
|
|
|
|
|
|
|
call!(term, "constructor") => { |_| BindgenAttr::Constructor }
|
|
|
|
|
|
|
|
|
call!(term, "method") => { |_| BindgenAttr::Method }
|
|
|
|
|
|
2018-02-14 13:16:02 -08:00
|
|
|
call!(term, "getter") => { |_| BindgenAttr::Getter }
|
|
|
|
|
|
|
|
|
call!(term, "setter") => { |_| BindgenAttr::Setter }
|
|
|
|
|
|
2018-02-07 16:41:33 -08:00
|
|
|
do_parse!(
|
|
|
|
call!(term, "static") >>
|
|
|
|
punct!(=) >>
|
|
|
|
s: syn!(syn::Type) >>
|
|
|
|
(s)
|
|
|
|
)=> { BindgenAttr::Static }
|
|
|
|
|
|
|
|
|
do_parse!(
|
|
|
|
call!(term, "module") >>
|
|
|
|
punct!(=) >>
|
|
|
|
s: syn!(syn::LitStr) >>
|
|
|
|
(s.value())
|
|
|
|
)=> { BindgenAttr::Module }
|
|
|
|
));
|
|
|
|
}
|
|
|
|
|
2018-02-06 19:04:12 -08:00
|
|
|
fn extract_first_ty_param(ty: Option<&Type>) -> Option<Option<Type>> {
|
|
|
|
let ty = match ty {
|
|
|
|
Some(t) => t,
|
|
|
|
None => return Some(None)
|
|
|
|
};
|
|
|
|
let ty = match *ty {
|
|
|
|
Type::ByValue(ref t) => t,
|
|
|
|
_ => return None,
|
|
|
|
};
|
|
|
|
let path = match *ty {
|
|
|
|
syn::Type::Path(syn::TypePath { qself: None, ref path }) => path,
|
|
|
|
_ => return None,
|
|
|
|
};
|
|
|
|
let seg = path.segments.last()?.into_value();
|
|
|
|
let generics = match seg.arguments {
|
|
|
|
syn::PathArguments::AngleBracketed(ref t) => t,
|
|
|
|
_ => return None,
|
|
|
|
};
|
|
|
|
let ty = match *generics.args.first()?.into_value() {
|
|
|
|
syn::GenericArgument::Type(ref t) => t,
|
|
|
|
_ => return None,
|
|
|
|
};
|
|
|
|
match *ty {
|
|
|
|
syn::Type::Tuple(ref t) if t.elems.len() == 0 => return Some(None),
|
|
|
|
_ => {}
|
|
|
|
}
|
|
|
|
Some(Some(Type::from(ty)))
|
|
|
|
}
|
2018-02-07 16:41:33 -08:00
|
|
|
|
|
|
|
fn term<'a>(cursor: syn::buffer::Cursor<'a>, name: &str)
|
|
|
|
-> syn::synom::PResult<'a, ()>
|
|
|
|
{
|
|
|
|
if let Some((_span, term, next)) = cursor.term() {
|
|
|
|
if term.as_str() == name {
|
|
|
|
return Ok(((), next))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
syn::parse_error()
|
|
|
|
}
|
2018-02-16 18:58:37 -08:00
|
|
|
|
|
|
|
fn ungroup(input: &syn::Type) -> &syn::Type {
|
|
|
|
match *input {
|
|
|
|
syn::Type::Group(ref t) => &t.elem,
|
|
|
|
_ => input,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl VectorType {
|
|
|
|
fn from(ty: &syn::Type) -> Option<VectorType> {
|
|
|
|
let path = match *ungroup(ty) {
|
|
|
|
syn::Type::Path(syn::TypePath { qself: None, ref path }) => path,
|
|
|
|
_ => return None,
|
|
|
|
};
|
|
|
|
match extract_path_ident(path)?.as_ref() {
|
|
|
|
"i8" => Some(VectorType::I8),
|
|
|
|
"u8" => Some(VectorType::U8),
|
|
|
|
"i16" => Some(VectorType::I16),
|
|
|
|
"u16" => Some(VectorType::U16),
|
|
|
|
"i32" => Some(VectorType::I32),
|
|
|
|
"u32" => Some(VectorType::U32),
|
|
|
|
"f32" => Some(VectorType::F32),
|
|
|
|
"f64" => Some(VectorType::F64),
|
2018-02-28 10:56:56 +01:00
|
|
|
"JsValue" => Some(VectorType::JsValue),
|
2018-02-16 18:58:37 -08:00
|
|
|
_ => None,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn abi_element(&self) -> syn::Ident {
|
|
|
|
match *self {
|
|
|
|
VectorType::String => syn::Ident::from("u8"),
|
|
|
|
VectorType::I8 => syn::Ident::from("i8"),
|
|
|
|
VectorType::U8 => syn::Ident::from("u8"),
|
|
|
|
VectorType::I16 => syn::Ident::from("i16"),
|
|
|
|
VectorType::U16 => syn::Ident::from("u16"),
|
|
|
|
VectorType::I32 => syn::Ident::from("i32"),
|
|
|
|
VectorType::U32 => syn::Ident::from("u32"),
|
|
|
|
VectorType::F32 => syn::Ident::from("f32"),
|
|
|
|
VectorType::F64 => syn::Ident::from("f64"),
|
2018-02-28 10:56:56 +01:00
|
|
|
VectorType::JsValue => syn::Ident::from("JsValue"),
|
2018-02-16 18:58:37 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl ToTokens for VectorType {
|
|
|
|
fn to_tokens(&self, tokens: &mut Tokens) {
|
|
|
|
let me = match *self {
|
|
|
|
VectorType::String => my_quote! { String },
|
|
|
|
VectorType::I8 => my_quote! { Vec<i8> },
|
|
|
|
VectorType::U8 => my_quote! { Vec<u8> },
|
|
|
|
VectorType::I16 => my_quote! { Vec<i16> },
|
|
|
|
VectorType::U16 => my_quote! { Vec<u16> },
|
|
|
|
VectorType::I32 => my_quote! { Vec<i32> },
|
|
|
|
VectorType::U32 => my_quote! { Vec<u32> },
|
|
|
|
VectorType::F32 => my_quote! { Vec<f32> },
|
|
|
|
VectorType::F64 => my_quote! { Vec<f64> },
|
2018-02-28 10:56:56 +01:00
|
|
|
VectorType::JsValue => my_quote! { Vec<JsValue> },
|
2018-02-16 18:58:37 -08:00
|
|
|
};
|
|
|
|
me.to_tokens(tokens);
|
|
|
|
}
|
|
|
|
}
|