mirror of
https://github.com/fluencelabs/wasm-bindgen
synced 2025-03-16 02:00:51 +00:00
parent
7802535948
commit
3c58aa7310
@ -402,6 +402,7 @@ are:
|
||||
* Imported types in a foreign module annotated with `#[wasm_bindgen]`
|
||||
* Borrowed exported structs (`&Foo` or `&mut Bar`)
|
||||
* The `JsValue` type and `&JsValue` (not mutable references)
|
||||
* Vectors and slices of supported integer types
|
||||
|
||||
All of the above can also be returned except borrowed references. Strings are
|
||||
implemented with shim functions to copy data in/out of the Rust heap. That is, a
|
||||
|
@ -467,6 +467,79 @@ impl<'a> Context<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
fn expose_pass_array8_to_wasm(&mut self) {
|
||||
if !self.exposed_globals.insert("pass_array8_to_wasm") {
|
||||
return
|
||||
}
|
||||
self.required_internal_exports.insert("__wbindgen_malloc");
|
||||
self.expose_uint8_memory();
|
||||
self.globals.push_str(&format!("
|
||||
function passArray8ToWasm(arg) {{
|
||||
const ptr = wasm.__wbindgen_malloc(arg.byteLength);
|
||||
getUint8Memory().set(arg, ptr);
|
||||
return [ptr, arg.length];
|
||||
}}
|
||||
"));
|
||||
}
|
||||
|
||||
fn expose_pass_array16_to_wasm(&mut self) {
|
||||
if !self.exposed_globals.insert("pass_array16_to_wasm") {
|
||||
return
|
||||
}
|
||||
self.required_internal_exports.insert("__wbindgen_malloc");
|
||||
self.expose_uint16_memory();
|
||||
self.globals.push_str(&format!("
|
||||
function passArray16ToWasm(arg) {{
|
||||
const ptr = wasm.__wbindgen_malloc(arg.byteLength);
|
||||
getUint16Memory().set(arg, ptr / 2);
|
||||
return [ptr, arg.length];
|
||||
}}
|
||||
"));
|
||||
}
|
||||
|
||||
fn expose_pass_array32_to_wasm(&mut self) {
|
||||
if !self.exposed_globals.insert("pass_array32_to_wasm") {
|
||||
return
|
||||
}
|
||||
self.required_internal_exports.insert("__wbindgen_malloc");
|
||||
self.expose_uint32_memory();
|
||||
self.globals.push_str(&format!("
|
||||
function passArray32ToWasm(arg) {{
|
||||
const ptr = wasm.__wbindgen_malloc(arg.byteLength);
|
||||
getUint32Memory().set(arg, ptr / 4);
|
||||
return [ptr, arg.length];
|
||||
}}
|
||||
"));
|
||||
}
|
||||
|
||||
fn expose_pass_array_f32_to_wasm(&mut self) {
|
||||
if !self.exposed_globals.insert("pass_array_f32_to_wasm") {
|
||||
return
|
||||
}
|
||||
self.required_internal_exports.insert("__wbindgen_malloc");
|
||||
self.globals.push_str(&format!("
|
||||
function passArrayF32ToWasm(arg) {{
|
||||
const ptr = wasm.__wbindgen_malloc(arg.byteLength);
|
||||
new Float32Array(wasm.memory.buffer).set(arg, ptr / 4);
|
||||
return [ptr, arg.length];
|
||||
}}
|
||||
"));
|
||||
}
|
||||
|
||||
fn expose_pass_array_f64_to_wasm(&mut self) {
|
||||
if !self.exposed_globals.insert("pass_array_f64_to_wasm") {
|
||||
return
|
||||
}
|
||||
self.required_internal_exports.insert("__wbindgen_malloc");
|
||||
self.globals.push_str(&format!("
|
||||
function passArrayF64ToWasm(arg) {{
|
||||
const ptr = wasm.__wbindgen_malloc(arg.byteLength);
|
||||
new Float64Array(wasm.memory.buffer).set(arg, ptr / 8);
|
||||
return [ptr, arg.length];
|
||||
}}
|
||||
"));
|
||||
}
|
||||
|
||||
fn expose_text_encoder(&mut self) {
|
||||
if !self.exposed_globals.insert("text_encoder") {
|
||||
return
|
||||
@ -523,6 +596,110 @@ impl<'a> Context<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
fn expose_get_array_i8_from_wasm(&mut self) {
|
||||
if !self.exposed_globals.insert("get_array_i8_from_wasm") {
|
||||
return
|
||||
}
|
||||
self.globals.push_str(&format!("
|
||||
function getArrayI8FromWasm(ptr, len) {{
|
||||
const mem = getUint8Memory();
|
||||
const slice = mem.slice(ptr, ptr + len);
|
||||
return new Int8Array(slice);
|
||||
}}
|
||||
"));
|
||||
}
|
||||
|
||||
fn expose_get_array_u8_from_wasm(&mut self) {
|
||||
if !self.exposed_globals.insert("get_array_u8_from_wasm") {
|
||||
return
|
||||
}
|
||||
self.globals.push_str(&format!("
|
||||
function getArrayU8FromWasm(ptr, len) {{
|
||||
const mem = getUint8Memory();
|
||||
const slice = mem.slice(ptr, ptr + len);
|
||||
return new Uint8Array(slice);
|
||||
}}
|
||||
"));
|
||||
}
|
||||
|
||||
fn expose_get_array_i16_from_wasm(&mut self) {
|
||||
if !self.exposed_globals.insert("get_array_i16_from_wasm") {
|
||||
return
|
||||
}
|
||||
self.globals.push_str(&format!("
|
||||
function getArrayI16FromWasm(ptr, len) {{
|
||||
const mem = getUint16Memory();
|
||||
const slice = mem.slice(ptr / 2, ptr / 2 + len);
|
||||
return new Int16Array(slice);
|
||||
}}
|
||||
"));
|
||||
}
|
||||
|
||||
fn expose_get_array_u16_from_wasm(&mut self) {
|
||||
if !self.exposed_globals.insert("get_array_u16_from_wasm") {
|
||||
return
|
||||
}
|
||||
self.globals.push_str(&format!("
|
||||
function getArrayU16FromWasm(ptr, len) {{
|
||||
const mem = getUint16Memory();
|
||||
const slice = mem.slice(ptr / 2, ptr / 2 + len);
|
||||
return new Uint16Array(slice);
|
||||
}}
|
||||
"));
|
||||
}
|
||||
|
||||
fn expose_get_array_i32_from_wasm(&mut self) {
|
||||
if !self.exposed_globals.insert("get_array_i32_from_wasm") {
|
||||
return
|
||||
}
|
||||
self.globals.push_str(&format!("
|
||||
function getArrayI32FromWasm(ptr, len) {{
|
||||
const mem = getUint32Memory();
|
||||
const slice = mem.slice(ptr / 4, ptr / 4 + len);
|
||||
return new Int32Array(slice);
|
||||
}}
|
||||
"));
|
||||
}
|
||||
|
||||
fn expose_get_array_u32_from_wasm(&mut self) {
|
||||
if !self.exposed_globals.insert("get_array_u32_from_wasm") {
|
||||
return
|
||||
}
|
||||
self.globals.push_str(&format!("
|
||||
function getArrayU32FromWasm(ptr, len) {{
|
||||
const mem = getUint32Memory();
|
||||
const slice = mem.slice(ptr / 4, ptr / 4 + len);
|
||||
return new Uint32Array(slice);
|
||||
}}
|
||||
"));
|
||||
}
|
||||
|
||||
fn expose_get_array_f32_from_wasm(&mut self) {
|
||||
if !self.exposed_globals.insert("get_array_f32_from_wasm") {
|
||||
return
|
||||
}
|
||||
self.globals.push_str(&format!("
|
||||
function getArrayF32FromWasm(ptr, len) {{
|
||||
const mem = new Float32Array(wasm.memory.buffer);
|
||||
const slice = mem.slice(ptr / 4, ptr / 4 + len);
|
||||
return new Float32Array(slice);
|
||||
}}
|
||||
"));
|
||||
}
|
||||
|
||||
fn expose_get_array_f64_from_wasm(&mut self) {
|
||||
if !self.exposed_globals.insert("get_array_f64_from_wasm") {
|
||||
return
|
||||
}
|
||||
self.globals.push_str(&format!("
|
||||
function getArrayF64FromWasm(ptr, len) {{
|
||||
const mem = new Float64Array(wasm.memory.buffer);
|
||||
const slice = mem.slice(ptr / 8, ptr / 8 + len);
|
||||
return new Float64Array(slice);
|
||||
}}
|
||||
"));
|
||||
}
|
||||
|
||||
fn expose_uint8_memory(&mut self) {
|
||||
if !self.exposed_globals.insert("uint8_memory") {
|
||||
return
|
||||
@ -538,6 +715,21 @@ impl<'a> Context<'a> {
|
||||
"));
|
||||
}
|
||||
|
||||
fn expose_uint16_memory(&mut self) {
|
||||
if !self.exposed_globals.insert("uint16_memory") {
|
||||
return
|
||||
}
|
||||
self.globals.push_str(&format!("
|
||||
let cachedUint16Memory = null;
|
||||
function getUint16Memory() {{
|
||||
if (cachedUint16Memory === null ||
|
||||
cachedUint16Memory.buffer !== wasm.memory.buffer)
|
||||
cachedUint16Memory = new Uint16Array(wasm.memory.buffer);
|
||||
return cachedUint16Memory;
|
||||
}}
|
||||
"));
|
||||
}
|
||||
|
||||
fn expose_uint32_memory(&mut self) {
|
||||
if !self.exposed_globals.insert("uint32_memory") {
|
||||
return
|
||||
@ -640,6 +832,76 @@ impl<'a> Context<'a> {
|
||||
let c = char::from_u32(c).unwrap();
|
||||
&self.custom_type_names[&c]
|
||||
}
|
||||
|
||||
fn pass_to_wasm_function(&mut self, ty: &VectorType) -> &'static str {
|
||||
match ty.kind {
|
||||
VectorKind::String => {
|
||||
self.expose_pass_string_to_wasm();
|
||||
"passStringToWasm"
|
||||
}
|
||||
VectorKind::I8 | VectorKind::U8 => {
|
||||
self.expose_pass_array8_to_wasm();
|
||||
"passArray8ToWasm"
|
||||
}
|
||||
VectorKind::I16 | VectorKind::U16 => {
|
||||
self.expose_pass_array16_to_wasm();
|
||||
"passArray16ToWasm"
|
||||
}
|
||||
VectorKind::I32 | VectorKind::U32 => {
|
||||
self.expose_pass_array32_to_wasm();
|
||||
"passArray32ToWasm"
|
||||
}
|
||||
VectorKind::F32 => {
|
||||
self.expose_pass_array_f32_to_wasm();
|
||||
"passArrayF32ToWasm"
|
||||
}
|
||||
VectorKind::F64 => {
|
||||
self.expose_pass_array_f64_to_wasm();
|
||||
"passArrayF64ToWasm"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn expose_get_vector_from_wasm(&mut self, ty: &VectorType) -> &'static str {
|
||||
match ty.kind {
|
||||
VectorKind::String => {
|
||||
self.expose_get_string_from_wasm();
|
||||
"getStringFromWasm"
|
||||
}
|
||||
VectorKind::I8 => {
|
||||
self.expose_get_array_i8_from_wasm();
|
||||
"getArrayI8FromWasm"
|
||||
}
|
||||
VectorKind::U8 => {
|
||||
self.expose_get_array_u8_from_wasm();
|
||||
"getArrayU8FromWasm"
|
||||
}
|
||||
VectorKind::I16 => {
|
||||
self.expose_get_array_i16_from_wasm();
|
||||
"getArrayI16FromWasm"
|
||||
}
|
||||
VectorKind::U16 => {
|
||||
self.expose_get_array_u16_from_wasm();
|
||||
"getArrayU16FromWasm"
|
||||
}
|
||||
VectorKind::I32 => {
|
||||
self.expose_get_array_i32_from_wasm();
|
||||
"getArrayI32FromWasm"
|
||||
}
|
||||
VectorKind::U32 => {
|
||||
self.expose_get_array_u32_from_wasm();
|
||||
"getArrayU32FromWasm"
|
||||
}
|
||||
VectorKind::F32 => {
|
||||
self.expose_get_array_f32_from_wasm();
|
||||
"getArrayF32FromWasm"
|
||||
}
|
||||
VectorKind::F64 => {
|
||||
self.expose_get_array_f64_from_wasm();
|
||||
"getArrayF64FromWasm"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'b> SubContext<'a, 'b> {
|
||||
@ -743,15 +1005,33 @@ impl<'a, 'b> SubContext<'a, 'b> {
|
||||
pass(&format!("arg{i} ? 1 : 0", i = i))
|
||||
}
|
||||
shared::TYPE_BORROWED_STR |
|
||||
shared::TYPE_STRING => {
|
||||
dst_ts.push_str(": string");
|
||||
self.cx.expose_pass_string_to_wasm();
|
||||
shared::TYPE_STRING |
|
||||
shared::TYPE_VECTOR_U8 |
|
||||
shared::TYPE_VECTOR_I8 |
|
||||
shared::TYPE_SLICE_U8 |
|
||||
shared::TYPE_SLICE_I8 |
|
||||
shared::TYPE_VECTOR_U16 |
|
||||
shared::TYPE_VECTOR_I16 |
|
||||
shared::TYPE_SLICE_U16 |
|
||||
shared::TYPE_SLICE_I16 |
|
||||
shared::TYPE_VECTOR_U32 |
|
||||
shared::TYPE_VECTOR_I32 |
|
||||
shared::TYPE_SLICE_U32 |
|
||||
shared::TYPE_SLICE_I32 |
|
||||
shared::TYPE_VECTOR_F32 |
|
||||
shared::TYPE_VECTOR_F64 |
|
||||
shared::TYPE_SLICE_F32 |
|
||||
shared::TYPE_SLICE_F64 => {
|
||||
let ty = VectorType::from(*arg);
|
||||
dst_ts.push_str(": ");
|
||||
dst_ts.push_str(ty.js_ty());
|
||||
let func = self.cx.pass_to_wasm_function(&ty);
|
||||
arg_conversions.push_str(&format!("\
|
||||
const [ptr{i}, len{i}] = passStringToWasm({arg});
|
||||
", i = i, arg = name));
|
||||
const [ptr{i}, len{i}] = {func}({arg});
|
||||
", i = i, func = func, arg = name));
|
||||
pass(&format!("ptr{}", i));
|
||||
pass(&format!("len{}", i));
|
||||
if *arg == shared::TYPE_BORROWED_STR {
|
||||
if ty.owned {
|
||||
destructors.push_str(&format!("\n\
|
||||
wasm.__wbindgen_free(ptr{i}, len{i});\n\
|
||||
", i = i));
|
||||
@ -823,19 +1103,29 @@ impl<'a, 'b> SubContext<'a, 'b> {
|
||||
self.cx.expose_take_object();
|
||||
format!("return takeObject(ret);")
|
||||
}
|
||||
Some(shared::TYPE_STRING) => {
|
||||
dst_ts.push_str(": string");
|
||||
self.cx.expose_get_string_from_wasm();
|
||||
Some(shared::TYPE_STRING) |
|
||||
Some(shared::TYPE_VECTOR_U8) |
|
||||
Some(shared::TYPE_VECTOR_I8) |
|
||||
Some(shared::TYPE_VECTOR_U16) |
|
||||
Some(shared::TYPE_VECTOR_I16) |
|
||||
Some(shared::TYPE_VECTOR_U32) |
|
||||
Some(shared::TYPE_VECTOR_I32) |
|
||||
Some(shared::TYPE_VECTOR_F32) |
|
||||
Some(shared::TYPE_VECTOR_F64) => {
|
||||
let ty = VectorType::from(function.ret.unwrap());
|
||||
dst_ts.push_str(": ");
|
||||
dst_ts.push_str(ty.js_ty());
|
||||
let f = self.cx.expose_get_vector_from_wasm(&ty);
|
||||
self.cx.required_internal_exports.insert("__wbindgen_boxed_str_ptr");
|
||||
self.cx.required_internal_exports.insert("__wbindgen_boxed_str_len");
|
||||
self.cx.required_internal_exports.insert("__wbindgen_boxed_str_free");
|
||||
format!("
|
||||
const ptr = wasm.__wbindgen_boxed_str_ptr(ret);
|
||||
const len = wasm.__wbindgen_boxed_str_len(ret);
|
||||
const realRet = getStringFromWasm(ptr, len);
|
||||
const realRet = {}(ptr, len);
|
||||
wasm.__wbindgen_boxed_str_free(ret);
|
||||
return realRet;
|
||||
")
|
||||
", f)
|
||||
}
|
||||
Some(shared::TYPE_JS_REF) |
|
||||
Some(shared::TYPE_BORROWED_STR) => panic!(),
|
||||
@ -925,22 +1215,39 @@ impl<'a, 'b> SubContext<'a, 'b> {
|
||||
invoc_args.push(format!("arg{} != 0", i));
|
||||
abi_args.push(format!("arg{}", i));
|
||||
}
|
||||
shared::TYPE_BORROWED_STR => {
|
||||
self.cx.expose_get_string_from_wasm();
|
||||
invoc_args.push(format!("getStringFromWasm(ptr{0}, len{0})", i));
|
||||
abi_args.push(format!("ptr{}", i));
|
||||
abi_args.push(format!("len{}", i));
|
||||
}
|
||||
shared::TYPE_STRING => {
|
||||
self.cx.expose_get_string_from_wasm();
|
||||
shared::TYPE_BORROWED_STR |
|
||||
shared::TYPE_STRING |
|
||||
shared::TYPE_VECTOR_U8 |
|
||||
shared::TYPE_VECTOR_I8 |
|
||||
shared::TYPE_SLICE_U8 |
|
||||
shared::TYPE_SLICE_I8 |
|
||||
shared::TYPE_VECTOR_U16 |
|
||||
shared::TYPE_VECTOR_I16 |
|
||||
shared::TYPE_SLICE_U16 |
|
||||
shared::TYPE_SLICE_I16 |
|
||||
shared::TYPE_VECTOR_U32 |
|
||||
shared::TYPE_VECTOR_I32 |
|
||||
shared::TYPE_SLICE_U32 |
|
||||
shared::TYPE_SLICE_I32 |
|
||||
shared::TYPE_VECTOR_F32 |
|
||||
shared::TYPE_VECTOR_F64 |
|
||||
shared::TYPE_SLICE_F32 |
|
||||
shared::TYPE_SLICE_F64 => {
|
||||
let ty = VectorType::from(*arg);
|
||||
let f = self.cx.expose_get_vector_from_wasm(&ty);
|
||||
abi_args.push(format!("ptr{}", i));
|
||||
abi_args.push(format!("len{}", i));
|
||||
extra.push_str(&format!("
|
||||
let arg{0} = getStringFromWasm(ptr{0}, len{0});
|
||||
wasm.__wbindgen_free(ptr{0}, len{0});
|
||||
", i));
|
||||
let arg{0} = {func}(ptr{0}, len{0});
|
||||
", i, func = f));
|
||||
invoc_args.push(format!("arg{}", i));
|
||||
self.cx.required_internal_exports.insert("__wbindgen_free");
|
||||
|
||||
if ty.owned {
|
||||
extra.push_str(&format!("
|
||||
wasm.__wbindgen_free(ptr{0}, len{0});
|
||||
", i));
|
||||
self.cx.required_internal_exports.insert("__wbindgen_free");
|
||||
}
|
||||
}
|
||||
shared::TYPE_JS_OWNED => {
|
||||
self.cx.expose_take_object();
|
||||
@ -1001,15 +1308,24 @@ impl<'a, 'b> SubContext<'a, 'b> {
|
||||
self.cx.expose_add_heap_object();
|
||||
format!("return addHeapObject({});", invoc)
|
||||
}
|
||||
Some(shared::TYPE_STRING) => {
|
||||
self.cx.expose_pass_string_to_wasm();
|
||||
Some(shared::TYPE_STRING) |
|
||||
Some(shared::TYPE_VECTOR_U8) |
|
||||
Some(shared::TYPE_VECTOR_I8) |
|
||||
Some(shared::TYPE_VECTOR_U16) |
|
||||
Some(shared::TYPE_VECTOR_I16) |
|
||||
Some(shared::TYPE_VECTOR_U32) |
|
||||
Some(shared::TYPE_VECTOR_I32) |
|
||||
Some(shared::TYPE_VECTOR_F32) |
|
||||
Some(shared::TYPE_VECTOR_F64) => {
|
||||
let ty = VectorType::from(import.function.ret.unwrap());
|
||||
let f = self.cx.pass_to_wasm_function(&ty);
|
||||
self.cx.expose_uint32_memory();
|
||||
abi_args.push("wasmretptr".to_string());
|
||||
format!("
|
||||
const [retptr, retlen] = passStringToWasm({});
|
||||
const [retptr, retlen] = {}({});
|
||||
getUint32Memory()[wasmretptr / 4] = retlen;
|
||||
return retptr;
|
||||
", invoc)
|
||||
", f, invoc)
|
||||
}
|
||||
None => invoc,
|
||||
_ => unimplemented!(),
|
||||
@ -1042,3 +1358,96 @@ impl<'a, 'b> SubContext<'a, 'b> {
|
||||
self.cx.globals.push_str("\n");
|
||||
}
|
||||
}
|
||||
|
||||
struct VectorType {
|
||||
owned: bool,
|
||||
kind: VectorKind,
|
||||
}
|
||||
|
||||
enum VectorKind {
|
||||
String,
|
||||
I8,
|
||||
U8,
|
||||
I16,
|
||||
U16,
|
||||
I32,
|
||||
U32,
|
||||
F32,
|
||||
F64,
|
||||
}
|
||||
|
||||
impl VectorType {
|
||||
fn from(desc: char) -> VectorType {
|
||||
match desc {
|
||||
shared::TYPE_BORROWED_STR => {
|
||||
VectorType { owned: false, kind: VectorKind::String }
|
||||
}
|
||||
shared::TYPE_STRING => {
|
||||
VectorType { owned: true, kind: VectorKind::String }
|
||||
}
|
||||
shared::TYPE_VECTOR_U8 => {
|
||||
VectorType { owned: true, kind: VectorKind::U8 }
|
||||
}
|
||||
shared::TYPE_VECTOR_I8 => {
|
||||
VectorType { owned: true, kind: VectorKind::I8 }
|
||||
}
|
||||
shared::TYPE_SLICE_U8 => {
|
||||
VectorType { owned: false, kind: VectorKind::U8 }
|
||||
}
|
||||
shared::TYPE_SLICE_I8 => {
|
||||
VectorType { owned: false, kind: VectorKind::I8 }
|
||||
}
|
||||
shared::TYPE_VECTOR_U16 => {
|
||||
VectorType { owned: true, kind: VectorKind::U16 }
|
||||
}
|
||||
shared::TYPE_VECTOR_I16 => {
|
||||
VectorType { owned: true, kind: VectorKind::I16 }
|
||||
}
|
||||
shared::TYPE_SLICE_U16 => {
|
||||
VectorType { owned: false, kind: VectorKind::U16 }
|
||||
}
|
||||
shared::TYPE_SLICE_I16 => {
|
||||
VectorType { owned: false, kind: VectorKind::I16 }
|
||||
}
|
||||
shared::TYPE_VECTOR_U32 => {
|
||||
VectorType { owned: true, kind: VectorKind::U32 }
|
||||
}
|
||||
shared::TYPE_VECTOR_I32 => {
|
||||
VectorType { owned: true, kind: VectorKind::I32 }
|
||||
}
|
||||
shared::TYPE_SLICE_U32 => {
|
||||
VectorType { owned: false, kind: VectorKind::U32 }
|
||||
}
|
||||
shared::TYPE_SLICE_I32 => {
|
||||
VectorType { owned: false, kind: VectorKind::I32 }
|
||||
}
|
||||
shared::TYPE_VECTOR_F32 => {
|
||||
VectorType { owned: true, kind: VectorKind::F32 }
|
||||
}
|
||||
shared::TYPE_VECTOR_F64 => {
|
||||
VectorType { owned: true, kind: VectorKind::F64 }
|
||||
}
|
||||
shared::TYPE_SLICE_F32 => {
|
||||
VectorType { owned: false, kind: VectorKind::F32 }
|
||||
}
|
||||
shared::TYPE_SLICE_F64 => {
|
||||
VectorType { owned: false, kind: VectorKind::F64 }
|
||||
}
|
||||
_ => panic!()
|
||||
}
|
||||
}
|
||||
|
||||
fn js_ty(&self) -> &str {
|
||||
match self.kind {
|
||||
VectorKind::String => "string",
|
||||
VectorKind::I8 => "Int8Array",
|
||||
VectorKind::U8 => "Uint8Array",
|
||||
VectorKind::I16 => "Int16Array",
|
||||
VectorKind::U16 => "Uint16Array",
|
||||
VectorKind::I32 => "Int32Array",
|
||||
VectorKind::U32 => "Uint32Array",
|
||||
VectorKind::F32 => "Float32Array",
|
||||
VectorKind::F64 => "Float64Array",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -49,14 +49,25 @@ pub struct Struct {
|
||||
|
||||
pub enum Type {
|
||||
// special
|
||||
BorrowedStr,
|
||||
String,
|
||||
Vector(VectorType, bool),
|
||||
|
||||
ByRef(syn::Type),
|
||||
ByMutRef(syn::Type),
|
||||
ByValue(syn::Type),
|
||||
}
|
||||
|
||||
pub enum VectorType {
|
||||
String,
|
||||
I8,
|
||||
U8,
|
||||
I16,
|
||||
U16,
|
||||
I32,
|
||||
U32,
|
||||
F32,
|
||||
F64,
|
||||
}
|
||||
|
||||
impl Program {
|
||||
pub fn push_item(&mut self,
|
||||
item: syn::Item,
|
||||
@ -216,8 +227,8 @@ impl Program {
|
||||
Type::ByMutRef(_) => {
|
||||
panic!("first method argument cannot be mutable ref")
|
||||
}
|
||||
Type::String | Type::BorrowedStr => {
|
||||
panic!("method receivers cannot be strings")
|
||||
Type::Vector(..) => {
|
||||
panic!("method receivers cannot be vectors")
|
||||
}
|
||||
};
|
||||
let class_name = match *class {
|
||||
@ -422,10 +433,15 @@ impl Type {
|
||||
syn::Type::Path(syn::TypePath { qself: None, ref path }) => {
|
||||
let ident = extract_path_ident(path);
|
||||
match ident.as_ref().map(|s| s.as_ref()) {
|
||||
Some("str") => return Type::BorrowedStr,
|
||||
Some("str") => return Type::Vector(VectorType::String, false),
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
syn::Type::Slice(ref slice) => {
|
||||
if let Some(ty) = VectorType::from(&slice.elem) {
|
||||
return Type::Vector(ty, false)
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
return if r.mutability.is_some() {
|
||||
@ -434,10 +450,29 @@ impl Type {
|
||||
Type::ByRef((*r.elem).clone())
|
||||
}
|
||||
}
|
||||
syn::Type::Path(syn::TypePath { qself: None, ref path }) => {
|
||||
let ident = extract_path_ident(path);
|
||||
match ident.as_ref().map(|s| s.as_ref()) {
|
||||
Some("String") => return Type::String,
|
||||
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)
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
@ -449,8 +484,24 @@ impl Type {
|
||||
|
||||
fn wbg_literal(&self, a: &mut LiteralBuilder) {
|
||||
match *self {
|
||||
Type::BorrowedStr => a.char(shared::TYPE_BORROWED_STR),
|
||||
Type::String => a.char(shared::TYPE_STRING),
|
||||
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),
|
||||
Type::ByValue(ref t) => {
|
||||
a.as_char(my_quote! {
|
||||
<#t as ::wasm_bindgen::convert::WasmBoundary>::DESCRIPTOR
|
||||
@ -849,3 +900,61 @@ fn term<'a>(cursor: syn::buffer::Cursor<'a>, name: &str)
|
||||
}
|
||||
syn::parse_error()
|
||||
}
|
||||
|
||||
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),
|
||||
_ => 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"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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> },
|
||||
};
|
||||
me.to_tokens(tokens);
|
||||
}
|
||||
}
|
||||
|
@ -144,29 +144,40 @@ fn bindgen_export(export: &ast::Export, into: &mut Tokens) {
|
||||
let i = i + offset;
|
||||
let ident = syn::Ident::from(format!("arg{}", i));
|
||||
match *ty {
|
||||
ast::Type::BorrowedStr => {
|
||||
ast::Type::Vector(ref ty, owned) => {
|
||||
let ptr = syn::Ident::from(format!("arg{}_ptr", i));
|
||||
let len = syn::Ident::from(format!("arg{}_len", i));
|
||||
args.push(my_quote! { #ptr: *const u8 });
|
||||
let abi_ty = ty.abi_element();
|
||||
args.push(my_quote! { #ptr: *const #abi_ty });
|
||||
args.push(my_quote! { #len: usize });
|
||||
arg_conversions.push(my_quote! {
|
||||
let #ident = unsafe {
|
||||
let slice = ::std::slice::from_raw_parts(#ptr, #len);
|
||||
::std::str::from_utf8_unchecked(slice)
|
||||
};
|
||||
});
|
||||
}
|
||||
ast::Type::String => {
|
||||
let ptr = syn::Ident::from(format!("arg{}_ptr", i));
|
||||
let len = syn::Ident::from(format!("arg{}_len", i));
|
||||
args.push(my_quote! { #ptr: *mut u8 });
|
||||
args.push(my_quote! { #len: usize });
|
||||
arg_conversions.push(my_quote! {
|
||||
let #ident = unsafe {
|
||||
let vec = ::std::vec::Vec::from_raw_parts(#ptr, #len, #len);
|
||||
::std::string::String::from_utf8_unchecked(vec)
|
||||
};
|
||||
});
|
||||
if owned {
|
||||
arg_conversions.push(my_quote! {
|
||||
let #ident = unsafe {
|
||||
::std::vec::Vec::from_raw_parts(#ptr, #len, #len)
|
||||
};
|
||||
});
|
||||
} else {
|
||||
arg_conversions.push(my_quote! {
|
||||
let #ident = unsafe {
|
||||
::std::slice::from_raw_parts(#ptr, #len)
|
||||
};
|
||||
});
|
||||
}
|
||||
if let ast::VectorType::String = *ty {
|
||||
if owned {
|
||||
arg_conversions.push(my_quote! {
|
||||
let #ident = unsafe {
|
||||
::std::string::String::from_utf8_unchecked(#ident)
|
||||
};
|
||||
});
|
||||
} else {
|
||||
arg_conversions.push(my_quote! {
|
||||
let #ident = unsafe {
|
||||
::std::str::from_utf8_unchecked(#ident)
|
||||
};
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
ast::Type::ByValue(ref t) => {
|
||||
args.push(my_quote! {
|
||||
@ -209,8 +220,8 @@ fn bindgen_export(export: &ast::Export, into: &mut Tokens) {
|
||||
let ret_ty;
|
||||
let convert_ret;
|
||||
match export.function.ret {
|
||||
Some(ast::Type::String) => {
|
||||
ret_ty = my_quote! { -> *mut String };
|
||||
Some(ast::Type::Vector(ref ty, true)) => {
|
||||
ret_ty = my_quote! { -> *mut #ty };
|
||||
convert_ret = my_quote! { Box::into_raw(Box::new(#ret)) };
|
||||
}
|
||||
Some(ast::Type::ByValue(ref t)) => {
|
||||
@ -221,7 +232,7 @@ fn bindgen_export(export: &ast::Export, into: &mut Tokens) {
|
||||
<#t as ::wasm_bindgen::convert::WasmBoundary>::into_js(#ret)
|
||||
};
|
||||
}
|
||||
Some(ast::Type::BorrowedStr) |
|
||||
Some(ast::Type::Vector(_, false)) |
|
||||
Some(ast::Type::ByMutRef(_)) |
|
||||
Some(ast::Type::ByRef(_)) => {
|
||||
panic!("can't return a borrowed ref");
|
||||
@ -344,17 +355,21 @@ fn bindgen_import(import: &ast::Import, tokens: &mut Tokens) {
|
||||
|
||||
for (i, (ty, name)) in import.function.arguments.iter().zip(names).enumerate() {
|
||||
match *ty {
|
||||
ast::Type::BorrowedStr => {
|
||||
ast::Type::Vector(ref ty, owned) => {
|
||||
let ptr = syn::Ident::from(format!("{}_ptr", name));
|
||||
let len = syn::Ident::from(format!("{}_len", name));
|
||||
abi_argument_names.push(ptr);
|
||||
abi_argument_names.push(len);
|
||||
abi_arguments.push(my_quote! { #ptr: *const u8 });
|
||||
let abi_ty = ty.abi_element();
|
||||
abi_arguments.push(my_quote! { #ptr: *const #abi_ty });
|
||||
abi_arguments.push(my_quote! { #len: usize });
|
||||
arg_conversions.push(my_quote! {
|
||||
let #ptr = #name.as_ptr();
|
||||
let #len = #name.len();
|
||||
});
|
||||
if owned {
|
||||
arg_conversions.push(my_quote! { ::std::mem::forget(#name); });
|
||||
}
|
||||
}
|
||||
ast::Type::ByValue(ref t) => {
|
||||
abi_argument_names.push(name);
|
||||
@ -389,20 +404,6 @@ fn bindgen_import(import: &ast::Import, tokens: &mut Tokens) {
|
||||
});
|
||||
}
|
||||
}
|
||||
// TODO: need to test this
|
||||
ast::Type::String => {
|
||||
let ptr = syn::Ident::from(format!("{}_ptr", name));
|
||||
let len = syn::Ident::from(format!("{}_len", name));
|
||||
abi_argument_names.push(ptr);
|
||||
abi_argument_names.push(len);
|
||||
abi_arguments.push(my_quote! { #ptr: *const u8 });
|
||||
abi_arguments.push(my_quote! { #len: usize });
|
||||
arg_conversions.push(my_quote! {
|
||||
let #ptr = #name.as_ptr();
|
||||
let #len = #name.len();
|
||||
::std::mem::forget(#name);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
let abi_ret;
|
||||
@ -417,25 +418,31 @@ fn bindgen_import(import: &ast::Import, tokens: &mut Tokens) {
|
||||
};
|
||||
}
|
||||
|
||||
// TODO: add a test for this
|
||||
Some(ast::Type::String) => {
|
||||
let name = syn::Ident::from("__ret_strlen");
|
||||
let name_ptr = syn::Ident::from("__ret_strlen_ptr");
|
||||
Some(ast::Type::Vector(ref ty, true)) => {
|
||||
let name = syn::Ident::from("__ret_len");
|
||||
let name_ptr = syn::Ident::from("__ret_len_ptr");
|
||||
abi_argument_names.push(name_ptr);
|
||||
abi_arguments.push(my_quote! { #name_ptr: *mut usize });
|
||||
arg_conversions.push(my_quote! {
|
||||
let mut #name = 0;
|
||||
let mut #name_ptr = &mut #name as *mut usize;
|
||||
});
|
||||
abi_ret = my_quote! { *mut u8 };
|
||||
convert_ret = my_quote! {
|
||||
String::from_utf8_unchecked(
|
||||
let abi_ty = ty.abi_element();
|
||||
abi_ret = my_quote! { *mut #abi_ty };
|
||||
if let ast::VectorType::String = *ty {
|
||||
convert_ret = my_quote! {
|
||||
String::from_utf8_unchecked(
|
||||
Vec::from_raw_parts(#ret_ident, #name, #name)
|
||||
)
|
||||
};
|
||||
} else {
|
||||
convert_ret = my_quote! {
|
||||
Vec::from_raw_parts(#ret_ident, #name, #name)
|
||||
)
|
||||
};
|
||||
};
|
||||
}
|
||||
}
|
||||
Some(ast::Type::BorrowedStr) |
|
||||
Some(ast::Type::ByRef(_)) |
|
||||
Some(ast::Type::Vector(_, false)) |
|
||||
Some(ast::Type::ByMutRef(_)) => panic!("can't return a borrowed ref"),
|
||||
None => {
|
||||
abi_ret = my_quote! { () };
|
||||
|
@ -81,8 +81,24 @@ pub const TYPE_NUMBER: char = '\u{5e}';
|
||||
pub const TYPE_BORROWED_STR: char = '\u{5f}';
|
||||
pub const TYPE_STRING: char = '\u{60}';
|
||||
pub const TYPE_BOOLEAN: char = '\u{61}';
|
||||
pub const TYPE_JS_OWNED: char = '\u{62}';
|
||||
pub const TYPE_JS_REF: char = '\u{63}';
|
||||
pub const TYPE_SLICE_U8: char = '\u{62}';
|
||||
pub const TYPE_VECTOR_U8: char = '\u{63}';
|
||||
pub const TYPE_SLICE_I8: char = '\u{64}';
|
||||
pub const TYPE_VECTOR_I8: char = '\u{65}';
|
||||
pub const TYPE_SLICE_U16: char = '\u{66}';
|
||||
pub const TYPE_VECTOR_U16: char = '\u{67}';
|
||||
pub const TYPE_SLICE_I16: char = '\u{68}';
|
||||
pub const TYPE_VECTOR_I16: char = '\u{69}';
|
||||
pub const TYPE_SLICE_U32: char = '\u{6a}';
|
||||
pub const TYPE_VECTOR_U32: char = '\u{6b}';
|
||||
pub const TYPE_SLICE_I32: char = '\u{6c}';
|
||||
pub const TYPE_VECTOR_I32: char = '\u{6d}';
|
||||
pub const TYPE_VECTOR_F32: char = '\u{6e}';
|
||||
pub const TYPE_SLICE_F32: char = '\u{6f}';
|
||||
pub const TYPE_VECTOR_F64: char = '\u{70}';
|
||||
pub const TYPE_SLICE_F64: char = '\u{71}';
|
||||
pub const TYPE_JS_OWNED: char = '\u{72}';
|
||||
pub const TYPE_JS_REF: char = '\u{73}';
|
||||
|
||||
pub const TYPE_CUSTOM_START: u32 = 0x64;
|
||||
pub const TYPE_CUSTOM_REF_FLAG: u32 = 1;
|
||||
|
232
tests/slice.rs
Normal file
232
tests/slice.rs
Normal file
@ -0,0 +1,232 @@
|
||||
extern crate test_support;
|
||||
|
||||
#[test]
|
||||
fn export() {
|
||||
test_support::project()
|
||||
.file("src/lib.rs", r#"
|
||||
#![feature(proc_macro)]
|
||||
|
||||
extern crate wasm_bindgen;
|
||||
|
||||
use wasm_bindgen::prelude::*;
|
||||
|
||||
macro_rules! doit {
|
||||
($($i:ident)*) => ($(
|
||||
#[no_mangle]
|
||||
#[wasm_bindgen]
|
||||
pub extern fn $i(a: &[$i]) -> Vec<$i> {
|
||||
assert_eq!(a.len(), 2);
|
||||
assert_eq!(a[0], 1 as $i);
|
||||
assert_eq!(a[1], 2 as $i);
|
||||
a.to_vec()
|
||||
}
|
||||
)*)
|
||||
}
|
||||
|
||||
|
||||
doit! { i8 u8 i16 u16 i32 u32 f32 f64 }
|
||||
"#)
|
||||
.file("test.ts", r#"
|
||||
import * as assert from "assert";
|
||||
import * as wasm from "./out";
|
||||
|
||||
function assert_arrays_equal(a: any, b: any) {
|
||||
console.log(a, b);
|
||||
assert.strictEqual(a.length, b.length);
|
||||
assert.strictEqual(a.byteLength, b.byteLength);
|
||||
for (let i = 0; i < a.length; i++) {
|
||||
assert.strictEqual(a[i], b[i]);
|
||||
}
|
||||
}
|
||||
|
||||
export function test() {
|
||||
const i8 = new Int8Array(2);
|
||||
i8[0] = 1;
|
||||
i8[1] = 2;
|
||||
assert_arrays_equal(wasm.i8(i8), i8);
|
||||
const u8 = new Uint8Array(2);
|
||||
u8[0] = 1;
|
||||
u8[1] = 2;
|
||||
assert_arrays_equal(wasm.u8(u8), u8);
|
||||
|
||||
const i16 = new Int16Array(2);
|
||||
i16[0] = 1;
|
||||
i16[1] = 2;
|
||||
assert_arrays_equal(wasm.i16(i16), i16);
|
||||
const u16 = new Uint16Array(2);
|
||||
u16[0] = 1;
|
||||
u16[1] = 2;
|
||||
assert_arrays_equal(wasm.u16(u16), u16);
|
||||
|
||||
const i32 = new Int32Array(2);
|
||||
i32[0] = 1;
|
||||
i32[1] = 2;
|
||||
wasm.i32(i32);
|
||||
assert_arrays_equal(wasm.i32(i32), i32);
|
||||
const u32 = new Uint32Array(2);
|
||||
u32[0] = 1;
|
||||
u32[1] = 2;
|
||||
assert_arrays_equal(wasm.u32(u32), u32);
|
||||
|
||||
const f32 = new Float32Array(2);
|
||||
f32[0] = 1;
|
||||
f32[1] = 2;
|
||||
assert_arrays_equal(wasm.f32(f32), f32);
|
||||
const f64 = new Float64Array(2);
|
||||
f64[0] = 1;
|
||||
f64[1] = 2;
|
||||
assert_arrays_equal(wasm.f64(f64), f64);
|
||||
}
|
||||
"#)
|
||||
.test();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn import() {
|
||||
test_support::project()
|
||||
.file("src/lib.rs", r#"
|
||||
#![feature(proc_macro)]
|
||||
|
||||
extern crate wasm_bindgen;
|
||||
|
||||
use wasm_bindgen::prelude::*;
|
||||
|
||||
macro_rules! doit {
|
||||
($(($rust:ident, $js:ident, $i:ident))*) => ($(
|
||||
#[wasm_bindgen(module = "./test")]
|
||||
extern {
|
||||
fn $js(a: &[$i]) -> Vec<$i>;
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
#[wasm_bindgen]
|
||||
pub extern fn $rust(a: &[$i]) -> Vec<$i> {
|
||||
assert_eq!(a.len(), 2);
|
||||
assert_eq!(a[0], 1 as $i);
|
||||
assert_eq!(a[1], 2 as $i);
|
||||
$js(a)
|
||||
}
|
||||
)*)
|
||||
}
|
||||
|
||||
|
||||
doit! {
|
||||
(rust_i8, js_i8, i8)
|
||||
(rust_u8, js_u8, u8)
|
||||
(rust_i16, js_i16, i16)
|
||||
(rust_u16, js_u16, u16)
|
||||
(rust_i32, js_i32, i32)
|
||||
(rust_u32, js_u32, u32)
|
||||
(rust_f32, js_f32, f32)
|
||||
(rust_f64, js_f64, f64)
|
||||
}
|
||||
"#)
|
||||
.file("test.ts", r#"
|
||||
import * as assert from "assert";
|
||||
import * as wasm from "./out";
|
||||
|
||||
export function js_i8(a: any): any {
|
||||
assert.strictEqual(a.length, 2);
|
||||
assert.strictEqual(a[0], 1);
|
||||
assert.strictEqual(a[1], 2);
|
||||
return a;
|
||||
}
|
||||
|
||||
export function js_u8(a: any): any {
|
||||
assert.strictEqual(a.length, 2);
|
||||
assert.strictEqual(a[0], 1);
|
||||
assert.strictEqual(a[1], 2);
|
||||
return a;
|
||||
}
|
||||
|
||||
export function js_i16(a: any): any {
|
||||
assert.strictEqual(a.length, 2);
|
||||
assert.strictEqual(a[0], 1);
|
||||
assert.strictEqual(a[1], 2);
|
||||
return a;
|
||||
}
|
||||
|
||||
export function js_u16(a: any): any {
|
||||
assert.strictEqual(a.length, 2);
|
||||
assert.strictEqual(a[0], 1);
|
||||
assert.strictEqual(a[1], 2);
|
||||
return a;
|
||||
}
|
||||
|
||||
export function js_i32(a: any): any {
|
||||
assert.strictEqual(a.length, 2);
|
||||
assert.strictEqual(a[0], 1);
|
||||
assert.strictEqual(a[1], 2);
|
||||
return a;
|
||||
}
|
||||
|
||||
export function js_u32(a: any): any {
|
||||
assert.strictEqual(a.length, 2);
|
||||
assert.strictEqual(a[0], 1);
|
||||
assert.strictEqual(a[1], 2);
|
||||
return a;
|
||||
}
|
||||
|
||||
export function js_f32(a: any): any {
|
||||
assert.strictEqual(a.length, 2);
|
||||
assert.strictEqual(a[0], 1);
|
||||
assert.strictEqual(a[1], 2);
|
||||
return a;
|
||||
}
|
||||
|
||||
export function js_f64(a: any): any {
|
||||
assert.strictEqual(a.length, 2);
|
||||
assert.strictEqual(a[0], 1);
|
||||
assert.strictEqual(a[1], 2);
|
||||
return a;
|
||||
}
|
||||
|
||||
function assert_arrays_equal(a: any, b: any) {
|
||||
console.log(a, b);
|
||||
assert.strictEqual(a.length, b.length);
|
||||
assert.strictEqual(a.byteLength, b.byteLength);
|
||||
for (let i = 0; i < a.length; i++) {
|
||||
assert.strictEqual(a[i], b[i]);
|
||||
}
|
||||
}
|
||||
|
||||
export function test() {
|
||||
const i8 = new Int8Array(2);
|
||||
i8[0] = 1;
|
||||
i8[1] = 2;
|
||||
assert_arrays_equal(wasm.rust_i8(i8), i8);
|
||||
const u8 = new Uint8Array(2);
|
||||
u8[0] = 1;
|
||||
u8[1] = 2;
|
||||
assert_arrays_equal(wasm.rust_u8(u8), u8);
|
||||
|
||||
const i16 = new Int16Array(2);
|
||||
i16[0] = 1;
|
||||
i16[1] = 2;
|
||||
assert_arrays_equal(wasm.rust_i16(i16), i16);
|
||||
const u16 = new Uint16Array(2);
|
||||
u16[0] = 1;
|
||||
u16[1] = 2;
|
||||
assert_arrays_equal(wasm.rust_u16(u16), u16);
|
||||
|
||||
const i32 = new Int32Array(2);
|
||||
i32[0] = 1;
|
||||
i32[1] = 2;
|
||||
assert_arrays_equal(wasm.rust_i32(i32), i32);
|
||||
const u32 = new Uint32Array(2);
|
||||
u32[0] = 1;
|
||||
u32[1] = 2;
|
||||
assert_arrays_equal(wasm.rust_u32(u32), u32);
|
||||
|
||||
const f32 = new Float32Array(2);
|
||||
f32[0] = 1;
|
||||
f32[1] = 2;
|
||||
assert_arrays_equal(wasm.rust_f32(f32), f32);
|
||||
const f64 = new Float64Array(2);
|
||||
f64[0] = 1;
|
||||
f64[1] = 2;
|
||||
assert_arrays_equal(wasm.rust_f64(f64), f64);
|
||||
}
|
||||
"#)
|
||||
.test();
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user