mirror of
https://github.com/fluencelabs/wasm-bindgen
synced 2025-06-14 21:41:23 +00:00
add char support (#206)
* add char support * add char test * remove __wbindgen_char fns * re-order travis script * update serve script * remove binds to unused char functions * add more wide character items to chars list * remove unused code * add char to readme * remove built file
This commit is contained in:
committed by
Alex Crichton
parent
17861a45ab
commit
4ddd93d75d
@ -51,9 +51,12 @@ matrix:
|
||||
(cd examples/dom && sed -i 's/: "webpack-dev-server"/: "webpack"/' package.json && ./build.sh)
|
||||
- |
|
||||
(cd examples/wasm-in-wasm && sed -i 's/: "webpack-dev-server"/: "webpack"/' package.json && ./build.sh)
|
||||
- |
|
||||
(cd examples/char && sed -i 's/: "webpack-dev-server"/: "webpack"/' package.json && ./build.sh)
|
||||
- |
|
||||
(cd examples/closures && sed -i 's/: "webpack-dev-server"/: "webpack"/' package.json && ./build.sh)
|
||||
|
||||
|
||||
install:
|
||||
- curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.33.8/install.sh | bash
|
||||
- source ~/.nvm/nvm.sh
|
||||
|
@ -44,6 +44,7 @@ members = [
|
||||
"examples/no_modules",
|
||||
"examples/add",
|
||||
"examples/asm.js",
|
||||
"examples/char",
|
||||
]
|
||||
|
||||
[profile.release]
|
||||
|
@ -32,6 +32,7 @@ tys! {
|
||||
ANYREF
|
||||
ENUM
|
||||
RUST_STRUCT
|
||||
CHAR
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
@ -57,6 +58,7 @@ pub enum Descriptor {
|
||||
Anyref,
|
||||
Enum,
|
||||
RustStruct(String),
|
||||
Char,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
@ -122,6 +124,7 @@ impl Descriptor {
|
||||
.collect();
|
||||
Descriptor::RustStruct(name)
|
||||
}
|
||||
CHAR => Descriptor::Char,
|
||||
other => panic!("unknown descriptor: {}", other),
|
||||
}
|
||||
}
|
||||
|
@ -3,7 +3,7 @@ use failure::Error;
|
||||
use super::{indent, Context};
|
||||
use descriptor::{Descriptor, Function};
|
||||
|
||||
/// Helper struct for manfuacturing a shim in JS used to translate JS types to
|
||||
/// Helper struct for manufacturing a shim in JS used to translate JS types to
|
||||
/// Rust, aka pass from JS back into Rust
|
||||
pub struct Js2Rust<'a, 'b: 'a> {
|
||||
cx: &'a mut Context<'b>,
|
||||
@ -210,6 +210,10 @@ impl<'a, 'b> Js2Rust<'a, 'b> {
|
||||
}
|
||||
self.rust_arguments.push(format!("{} ? 1 : 0", name));
|
||||
}
|
||||
Descriptor::Char => {
|
||||
self.js_arguments.push((name.clone(), "string".to_string()));
|
||||
self.rust_arguments.push(format!("{}.codePointAt(0)", name))
|
||||
},
|
||||
Descriptor::Anyref => {
|
||||
self.js_arguments.push((name.clone(), "any".to_string()));
|
||||
self.cx.expose_add_heap_object();
|
||||
@ -299,6 +303,10 @@ impl<'a, 'b> Js2Rust<'a, 'b> {
|
||||
self.ret_ty = "boolean".to_string();
|
||||
self.ret_expr = format!("return (RET) !== 0;");
|
||||
}
|
||||
Descriptor::Char => {
|
||||
self.ret_ty = "string".to_string();
|
||||
self.ret_expr = format!("return String.fromCodePoint(RET)")
|
||||
}
|
||||
Descriptor::Anyref => {
|
||||
self.ret_ty = "any".to_string();
|
||||
self.cx.expose_take_object();
|
||||
@ -316,7 +324,7 @@ impl<'a, 'b> Js2Rust<'a, 'b> {
|
||||
/// invoking, like `wasm.bar` or `this.f`.
|
||||
///
|
||||
/// Returns two strings, the first of which is the JS expression for the
|
||||
/// generated function shim and the second is a TyepScript signature of rthe
|
||||
/// generated function shim and the second is a TypeScript signature of the
|
||||
/// JS expression.
|
||||
pub fn finish(&self, prefix: &str, invoc: &str) -> (String, String) {
|
||||
let js_args = self.js_arguments
|
||||
|
@ -3,7 +3,7 @@ use failure::Error;
|
||||
use descriptor::{Descriptor, Function};
|
||||
use super::{indent, Context, Js2Rust};
|
||||
|
||||
/// Helper struct for manfuacturing a shim in JS used to translate Rust types to
|
||||
/// Helper struct for manufacturing a shim in JS used to translate Rust types to
|
||||
/// JS, then invoking an imported JS function.
|
||||
pub struct Rust2Js<'a, 'b: 'a> {
|
||||
cx: &'a mut Context<'b>,
|
||||
@ -211,6 +211,9 @@ impl<'a, 'b> Rust2Js<'a, 'b> {
|
||||
let invoc_arg = match *arg {
|
||||
ref d if d.is_number() => abi,
|
||||
Descriptor::Boolean => format!("{} !== 0", abi),
|
||||
Descriptor::Char => {
|
||||
format!("String.fromCodePoint({})", abi)
|
||||
}
|
||||
Descriptor::Anyref => {
|
||||
self.cx.expose_take_object();
|
||||
format!("takeObject({})", abi)
|
||||
@ -269,6 +272,7 @@ impl<'a, 'b> Rust2Js<'a, 'b> {
|
||||
}
|
||||
self.ret_expr = match *ty {
|
||||
Descriptor::Boolean => "return JS ? 1 : 0;".to_string(),
|
||||
Descriptor::Char => "return JS.codePointAt(0)".to_string(),
|
||||
Descriptor::Anyref => {
|
||||
self.cx.expose_add_heap_object();
|
||||
"return addHeapObject(JS);".to_string()
|
||||
|
@ -33,5 +33,6 @@ The examples here are:
|
||||
numbers.
|
||||
* `asm.js` - an example of using the `wasm2asm` tool from [binaryen] to convert
|
||||
the generated WebAssembly to normal JS
|
||||
* `char` - an example of passing the rust `char` type to and from the js `string` type
|
||||
|
||||
[binaryen]: https://github.com/WebAssembly/binaryen
|
||||
|
4
examples/char/.gitignore
vendored
Normal file
4
examples/char/.gitignore
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
package-lock.json
|
||||
char.js
|
||||
char_bg.js
|
||||
char_bg.wasm
|
14
examples/char/Cargo.toml
Normal file
14
examples/char/Cargo.toml
Normal file
@ -0,0 +1,14 @@
|
||||
[package]
|
||||
name = "char"
|
||||
version = "0.1.0"
|
||||
authors = ["Robert Masen <r@robertmasen.com>"]
|
||||
|
||||
[lib]
|
||||
crate-type = ["cdylib"]
|
||||
|
||||
[dependencies]
|
||||
# Here we're using a path dependency to use what's already in this repository,
|
||||
# but you'd use the commented out version below if you're copying this into your
|
||||
# project.
|
||||
wasm-bindgen = { path = "../.." }
|
||||
#wasm-bindgen = "0.2"
|
13
examples/char/README.md
Normal file
13
examples/char/README.md
Normal file
@ -0,0 +1,13 @@
|
||||
# Char
|
||||
|
||||
This directory is an example of how the `#[wasm_bindgen]` macro will convert the rust `char` type to a single code-point js `string`.
|
||||
|
||||
You can build the example locally with:
|
||||
|
||||
```
|
||||
$ ./build.sh
|
||||
```
|
||||
|
||||
Opening your web browser should display a single counter with a random character for it's `key` and 0 for its `count`. You can click the `+` button to increase a counter's count. By clicking on the "add counter" button you should see a new counter added to the list with a different random character for it's `key`.
|
||||
|
||||
Under the hood javascript is choosing a random character from an Array of characters and passing that to the rust Counter struct's constructor so the character you are seeing on the page has made the full round trip from js to rust and back to js.
|
22
examples/char/build.sh
Executable file
22
examples/char/build.sh
Executable file
@ -0,0 +1,22 @@
|
||||
#!/bin/sh
|
||||
|
||||
set -ex
|
||||
|
||||
# Build the `hello_world.wasm` file using Cargo/rustc
|
||||
cargo +nightly build --target wasm32-unknown-unknown
|
||||
|
||||
# Run the `wasm-bindgen` CLI tool to postprocess the wasm file emitted by the
|
||||
# Rust compiler to emit the JS support glue that's necessary
|
||||
#
|
||||
# Here we're using the version of the CLI in this repository, but for external
|
||||
# usage you'd use the commented out version below
|
||||
cargo +nightly run --manifest-path ../../crates/cli/Cargo.toml \
|
||||
--bin wasm-bindgen -- \
|
||||
../../target/wasm32-unknown-unknown/debug/char.wasm --out-dir .
|
||||
# wasm-bindgen ../../target/wasm32-unknown-unknown/hello_world.wasm --out-dir .
|
||||
|
||||
# Finally, package everything up using Webpack and start a server so we can
|
||||
# browse the result
|
||||
|
||||
npm install
|
||||
npm run serve
|
85
examples/char/chars.js
Normal file
85
examples/char/chars.js
Normal file
@ -0,0 +1,85 @@
|
||||
export let chars = [
|
||||
"!","#","$","%","&","'","(",")","*","+",",",
|
||||
"-",".","/","0","1","2","3","4","5","6","7",
|
||||
"8","9",":",";","<","=",">","?","@","A","B",
|
||||
"C","D","E","F","G","H","I","J","K","L","M",
|
||||
"N","O","P","Q","R","S","T","U","V","W","X",
|
||||
"Y","Z","[","]","^","_","`","a","b","c",
|
||||
"d","e","f","g","h","i","j","k","l","m","n",
|
||||
"o","p","q","r","s","t","u","v","w","x","y",
|
||||
"z","{","|","}","~"," ","¡","¢","£","¤","¥",
|
||||
"¦","§","¨","©","ª","«","¬","®","¯","°",
|
||||
"±","²","³","´","µ","¶","·","¸","¹","º","»",
|
||||
"¼","½","¾","¿","À","Á","Â","Ã","Ä","Å","Æ",
|
||||
"Ç","È","É","Ê","Ë","Ì","Í","Î","Ï","Ð","Ñ",
|
||||
"Ò","Ó","Ô","Õ","Ö","×","Ø","Ù","Ú","Û","Ü",
|
||||
"Ý","Þ","ß","à","á","â","ã","ä","å","æ","ç",
|
||||
"è","é","ê","ë","ì","í","î","ï","ð","ñ","ò",
|
||||
"ó","ô","õ","ö","÷","ø","ù","ú","û","ü","ý",
|
||||
"þ","ÿ","Ā","ā","Ă","ă","Ą","ą","Ć","ć","Ĉ",
|
||||
"ĉ","Ċ","ċ","Č","č","Ď","ď","Đ","đ","Ē","ē",
|
||||
"Ĕ","ĕ","Ė","ė","Ę","ę","Ě","ě","Ĝ","ĝ","Ğ",
|
||||
"ğ","Ġ","ġ","Ģ","ģ","Ĥ","ĥ","Ħ","ħ","Ĩ","ĩ",
|
||||
"Ī","ī","Ĭ","ĭ","Į","į","İ","ı","IJ","ij","Ĵ",
|
||||
"ĵ","Ķ","ķ","ĸ","Ĺ","ĺ","Ļ","ļ","Ľ","ľ","Ŀ",
|
||||
"ŀ","Ł","ł","Ń","ń","Ņ","ņ","Ň","ň","ʼn","Ŋ",
|
||||
"ŋ","Ō","ō","Ŏ","ŏ","Ő","ő","Œ","œ","Ŕ","ŕ",
|
||||
"Ŗ","ŗ","Ř","ř","Ś","ś","Ŝ","ŝ","Ş","ş","Š",
|
||||
"š","Ţ","ţ","Ť","ť","Ŧ","ŧ","Ũ","ũ","Ū","ū",
|
||||
"Ŭ","ŭ","Ů","ů","Ű","ű","Ų","ų","Ŵ","ŵ","Ŷ",
|
||||
"ŷ","Ÿ","Ź","ź","Ż","ż","Ž","ž","ſ","ƀ","Ɓ",
|
||||
"Ƃ","ƃ","Ƅ","ƅ","Ɔ","Ƈ","ƈ","Ɖ","Ɗ","Ƌ","ƌ",
|
||||
"ƍ","Ǝ","Ə","Ɛ","Ƒ","ƒ","Ɠ","Ɣ","ƕ","Ɩ","Ɨ",
|
||||
"Ƙ","ƙ","ƚ","ƛ","Ɯ","Ɲ","ƞ","Ɵ","Ơ","ơ","Ƣ",
|
||||
"ƣ","Ƥ","ƥ","Ʀ","Ƨ","ƨ","Ʃ","ƪ","ƫ","Ƭ","ƭ",
|
||||
"Ʈ","Ư","ư","Ʊ","Ʋ","Ƴ","ƴ","Ƶ","ƶ","Ʒ","Ƹ",
|
||||
"ƹ","ƺ","ƻ","Ƽ","ƽ","ƾ","ƿ","ǀ","ǁ","ǂ","ǃ",
|
||||
"DŽ","Dž","dž","LJ","Lj","lj","NJ","Nj","nj","Ǎ","ǎ",
|
||||
"Ǐ","ǐ","Ǒ","ǒ","Ǔ","ǔ","Ǖ","ǖ","Ǘ","ǘ","Ǚ",
|
||||
"ǚ","Ǜ","ǜ","ǝ","Ǟ","ǟ","Ǡ","ǡ","Ǣ","ǣ","Ǥ",
|
||||
"ǥ","Ǧ","ǧ","Ǩ","ǩ","Ǫ","ǫ","Ǭ","ǭ","Ǯ","ǯ",
|
||||
"ǰ","DZ","Dz","dz","Ǵ","ǵ","Ƕ","Ƿ","Ǹ","ǹ","Ǻ",
|
||||
"ǻ","Ǽ","ǽ","Ǿ","ǿ","Ȁ","ȁ","Ȃ","ȃ","Ȅ","ȅ",
|
||||
"Ȇ","ȇ","Ȉ","ȉ","Ȋ","ȋ","Ȍ","ȍ","Ȏ","ȏ","Ȑ",
|
||||
"ȑ","Ȓ","ȓ","Ȕ","ȕ","Ȗ","ȗ","Ș","ș","Ț","ț",
|
||||
"Ȝ","ȝ","Ȟ","ȟ","Ƞ","ȡ","Ȣ","ȣ","Ȥ","ȥ","Ȧ",
|
||||
"ȧ","Ȩ","ȩ","Ȫ","ȫ","Ȭ","ȭ","Ȯ","ȯ","Ȱ","ȱ",
|
||||
"Ȳ","ȳ","ȴ","ȵ","ȶ","ȷ","ȸ","ȹ","Ⱥ","Ȼ","ȼ",
|
||||
"Ƚ","Ⱦ","ȿ","ɀ","Ɂ","ɂ","Ƀ","Ʉ","Ʌ","Ɇ","ɇ",
|
||||
"Ɉ","ɉ","Ɋ","ɋ","Ɍ","ɍ","Ɏ","ɏ","ɐ","ɑ","ɒ",
|
||||
"ɓ","ɔ","ɕ","ɖ","ɗ","ɘ","ə","ɚ","ɛ","ɜ","ɝ",
|
||||
"ɞ","ɟ","ɠ","ɡ","ɢ","ɣ","ɤ","ɥ","ɦ","ɧ","ɨ",
|
||||
"ɩ","ɪ","ɫ","ɬ","ɭ","ɮ","ɯ","ɰ","ɱ","ɲ","ɳ",
|
||||
"ɴ","ɵ","ɶ","ɷ","ɸ","ɹ","ɺ","ɻ","ɼ","ɽ","ɾ",
|
||||
"ɿ","ʀ","ʁ","ʂ","ʃ","ʄ","ʅ","ʆ","ʇ","ʈ","ʉ",
|
||||
"ʊ","ʋ","ʌ","ʍ","ʎ","ʏ","ʐ","ʑ","ʒ","ʓ","ʔ",
|
||||
"ʕ","ʖ","ʗ","ʘ","ʙ","ʚ","ʛ","ʜ","ʝ","ʞ","ʟ",
|
||||
"ʠ","ʡ","ʢ","ʣ","ʤ","ʥ","ʦ","ʧ","ʨ","ʩ","ʪ",
|
||||
"ʫ","ʬ","ʭ","ʮ","ʯ","Ͳ","ͳ","ʹ","͵","Ͷ","ͷ",
|
||||
"ͺ","ͻ","ͼ","ͽ",";","Ϳ","΄","΅","Ά","·","Έ","Ή",
|
||||
"Ί","Ό","Ύ","Ώ",
|
||||
"ΐ","Α","Β","Γ","Δ","Ε","Ζ","Η","Θ","Ι","Κ",
|
||||
"Λ","Μ","Ν","Ξ","Ο","Π","Ρ","Σ","Τ","Υ","Φ",
|
||||
"Χ","Ψ","Ω","Ϊ","Ϋ","ά","έ","ή","ί","ΰ","α",
|
||||
"β","γ","δ","ε","ζ","η","θ","ι","κ","λ","μ",
|
||||
"ν","ξ","ο","π","ρ","ς","σ","τ","υ","φ","χ",
|
||||
"ψ","ω","ϊ","ϋ","ό","ύ","ώ","Ϗ","ϐ","ϑ","ϒ",
|
||||
"ϓ","ϔ","ϕ","ϖ","ϗ","Ϙ","ϙ","Ϛ","ϛ","Ϝ","ϝ",
|
||||
"Ϟ","ϟ","Ϡ","ϡ","Ϣ","ϣ","Ϥ","ϥ","Ϧ","ϧ","Ϩ",
|
||||
"ϩ","Ϫ","ϫ","Ϭ","ϭ","Ϯ","ϯ","ϰ","ϱ","ϲ","ϳ",
|
||||
"Օ","Ֆ","🕧","🕨","🕩","🕪","🕫","🕬","🕭","🕮",
|
||||
"🕯","🕰","🕱","🕲","🕳","🕴","🕵","🕶","🕷","🕸",
|
||||
"🕹","🕺","🕻","🕼","🕽","🕾","🕿","🖀","🖁","🖂",
|
||||
"🖃","🖄","🖅","🖆","🖇","🖈","🖉","🖊","🖋",
|
||||
"🖌","🖍","🖎","🖏","🖐","🖑","🖒","🖓","🖔","🖕",
|
||||
"🖖","🖗","🖘","🖙","🖚","🖛","🖜","🖝","🖞","🖟",
|
||||
"🖠","🖡","🖢","🖣","🖤","🖥","🖦","🖧","🖨","🖩",
|
||||
"🖪","🖫","🖬","🖭","🖮","🖯","🖰","🖱","🖲","🖳",
|
||||
"🖴","🖵","🖶","🖷","🖸","🖹","🖺","🖻","🖼","🖽",
|
||||
"🖾","🖿","🗀","🗁","🗂","🗃","🗄","🗅","🗆","🗇",
|
||||
"🗈","🗉","🗊","🗋","🗌","🗍","🗎","🗏","🗐","🗑","🗒",
|
||||
"🗓","🗔","🗕","🗖","🗗","🗘","🗙","🗚","🗛","🗜",
|
||||
"🗝","🗞","🗟","🗠","🗡","🗢","🗣","🗤","🗥","🗦",
|
||||
"🗧","🗨","🗩","🗪","🗫","🗬","🗭","🗮","🗯","🗰",
|
||||
"🗱","🗲","🗳","🗴","🗵","🗶","🗷","🗸","🗹","🗺",
|
||||
"🗻","🗼","🗽","🗾","🗿","😀"];
|
56
examples/char/index.html
Normal file
56
examples/char/index.html
Normal file
@ -0,0 +1,56 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Counter</title>
|
||||
<style>
|
||||
* {
|
||||
font-family: sans-serif;
|
||||
font-size: 16pt;
|
||||
}
|
||||
h1 {
|
||||
font-size: 18pt;
|
||||
font-weight: bold;
|
||||
margin: 0;
|
||||
}
|
||||
button {
|
||||
padding: 5px 10px;
|
||||
border: none;
|
||||
background: slategrey;
|
||||
margin: 10px auto;
|
||||
color: white;
|
||||
}
|
||||
body {
|
||||
width: 400px;
|
||||
margin: auto;
|
||||
}
|
||||
#container,
|
||||
.counter {
|
||||
display: flex;
|
||||
flex-flow: column;
|
||||
justify-content: flex-start;
|
||||
align-items: flex-start;
|
||||
align-content: flex-start;
|
||||
}
|
||||
.counter {
|
||||
margin-bottom: 10px;
|
||||
background: steelblue;
|
||||
color: white;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
}
|
||||
.field {
|
||||
display: flex;
|
||||
flex-flow: row;
|
||||
justify-content: space-around;
|
||||
width: 100%;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<button id="add-counter" type="button">add counter</button>
|
||||
<div id="container">
|
||||
|
||||
</div>
|
||||
<script type="text/javascript" src="index.js"></script>
|
||||
</body>
|
||||
</html>
|
73
examples/char/index.js
Normal file
73
examples/char/index.js
Normal file
@ -0,0 +1,73 @@
|
||||
import {chars} from './chars.js'
|
||||
let imp = import('./char.js')
|
||||
let mod;
|
||||
|
||||
let counters = [];
|
||||
imp.then(wasm => {
|
||||
mod = wasm;
|
||||
addCounter();
|
||||
let b = document.getElementById('add-counter');
|
||||
if (!b) throw new Error('Unable to find #add-counter');
|
||||
b.addEventListener('click', ev => addCounter())
|
||||
});
|
||||
|
||||
function addCounter() {
|
||||
let ctr = mod.Counter.new(randomChar(), 0);
|
||||
counters.push(ctr);
|
||||
update();
|
||||
}
|
||||
|
||||
function update() {
|
||||
let container = document.getElementById('container');
|
||||
if (!container) throw new Error('Unable to find #container in dom');
|
||||
while (container.hasChildNodes()) {
|
||||
if (container.lastChild.id == "add-counter") break;
|
||||
container.removeChild(container.lastChild);
|
||||
}
|
||||
for (var i = 0; i < counters.length; i++) {
|
||||
let counter = counters[i];
|
||||
container.appendChild(newCounter(counter.key(), counter.count(), ev => {
|
||||
counter.increment();
|
||||
update();
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
||||
function randomChar() {
|
||||
console.log('randomChar');
|
||||
let idx = Math.floor(Math.random() * (chars.length - 1));
|
||||
console.log('index', idx);
|
||||
let ret = chars.splice(idx, 1)[0];
|
||||
console.log('char', ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
function newCounter(key, value, cb) {
|
||||
let container = document.createElement('div');
|
||||
container.setAttribute('class', 'counter');
|
||||
let title = document.createElement('h1');
|
||||
title.appendChild(document.createTextNode('Counter ' + key));
|
||||
container.appendChild(title);
|
||||
container.appendChild(newField('Count', value));
|
||||
let plus = document.createElement('button');
|
||||
plus.setAttribute('type', 'button');
|
||||
plus.setAttribute('class', 'plus-button');
|
||||
plus.appendChild(document.createTextNode('+'));
|
||||
plus.addEventListener('click', cb);
|
||||
container.appendChild(plus);
|
||||
return container;
|
||||
}
|
||||
|
||||
function newField(key, value) {
|
||||
let ret = document.createElement('div');
|
||||
ret.setAttribute('class', 'field');
|
||||
let name = document.createElement('span');
|
||||
name.setAttribute('class', 'name');
|
||||
name.appendChild(document.createTextNode(key));
|
||||
ret.appendChild(name);
|
||||
let val = document.createElement('span');
|
||||
val.setAttribute('class', 'value');
|
||||
val.appendChild(document.createTextNode(value));
|
||||
ret.appendChild(val);
|
||||
return ret;
|
||||
}
|
10
examples/char/package.json
Normal file
10
examples/char/package.json
Normal file
@ -0,0 +1,10 @@
|
||||
{
|
||||
"scripts": {
|
||||
"serve": "webpack-dev-server"
|
||||
},
|
||||
"devDependencies": {
|
||||
"webpack": "^4.8.3",
|
||||
"webpack-cli": "^2.1.3",
|
||||
"webpack-dev-server": "^3.1.4"
|
||||
}
|
||||
}
|
49
examples/char/src/lib.rs
Normal file
49
examples/char/src/lib.rs
Normal file
@ -0,0 +1,49 @@
|
||||
#![feature(proc_macro, wasm_custom_section, wasm_import_module)]
|
||||
|
||||
extern crate wasm_bindgen;
|
||||
|
||||
use wasm_bindgen::prelude::*;
|
||||
|
||||
#[wasm_bindgen]
|
||||
extern {
|
||||
#[wasm_bindgen(js_namespace = console)]
|
||||
fn log(s: &str);
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
#[wasm_bindgen]
|
||||
pub struct Counter {
|
||||
key: char,
|
||||
count: i32
|
||||
}
|
||||
|
||||
#[wasm_bindgen]
|
||||
impl Counter {
|
||||
pub fn default() -> Counter {
|
||||
log("Counter::default");
|
||||
Self::new('a', 0)
|
||||
}
|
||||
pub fn new(key: char, count: i32) -> Counter {
|
||||
log(&format!("Counter::new({}, {})", key, count));
|
||||
Counter { key: key, count: count }
|
||||
}
|
||||
|
||||
pub fn key(&self) -> char {
|
||||
log("Counter.key()");
|
||||
self.key
|
||||
}
|
||||
|
||||
pub fn count(&self) -> i32 {
|
||||
log("Counter.count");
|
||||
self.count
|
||||
}
|
||||
|
||||
pub fn increment(&mut self) {
|
||||
log("Counter.increment");
|
||||
self.count += 1;
|
||||
}
|
||||
|
||||
pub fn update_key(&mut self, key: char) {
|
||||
self.key = key;
|
||||
}
|
||||
}
|
10
examples/char/webpack.config.js
Normal file
10
examples/char/webpack.config.js
Normal file
@ -0,0 +1,10 @@
|
||||
const path = require('path');
|
||||
|
||||
module.exports = {
|
||||
entry: "./index.js",
|
||||
output: {
|
||||
path: path.resolve(__dirname, "dist"),
|
||||
filename: "index.js",
|
||||
},
|
||||
mode: "development"
|
||||
};
|
@ -1,10 +1,11 @@
|
||||
//! This is mostly an internal module, no stability guarantees are provied. Use
|
||||
//! This is mostly an internal module, no stability guarantees are provided. Use
|
||||
//! at your own risk.
|
||||
|
||||
use core::mem::{self, ManuallyDrop};
|
||||
use core::ops::{Deref, DerefMut};
|
||||
use core::slice;
|
||||
use core::str;
|
||||
use core::char;
|
||||
|
||||
use {JsValue, throw};
|
||||
use describe::*;
|
||||
@ -134,6 +135,18 @@ impl FromWasmAbi for bool {
|
||||
unsafe fn from_abi(js: u32, _extra: &mut Stack) -> bool { js != 0 }
|
||||
}
|
||||
|
||||
impl IntoWasmAbi for char {
|
||||
type Abi = u32;
|
||||
fn into_abi(self, _extra: &mut Stack) -> u32 { self as u32 }
|
||||
}
|
||||
|
||||
impl FromWasmAbi for char {
|
||||
type Abi = u32;
|
||||
unsafe fn from_abi(js: u32, _extra: &mut Stack) -> char {
|
||||
char::from_u32_unchecked(js)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> IntoWasmAbi for *const T {
|
||||
type Abi = u32;
|
||||
|
||||
|
@ -37,6 +37,7 @@ tys! {
|
||||
ANYREF
|
||||
ENUM
|
||||
RUST_STRUCT
|
||||
CHAR
|
||||
}
|
||||
|
||||
pub fn inform(a: u32) {
|
||||
@ -71,6 +72,7 @@ simple! {
|
||||
f32 => F32
|
||||
f64 => F64
|
||||
bool => BOOLEAN
|
||||
char => CHAR
|
||||
str => STRING
|
||||
JsValue => ANYREF
|
||||
}
|
||||
|
60
tests/all/char.rs
Normal file
60
tests/all/char.rs
Normal file
@ -0,0 +1,60 @@
|
||||
use super::project;
|
||||
|
||||
#[test]
|
||||
fn works() {
|
||||
project()
|
||||
.file("src/lib.rs", r#"
|
||||
#![feature(proc_macro, wasm_custom_section, wasm_import_module)]
|
||||
|
||||
extern crate wasm_bindgen;
|
||||
|
||||
use wasm_bindgen::prelude::*;
|
||||
|
||||
#[wasm_bindgen(module = "./test")]
|
||||
extern {
|
||||
fn js_parrot(c: char) -> char;
|
||||
}
|
||||
|
||||
#[wasm_bindgen]
|
||||
pub fn single_char() -> char { 'a' }
|
||||
#[wasm_bindgen]
|
||||
pub fn wide_char() -> char { '💩' }
|
||||
|
||||
#[wasm_bindgen]
|
||||
pub fn parrot(c: char) -> char { c }
|
||||
|
||||
#[wasm_bindgen]
|
||||
pub fn short_test(a: char) { assert_eq!(a, 'a'); }
|
||||
#[wasm_bindgen]
|
||||
pub fn wide_test(p: char) { assert_eq!(p, '💩'); }
|
||||
|
||||
#[wasm_bindgen]
|
||||
pub fn char_round(c: char)-> char { js_parrot(c) }
|
||||
"#)
|
||||
.file("test.js", r#"
|
||||
import * as wasm from './out';
|
||||
|
||||
function assertEq(a, b) {
|
||||
console.log(a, '?=', b);
|
||||
if (a === b)
|
||||
return;
|
||||
throw new Error('not equal');
|
||||
}
|
||||
|
||||
export function test() {
|
||||
assertEq(wasm.single_char(), 'a');
|
||||
assertEq(wasm.wide_char(), '💩');
|
||||
assertEq(wasm.parrot('Ղ'), 'Ղ');
|
||||
assertEq(wasm.parrot('ҝ'), 'ҝ');
|
||||
assertEq(wasm.parrot('Δ'), 'Δ');
|
||||
assertEq(wasm.parrot('䉨'), '䉨');
|
||||
assertEq(wasm.char_round('a'), 'a');
|
||||
assertEq(wasm.char_round('㊻'), '㊻');
|
||||
wasm.short_test('a');
|
||||
wasm.wide_test('💩');
|
||||
}
|
||||
|
||||
export function js_parrot(a) { return a; }
|
||||
"#)
|
||||
.test();
|
||||
}
|
@ -382,3 +382,4 @@ mod slice;
|
||||
mod structural;
|
||||
mod non_wasm;
|
||||
mod u64;
|
||||
mod char;
|
Reference in New Issue
Block a user