mirror of
https://github.com/fluencelabs/assemblyscript
synced 2025-06-13 06:51:34 +00:00
PSON decoder example using namespaced imports
This commit is contained in:
19
examples/pson/README.md
Normal file
19
examples/pson/README.md
Normal file
@ -0,0 +1,19 @@
|
||||
PSON decoder in WebAssembly
|
||||
===========================
|
||||
|
||||
An [AssemblyScript](http://assemblyscript.org) example. Decodes a [PSON](https://github.com/dcodeIO/PSON) encoded buffer.
|
||||
|
||||
Instructions
|
||||
------------
|
||||
|
||||
To build [assembly/pson.ts](./assembly/pson.ts) to an untouched and an optimized `.wasm` including their respective `.wast` representations, run:
|
||||
|
||||
```
|
||||
$> npm run build
|
||||
```
|
||||
|
||||
Afterwards, to run the included test, do:
|
||||
|
||||
```
|
||||
$> npm test
|
||||
```
|
156
examples/pson/assembly/pson.ts
Normal file
156
examples/pson/assembly/pson.ts
Normal file
@ -0,0 +1,156 @@
|
||||
const enum Token {
|
||||
ZERO = 0x00,
|
||||
MAX = 0xEF,
|
||||
NULL = 0xf0,
|
||||
TRUE = 0xf1,
|
||||
FALSE = 0xf2,
|
||||
EOBJECT = 0xf3,
|
||||
EARRAY = 0xf4,
|
||||
ESTRING = 0xf5,
|
||||
OBJECT = 0xf6,
|
||||
ARRAY = 0xf7,
|
||||
INTEGER = 0xf8,
|
||||
LONG = 0xf9,
|
||||
FLOAT = 0xfa,
|
||||
DOUBLE = 0xfb,
|
||||
STRING = 0xfc,
|
||||
STRING_ADD = 0xfd,
|
||||
STRING_GET = 0xfe,
|
||||
BINARY = 0xff
|
||||
}
|
||||
|
||||
namespace pson {
|
||||
export declare function onNull(): void;
|
||||
export declare function onTrue(): void;
|
||||
export declare function onFalse(): void;
|
||||
export declare function onEObject(): void;
|
||||
export declare function onEArray(): void;
|
||||
export declare function onEString(): void;
|
||||
export declare function onObject(size: u32): void;
|
||||
export declare function onArray(size: u32): void;
|
||||
export declare function onInteger(value: i32): void;
|
||||
export declare function onLong(valueLow: i32, valueHigh: i32): void;
|
||||
export declare function onFloat(value: f32): void;
|
||||
export declare function onDouble(value: f64): void;
|
||||
export declare function onString(offset: usize, length: u32): void;
|
||||
export declare function onBinary(offset: usize, length: u32): void;
|
||||
export declare function onTruncated(): void;
|
||||
}
|
||||
|
||||
var offset: usize = 0;
|
||||
|
||||
export function decode(length: usize): void {
|
||||
offset = 0;
|
||||
while (offset < length)
|
||||
decodeValue();
|
||||
if (offset != length)
|
||||
pson.onTruncated();
|
||||
}
|
||||
|
||||
function decodeValue(): void {
|
||||
var token: u32 = load<u8>(offset++);
|
||||
var size: u32;
|
||||
var long: u64;
|
||||
switch (token) {
|
||||
|
||||
case Token.NULL:
|
||||
pson.onNull();
|
||||
break;
|
||||
|
||||
case Token.TRUE:
|
||||
pson.onTrue();
|
||||
break;
|
||||
|
||||
case Token.FALSE:
|
||||
pson.onFalse();
|
||||
break;
|
||||
|
||||
case Token.EOBJECT:
|
||||
pson.onEObject();
|
||||
break;
|
||||
|
||||
case Token.EARRAY:
|
||||
pson.onEArray();
|
||||
break;
|
||||
|
||||
case Token.ESTRING:
|
||||
pson.onEString();
|
||||
break;
|
||||
|
||||
case Token.OBJECT:
|
||||
pson.onObject(size = readVarint32());
|
||||
while (size--) {
|
||||
decodeValue();
|
||||
decodeValue();
|
||||
}
|
||||
break;
|
||||
|
||||
case Token.ARRAY:
|
||||
pson.onArray(size = readVarint32());
|
||||
while (size--)
|
||||
decodeValue();
|
||||
break;
|
||||
|
||||
case Token.INTEGER:
|
||||
pson.onInteger(((size = readVarint32()) >> 1) ^ -(size & 1));
|
||||
break;
|
||||
|
||||
case Token.LONG:
|
||||
long = ((long = readVarint64()) >> 1) ^ -(long & 1);
|
||||
pson.onLong(<i32>long, <i32>(long >>> 32));
|
||||
break;
|
||||
|
||||
case Token.FLOAT:
|
||||
pson.onFloat(load<f32>(offset));
|
||||
offset += 4;
|
||||
break;
|
||||
|
||||
case Token.DOUBLE:
|
||||
pson.onDouble(load<f64>(offset));
|
||||
offset += 8;
|
||||
break;
|
||||
|
||||
case Token.STRING:
|
||||
size = readVarint32();
|
||||
pson.onString(offset, size);
|
||||
offset += size;
|
||||
break;
|
||||
|
||||
case Token.STRING_ADD:
|
||||
case Token.STRING_GET:
|
||||
// could be implemented via imports as well, but isn't necessary for this example
|
||||
throw new Error("not implemented");
|
||||
|
||||
case Token.BINARY:
|
||||
size = readVarint32();
|
||||
pson.onBinary(offset, size);
|
||||
offset += size;
|
||||
break;
|
||||
|
||||
default: // small integer?
|
||||
if (token > Token.MAX)
|
||||
throw new Error("unexpected token");
|
||||
pson.onInteger((token >> 1) ^ -(token & 1));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
function readVarint32(): u32 {
|
||||
var value: u32 = 0;
|
||||
var shift: u32 = 0;
|
||||
do {
|
||||
var b = load<u8>(offset++);
|
||||
value |= <u32>(b & 0x7f) << (7 * shift++);
|
||||
} while (b & 0x80);
|
||||
return value;
|
||||
}
|
||||
|
||||
function readVarint64(): u64 {
|
||||
var value: u64 = 0;
|
||||
var shift: u64 = 0;
|
||||
do {
|
||||
var b = load<u8>(offset++);
|
||||
value |= <u64>(b & 0x7f) << (7 * shift++);
|
||||
} while (b & 0x80);
|
||||
return value;
|
||||
}
|
6
examples/pson/assembly/tsconfig.json
Normal file
6
examples/pson/assembly/tsconfig.json
Normal file
@ -0,0 +1,6 @@
|
||||
{
|
||||
"extends": "../../../std/assembly.json",
|
||||
"include": [
|
||||
"./**/*.ts"
|
||||
]
|
||||
}
|
71
examples/pson/index.js
Normal file
71
examples/pson/index.js
Normal file
@ -0,0 +1,71 @@
|
||||
var fs = require("fs");
|
||||
|
||||
// Define imports. Just logs to console for the sake of this example.
|
||||
var pson = {
|
||||
onNull: function() {
|
||||
console.log("null");
|
||||
},
|
||||
onTrue: function() {
|
||||
console.log("true");
|
||||
},
|
||||
onFalse: function() {
|
||||
console.log("false");
|
||||
},
|
||||
onEObject: function() {
|
||||
console.log("{}");
|
||||
},
|
||||
onEArray: function() {
|
||||
console.log("[]");
|
||||
},
|
||||
onEString: function() {
|
||||
console.log("\"\"");
|
||||
},
|
||||
onObject: function(size) {
|
||||
console.log("{" + size + "}")
|
||||
},
|
||||
onArray: function(size) {
|
||||
console.log("[" + size + "]");
|
||||
},
|
||||
onInteger: function(value) {
|
||||
console.log("integer: " + value);
|
||||
},
|
||||
onLong: function(valueLow, valueHigh) {
|
||||
console.log("long: " + valueLow + ", " + valueHigh);
|
||||
},
|
||||
onFloat: function(value) {
|
||||
console.log("float: " + value);
|
||||
},
|
||||
onDouble: function(value) {
|
||||
console.log("double: " + value);
|
||||
},
|
||||
onString: function(offset, length) {
|
||||
console.log("string(length=" + length + "): " + new Buffer(mem.slice(offset, offset + length)).toString());
|
||||
},
|
||||
onBinary: function(offset, length) {
|
||||
console.log("binary(length=" + length + "): " + mem.slice(offset, offset + length));
|
||||
},
|
||||
onTruncated: function() {
|
||||
console.log("buffer is truncated :-(");
|
||||
}
|
||||
};
|
||||
|
||||
// Instantiate the module
|
||||
var mod = new WebAssembly.Module(fs.readFileSync(__dirname + "/pson.optimized.wasm"));
|
||||
var ins = new WebAssembly.Instance(mod, { pson: pson });
|
||||
var mem = new Uint8Array(ins.exports.memory.buffer);
|
||||
|
||||
// Export API
|
||||
exports.decode = function(buffer) {
|
||||
|
||||
// grow memory if necessary
|
||||
if (mem.length < buffer.length) {
|
||||
ins.exports.memory.grow(Math.ceil((buffer.length - mem.length) / 65536));
|
||||
mem = new Uint8Array(ins.exports.memory.buffer);
|
||||
}
|
||||
|
||||
// copy buffer to memory
|
||||
mem.set(buffer);
|
||||
|
||||
// start decoding (calls the imports defined above)
|
||||
ins.exports.decode(buffer.length);
|
||||
}
|
14
examples/pson/package.json
Normal file
14
examples/pson/package.json
Normal file
@ -0,0 +1,14 @@
|
||||
{
|
||||
"name": "@assemblyscript/pson-example",
|
||||
"version": "1.0.0",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"build": "npm run build:untouched && npm run build:optimized",
|
||||
"build:untouched": "asc assembly/pson.ts -b pson.untouched.wasm -t pson.untouched.wast --validate",
|
||||
"build:optimized": "asc -O assembly/pson.ts -b pson.optimized.wasm -t pson.optimized.wast --validate",
|
||||
"test": "node tests"
|
||||
},
|
||||
"devDependencies": {
|
||||
"pson": "^2.0.0"
|
||||
}
|
||||
}
|
24
examples/pson/tests/index.js
Normal file
24
examples/pson/tests/index.js
Normal file
@ -0,0 +1,24 @@
|
||||
var Long = require("long");
|
||||
|
||||
var psonJS = require("pson");
|
||||
var psonWASM = require("..");
|
||||
|
||||
// encode in JS
|
||||
var buf = new psonJS.Encoder().encode({
|
||||
emptyObject: {},
|
||||
emptyArray: [],
|
||||
emptyString: "",
|
||||
object: {
|
||||
aSmallInt: 42,
|
||||
anInt: 9000,
|
||||
aLong: Long.MIN_VALUE.add(1)
|
||||
},
|
||||
array: [
|
||||
0.25, // fits into float
|
||||
0.1 // always a double
|
||||
],
|
||||
binary: Buffer.from([1, 2, 3])
|
||||
}).toBuffer();
|
||||
|
||||
// decode in WASM
|
||||
psonWASM.decode(buf);
|
Reference in New Issue
Block a user