Add docs and remove typecheck from variadic attribute

This commit is contained in:
Richard Dodd
2018-09-01 13:55:35 +01:00
parent ce1cb84327
commit 7d5d845608
7 changed files with 53 additions and 58 deletions

View File

@ -2128,7 +2128,6 @@ impl<'a, 'b> SubContext<'a, 'b> {
import.shim,
if op.is_static { "" } else { ".call" }
))
>>>>>>> master
}
fn generate_import_type(

View File

@ -1101,60 +1101,6 @@ fn assert_not_variadic(attrs: &BindgenAttrs, span: &dyn ToTokens) -> Result<(),
Ok(())
}
/// Checks the function signature to ensure it finishes with a slice
///
/// Example of a valid signature: `fn my_func(arg1: u64, res: &[u64])`.
fn assert_last_param_is_slice(decl: &syn::FnDecl) -> Result<(), Diagnostic> {
#[inline]
fn not_slice_error(tok: &dyn ToTokens) -> Diagnostic {
Diagnostic::span_error(tok, "for variadic extern functions, the last argument must be a \
slice or `::std::vec::Vec`, to hold the arguments of unknown length")
}
/// Is this path `::std::vec::Vec`.
///
/// I could add `Vec`, but this would break in wierd ways if the user does
/// `use SomethingElse as Vec;`.
#[inline]
fn path_is_vec(path: &syn::Path) -> bool {
#[inline]
fn is_path_segment(path: Option<&syn::PathSegment>,
name: Option<&str>,
plain: bool) -> bool {
match (path, name) {
(Some(ref path), Some(ref name)) =>
(path.arguments.is_empty() || ! plain) && path.ident == name,
(None, None) => true,
_ => false
}
}
let mut iter = (&path.segments).into_iter();
path.leading_colon.is_some()
&& is_path_segment(iter.next(), Some("std"), true)
&& is_path_segment(iter.next(), Some("vec"), true)
&& is_path_segment(iter.next(), Some("Vec"), false)
&& is_path_segment(iter.next(), None, true)
}
let arg = decl.inputs.last().ok_or_else(|| not_slice_error(&decl.inputs))?;
if let syn::FnArg::Captured(ref arg_cap) = arg.value() {
// check for slice reference
if let syn::Type::Reference(ref ref_ty) = arg_cap.ty {
if let syn::Type::Slice(_) = *ref_ty.elem {
return Ok(());
}
}
// check for `Vec`
if let syn::Type::Path(ref path) = arg_cap.ty {
if path_is_vec(&path.path) {
return Ok(());
}
}
}
Err(not_slice_error(&arg))
}
/// If the path is a single ident, return it.
fn extract_path_ident(path: &syn::Path) -> Result<Ident, Diagnostic> {
if path.leading_colon.is_some() {

View File

@ -42,6 +42,7 @@
- [`module = "blah"`](./reference/attributes/on-js-imports/module.md)
- [`static_method_of = Blah`](./reference/attributes/on-js-imports/static_method_of.md)
- [`structural`](./reference/attributes/on-js-imports/structural.md)
- [variadic](./reference/attributes/on-js-imports/variadic.md)
- [On Rust Exports](./reference/attributes/on-rust-exports/index.md)
- [`constructor`](./reference/attributes/on-rust-exports/constructor.md)
- [`js_name = Blah`](./reference/attributes/on-rust-exports/js_name.md)

View File

@ -0,0 +1,38 @@
# Variadic Parameters
In javascript, both the types of function arguments, and the number of function arguments are
dynamic. For example
```js
function sum(...rest) {
let i;
// the old way
let old_way = 0;
for (i=0; i<arguments.length; i++) {
old_way += arguments[i];
}
// the new way
let new_way = 0;
for (i=0; i<rest.length; i++) {
new_way += rest[i];
}
// both give the same answer
assert(old_way === new_way);
return new_way;
}
```
This function doesn't translate directly into rust, since we don't currently support variadic
arguments on the wasm target. To bind to it, we use a slice as the last argument, and annotate the
function as variadic:
```rust
#[wasm_bindgen]
extern {
#[wasm_bindgen(variadic)]
fn sum(args: &[i32]) -> i32;
}
```
when we call this function, the last argument will be expanded as the javascript expects.

View File

@ -64,6 +64,10 @@ extern {
fn new() -> Awesome;
#[wasm_bindgen(method)]
fn get_internal(this: &Awesome) -> u32;
// We can call javascript functions that have a dynamic number of arguments,
// e.g. rust `sum(&[1, 2, 3])` will be called like `sum(1, 2, 3)`
#[wasm_bindgen(variadic)]
fn sum(vals: &[u32]) -> u32;
}
#[wasm_bindgen]
@ -143,5 +147,13 @@ export class Awesome {
}
}
export function sum(...args) {
let answer = 0;
for(var i=0; i<args.length; i++) {
answer += args[i];
}
return answer;
}
booted.then(main);
```

View File

@ -1,4 +1,3 @@
const wasm = require('wasm-bindgen-test.js');
const assert = require('assert');
// a function for testing numbers

View File

@ -34,9 +34,9 @@ extern {
//#[wasm_bindgen(variadic)]
//fn variadic_concat_string(first: String,
// second: String,
// rest: ::std::vec::Vec<String>) -> String;
// rest: Vec<String>) -> String;
#[wasm_bindgen(variadic)]
fn variadic_sum_rest_vec(first: u8, second: u8, rest: ::std::vec::Vec<u8>) -> u8;
fn variadic_sum_rest_vec(first: u8, second: u8, rest: Vec<u8>) -> u8;
//#[wasm_bindgen(variadic)]
//fn variadic_compare_pairs(first: JsValue, second: JsValue, rest: &[JsValue]);
//TODO imported type