@thi.ng/wasm-api 0.10.0 → 0.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +48 -1
- package/README.md +146 -120
- package/api.d.ts +76 -11
- package/bridge.d.ts +11 -1
- package/bridge.js +13 -8
- package/cli.js +27 -6
- package/codegen/c.d.ts +33 -0
- package/codegen/c.js +100 -0
- package/codegen/c11.d.ts +22 -0
- package/codegen/c11.js +125 -0
- package/codegen/typescript.d.ts +2 -12
- package/codegen/typescript.js +120 -84
- package/codegen/utils.d.ts +48 -1
- package/codegen/utils.js +55 -0
- package/codegen/zig.d.ts +2 -9
- package/codegen/zig.js +54 -28
- package/codegen.d.ts +1 -23
- package/codegen.js +31 -8
- package/doc/assets/main.js +52 -0
- package/doc/assets/search.js +1 -0
- package/include/wasmapi.h +34 -20
- package/include/wasmapi.zig +53 -46
- package/index.d.ts +3 -0
- package/index.js +3 -0
- package/package.json +31 -19
- package/pointer.d.ts +23 -0
- package/pointer.js +27 -0
- package/string.d.ts +97 -0
- package/string.js +145 -0
package/include/wasmapi.zig
CHANGED
|
@@ -3,9 +3,24 @@
|
|
|
3
3
|
const std = @import("std");
|
|
4
4
|
const root = @import("root");
|
|
5
5
|
|
|
6
|
+
/// JS external part of the custom panic handler
|
|
7
|
+
/// Prints message using configured JS logger and then throws JS error
|
|
8
|
+
pub extern "wasmapi" fn _panic(addr: [*]const u8, len: usize) noreturn;
|
|
9
|
+
|
|
10
|
+
/// Custom panic handler which prints given message using configured JS logger
|
|
11
|
+
/// To use this handler, add the following line to your **root** source file:
|
|
12
|
+
///
|
|
13
|
+
/// ```
|
|
14
|
+
/// pub const panic = @import("wasmapi").panic;
|
|
15
|
+
/// ```
|
|
16
|
+
pub fn panic(msg: []const u8, _: ?*std.builtin.StackTrace) noreturn {
|
|
17
|
+
_panic(msg.ptr, msg.len);
|
|
18
|
+
unreachable;
|
|
19
|
+
}
|
|
20
|
+
|
|
6
21
|
/// Obtains the allocator to be exposed to the WASM host env
|
|
7
22
|
/// (via `_wasm_allocate()` and `_wasm_free()`).
|
|
8
|
-
/// If the user defines a public `WASM_ALLOCATOR` in their root file
|
|
23
|
+
/// If the user defines a public `WASM_ALLOCATOR` in their **root** file
|
|
9
24
|
/// then this allocator will be used, otherwise the implementations
|
|
10
25
|
/// of the two mentioned functions are no-ops.
|
|
11
26
|
/// The `WASM_ALLOCATOR` can be changed and/or enabled/disabled dynamically
|
|
@@ -32,9 +47,9 @@ pub export fn _wasm_allocate(numBytes: usize) usize {
|
|
|
32
47
|
/// Frees chunk of heap memory (previously allocated using `_wasm_allocate()`)
|
|
33
48
|
/// starting at given address and of given byte length.
|
|
34
49
|
/// Note: This is a no-op if no allocator is configured (see `allocator()`)
|
|
35
|
-
pub export fn _wasm_free(addr:
|
|
50
|
+
pub export fn _wasm_free(addr: [*]u8, numBytes: usize) void {
|
|
36
51
|
if (allocator()) |alloc| {
|
|
37
|
-
var mem = [2]usize{ addr, numBytes };
|
|
52
|
+
var mem = [2]usize{ @ptrToInt(addr), numBytes };
|
|
38
53
|
alloc.free(@ptrCast(*[]u8, &mem).*);
|
|
39
54
|
}
|
|
40
55
|
}
|
|
@@ -60,26 +75,12 @@ pub extern "wasmapi" fn printU32(x: u32) void;
|
|
|
60
75
|
/// Prints hex number using configured JS logger
|
|
61
76
|
pub extern "wasmapi" fn printU32Hex(x: u32) void;
|
|
62
77
|
|
|
63
|
-
/// Prints
|
|
64
|
-
pub extern "wasmapi" fn
|
|
65
|
-
///
|
|
66
|
-
pub fn
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
/// Prints decomposed u64 number using configured JS logger
|
|
71
|
-
pub extern "wasmapi" fn _printU64(hi: u32, lo: u32) void;
|
|
72
|
-
/// Convenience wrapper for _printU64(), accepting an u64
|
|
73
|
-
pub fn printU64(x: u64) void {
|
|
74
|
-
_printU64(@truncate(u32, x >> 32), @truncate(u32, x));
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
/// Prints decomposed u64 hex number using configured JS logger
|
|
78
|
-
pub extern "wasmapi" fn _printU64Hex(hi: u32, lo: u32) void;
|
|
79
|
-
/// Convenience wrapper for _printU64Hex(), accepting an u64
|
|
80
|
-
pub fn printU64Hex(x: u64) void {
|
|
81
|
-
_printU64Hex(@truncate(u32, x >> 32), @truncate(u32, x));
|
|
82
|
-
}
|
|
78
|
+
/// Prints i64 number using configured JS logger
|
|
79
|
+
pub extern "wasmapi" fn printI64(x: i64) void;
|
|
80
|
+
/// Prints u64 number using configured JS logger
|
|
81
|
+
pub extern "wasmapi" fn printU64(x: u64) void;
|
|
82
|
+
/// Prints u64 hex number using configured JS logger
|
|
83
|
+
pub extern "wasmapi" fn printU64Hex(x: u64) void;
|
|
83
84
|
|
|
84
85
|
/// Prints number using configured JS logger
|
|
85
86
|
pub extern "wasmapi" fn printF32(x: f32) void;
|
|
@@ -92,74 +93,74 @@ pub fn printPtr(ptr: *const anyopaque) void {
|
|
|
92
93
|
}
|
|
93
94
|
|
|
94
95
|
/// Prints number array using configured JS logger
|
|
95
|
-
pub extern "wasmapi" fn _printI8Array(addr:
|
|
96
|
+
pub extern "wasmapi" fn _printI8Array(addr: [*]const i8, len: usize) void;
|
|
96
97
|
/// Prints number array using configured JS logger
|
|
97
|
-
pub extern "wasmapi" fn _printU8Array(addr:
|
|
98
|
+
pub extern "wasmapi" fn _printU8Array(addr: [*]const u8, len: usize) void;
|
|
98
99
|
/// Prints number array using configured JS logger
|
|
99
|
-
pub extern "wasmapi" fn _printI16Array(addr:
|
|
100
|
+
pub extern "wasmapi" fn _printI16Array(addr: [*]const i16, len: usize) void;
|
|
100
101
|
/// Prints number array using configured JS logger
|
|
101
|
-
pub extern "wasmapi" fn _printU16Array(addr:
|
|
102
|
+
pub extern "wasmapi" fn _printU16Array(addr: [*]const u16, len: usize) void;
|
|
102
103
|
/// Prints number array using configured JS logger
|
|
103
|
-
pub extern "wasmapi" fn _printI32Array(addr:
|
|
104
|
+
pub extern "wasmapi" fn _printI32Array(addr: [*]const i32, len: usize) void;
|
|
104
105
|
/// Prints number array using configured JS logger
|
|
105
|
-
pub extern "wasmapi" fn _printU32Array(addr:
|
|
106
|
+
pub extern "wasmapi" fn _printU32Array(addr: [*]const u32, len: usize) void;
|
|
106
107
|
/// Prints number array using configured JS logger
|
|
107
|
-
pub extern "wasmapi" fn _printI64Array(addr:
|
|
108
|
+
pub extern "wasmapi" fn _printI64Array(addr: [*]const i64, len: usize) void;
|
|
108
109
|
/// Prints number array using configured JS logger
|
|
109
|
-
pub extern "wasmapi" fn _printU64Array(addr:
|
|
110
|
+
pub extern "wasmapi" fn _printU64Array(addr: [*]const u64, len: usize) void;
|
|
110
111
|
/// Prints number array using configured JS logger
|
|
111
|
-
pub extern "wasmapi" fn _printF32Array(addr:
|
|
112
|
+
pub extern "wasmapi" fn _printF32Array(addr: [*]const f32, len: usize) void;
|
|
112
113
|
/// Prints number array using configured JS logger
|
|
113
|
-
pub extern "wasmapi" fn _printF64Array(addr:
|
|
114
|
+
pub extern "wasmapi" fn _printF64Array(addr: [*]const f64, len: usize) void;
|
|
114
115
|
|
|
115
116
|
/// Prints number array using configured JS logger
|
|
116
117
|
pub fn printI8Array(buf: []const i8) void {
|
|
117
|
-
_printI8Array(
|
|
118
|
+
_printI8Array(buf.ptr, buf.len);
|
|
118
119
|
}
|
|
119
120
|
/// Prints number array using configured JS logger
|
|
120
121
|
pub fn printU8Array(buf: []const u8) void {
|
|
121
|
-
_printU8Array(
|
|
122
|
+
_printU8Array(buf.ptr, buf.len);
|
|
122
123
|
}
|
|
123
124
|
/// Prints number array using configured JS logger
|
|
124
125
|
pub fn printI16Array(buf: []const i16) void {
|
|
125
|
-
_printI16Array(
|
|
126
|
+
_printI16Array(buf.ptr, buf.len);
|
|
126
127
|
}
|
|
127
128
|
/// Prints number array using configured JS logger
|
|
128
129
|
pub fn printU16Array(buf: []const u16) void {
|
|
129
|
-
_printU16Array(
|
|
130
|
+
_printU16Array(buf.ptr, buf.len);
|
|
130
131
|
}
|
|
131
132
|
/// Prints number array using configured JS logger
|
|
132
133
|
pub fn printI32Array(buf: []const i32) void {
|
|
133
|
-
_printI32Array(
|
|
134
|
+
_printI32Array(buf.ptr, buf.len);
|
|
134
135
|
}
|
|
135
136
|
/// Prints number array using configured JS logger
|
|
136
137
|
pub fn printU32Array(buf: []const u32) void {
|
|
137
|
-
_printU32Array(
|
|
138
|
+
_printU32Array(buf.ptr, buf.len);
|
|
138
139
|
}
|
|
139
140
|
/// Prints number array using configured JS logger
|
|
140
141
|
pub fn printI64Array(buf: []const i64) void {
|
|
141
|
-
_printI64Array(
|
|
142
|
+
_printI64Array(buf.ptr, buf.len);
|
|
142
143
|
}
|
|
143
144
|
/// Prints number array using configured JS logger
|
|
144
145
|
pub fn printU64Array(buf: []const u64) void {
|
|
145
|
-
_printU64Array(
|
|
146
|
+
_printU64Array(buf.ptr, buf.len);
|
|
146
147
|
}
|
|
147
148
|
/// Prints number array using configured JS logger
|
|
148
149
|
pub fn printF32Array(buf: []const f32) void {
|
|
149
|
-
_printF32Array(
|
|
150
|
+
_printF32Array(buf.ptr, buf.len);
|
|
150
151
|
}
|
|
151
152
|
/// Prints number array using configured JS logger
|
|
152
153
|
pub fn printF64Array(buf: []const f64) void {
|
|
153
|
-
_printF64Array(
|
|
154
|
+
_printF64Array(buf.ptr, buf.len);
|
|
154
155
|
}
|
|
155
156
|
|
|
156
157
|
/// Prints a zero-terminated string using configured JS logger
|
|
157
|
-
pub extern "wasmapi" fn _printStr0(addr:
|
|
158
|
+
pub extern "wasmapi" fn _printStr0(addr: [*]const u8) void;
|
|
158
159
|
/// Prints a string of given length using configured JS logger
|
|
159
|
-
pub extern "wasmapi" fn _printStr(addr:
|
|
160
|
+
pub extern "wasmapi" fn _printStr(addr: [*]const u8, len: usize) void;
|
|
160
161
|
/// Convenience wrapper for _printStr, accepting a slice as arg
|
|
161
162
|
pub fn printStr(msg: []const u8) void {
|
|
162
|
-
_printStr(
|
|
163
|
+
_printStr(msg.ptr, msg.len);
|
|
163
164
|
}
|
|
164
165
|
|
|
165
166
|
/// Calls std.fmt.allocPrint to format given string, then calls `printStr()`
|
|
@@ -175,3 +176,9 @@ pub fn printFmt(comptime fmt: []const u8, args: anytype) void {
|
|
|
175
176
|
|
|
176
177
|
/// Triggers the JS/browser debugger
|
|
177
178
|
pub extern "wasmapi" fn debug() void;
|
|
179
|
+
|
|
180
|
+
/// Returns a JS/browser highres timer value (via `performance.now()`)
|
|
181
|
+
pub extern "wasmapi" fn timer() f64;
|
|
182
|
+
|
|
183
|
+
/// Returns a JS/browser Unix epoch (via `Date.now()`)
|
|
184
|
+
pub extern "wasmapi" fn epoch() u64;
|
package/index.d.ts
CHANGED
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
export * from "./api.js";
|
|
2
2
|
export * from "./bridge.js";
|
|
3
3
|
export * from "./codegen.js";
|
|
4
|
+
export * from "./codegen/c11.js";
|
|
4
5
|
export * from "./codegen/typescript.js";
|
|
5
6
|
export * from "./codegen/utils.js";
|
|
6
7
|
export * from "./codegen/zig.js";
|
|
7
8
|
export * from "./object-index.js";
|
|
9
|
+
export * from "./pointer.js";
|
|
10
|
+
export * from "./string.js";
|
|
8
11
|
//# sourceMappingURL=index.d.ts.map
|
package/index.js
CHANGED
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
export * from "./api.js";
|
|
2
2
|
export * from "./bridge.js";
|
|
3
3
|
export * from "./codegen.js";
|
|
4
|
+
export * from "./codegen/c11.js";
|
|
4
5
|
export * from "./codegen/typescript.js";
|
|
5
6
|
export * from "./codegen/utils.js";
|
|
6
7
|
export * from "./codegen/zig.js";
|
|
7
8
|
export * from "./object-index.js";
|
|
9
|
+
export * from "./pointer.js";
|
|
10
|
+
export * from "./string.js";
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@thi.ng/wasm-api",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "Generic, modular, extensible API bridge, glue code and bindings code
|
|
3
|
+
"version": "0.11.0",
|
|
4
|
+
"description": "Generic, modular, extensible API bridge, polyglot glue code and bindings code generators for hybrid JS & WebAssembly projects",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"module": "./index.js",
|
|
7
7
|
"typings": "./index.d.ts",
|
|
@@ -36,25 +36,26 @@
|
|
|
36
36
|
"test:build-zig": "zig build-lib -O ReleaseSmall -target wasm32-freestanding -dynamic --strip --pkg-begin wasmapi include/wasmapi.zig --pkg-end test/custom.zig && wasm-dis -o custom.wast custom.wasm && cp custom.wasm test"
|
|
37
37
|
},
|
|
38
38
|
"dependencies": {
|
|
39
|
-
"@thi.ng/api": "^8.4.
|
|
40
|
-
"@thi.ng/args": "^2.2.
|
|
41
|
-
"@thi.ng/binary": "^3.3.
|
|
42
|
-
"@thi.ng/checks": "^3.2.
|
|
43
|
-
"@thi.ng/compare": "^2.1.
|
|
44
|
-
"@thi.ng/defmulti": "^2.1.
|
|
45
|
-
"@thi.ng/errors": "^2.
|
|
46
|
-
"@thi.ng/file-io": "^0.3.
|
|
47
|
-
"@thi.ng/hex": "^2.
|
|
48
|
-
"@thi.ng/idgen": "^2.1.
|
|
49
|
-
"@thi.ng/logger": "^1.
|
|
39
|
+
"@thi.ng/api": "^8.4.2",
|
|
40
|
+
"@thi.ng/args": "^2.2.2",
|
|
41
|
+
"@thi.ng/binary": "^3.3.5",
|
|
42
|
+
"@thi.ng/checks": "^3.2.5",
|
|
43
|
+
"@thi.ng/compare": "^2.1.12",
|
|
44
|
+
"@thi.ng/defmulti": "^2.1.14",
|
|
45
|
+
"@thi.ng/errors": "^2.2.0",
|
|
46
|
+
"@thi.ng/file-io": "^0.3.11",
|
|
47
|
+
"@thi.ng/hex": "^2.2.0",
|
|
48
|
+
"@thi.ng/idgen": "^2.1.13",
|
|
49
|
+
"@thi.ng/logger": "^1.3.0",
|
|
50
|
+
"@thi.ng/paths": "^5.1.15"
|
|
50
51
|
},
|
|
51
52
|
"devDependencies": {
|
|
52
|
-
"@microsoft/api-extractor": "^7.
|
|
53
|
-
"@thi.ng/testament": "^0.
|
|
53
|
+
"@microsoft/api-extractor": "^7.31.1",
|
|
54
|
+
"@thi.ng/testament": "^0.3.0",
|
|
54
55
|
"rimraf": "^3.0.2",
|
|
55
56
|
"tools": "^0.0.1",
|
|
56
57
|
"typedoc": "^0.22.17",
|
|
57
|
-
"typescript": "^4.
|
|
58
|
+
"typescript": "^4.8.3"
|
|
58
59
|
},
|
|
59
60
|
"keywords": [
|
|
60
61
|
"allocator",
|
|
@@ -62,10 +63,12 @@
|
|
|
62
63
|
"bindings",
|
|
63
64
|
"c",
|
|
64
65
|
"codegen",
|
|
66
|
+
"enum",
|
|
65
67
|
"event",
|
|
66
68
|
"id",
|
|
67
69
|
"logger",
|
|
68
70
|
"memory",
|
|
71
|
+
"polyglot",
|
|
69
72
|
"string",
|
|
70
73
|
"struct",
|
|
71
74
|
"typedarray",
|
|
@@ -103,8 +106,8 @@
|
|
|
103
106
|
"./bridge": {
|
|
104
107
|
"default": "./bridge.js"
|
|
105
108
|
},
|
|
106
|
-
"./codegen": {
|
|
107
|
-
"default": "./codegen.js"
|
|
109
|
+
"./codegen/c11": {
|
|
110
|
+
"default": "./codegen/c11.js"
|
|
108
111
|
},
|
|
109
112
|
"./codegen/typescript": {
|
|
110
113
|
"default": "./codegen/typescript.js"
|
|
@@ -115,13 +118,22 @@
|
|
|
115
118
|
"./codegen/zig": {
|
|
116
119
|
"default": "./codegen/zig.js"
|
|
117
120
|
},
|
|
121
|
+
"./codegen": {
|
|
122
|
+
"default": "./codegen.js"
|
|
123
|
+
},
|
|
118
124
|
"./object-index": {
|
|
119
125
|
"default": "./object-index.js"
|
|
126
|
+
},
|
|
127
|
+
"./pointer": {
|
|
128
|
+
"default": "./pointer.js"
|
|
129
|
+
},
|
|
130
|
+
"./string": {
|
|
131
|
+
"default": "./string.js"
|
|
120
132
|
}
|
|
121
133
|
},
|
|
122
134
|
"thi.ng": {
|
|
123
135
|
"status": "alpha",
|
|
124
136
|
"year": 2022
|
|
125
137
|
},
|
|
126
|
-
"gitHead": "
|
|
138
|
+
"gitHead": "973139c5aa3b50081020f4cc726a7cc330f77fc7\n"
|
|
127
139
|
}
|
package/pointer.d.ts
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { Fn, IDeref } from "@thi.ng/api";
|
|
2
|
+
import type { IWasmMemoryAccess } from "./api.js";
|
|
3
|
+
/**
|
|
4
|
+
* Generic pointer facility which on {@link Pointer.deref()} calls wrapper
|
|
5
|
+
* function (provided as ctor arg) to realise the pointer's target value. The
|
|
6
|
+
* pointer's target address can be accessed via {@link Pointer.addr}
|
|
7
|
+
* (read/write).
|
|
8
|
+
*
|
|
9
|
+
* @remarks
|
|
10
|
+
* The pointer always behaves like `volatile`, i.e. memoization of target values
|
|
11
|
+
* is purposfully avoided and the wrapper function is executed anew _each_ time
|
|
12
|
+
* the pointer is deref'd.
|
|
13
|
+
*/
|
|
14
|
+
export declare class Pointer<T> implements IDeref<T> {
|
|
15
|
+
readonly mem: IWasmMemoryAccess;
|
|
16
|
+
readonly base: number;
|
|
17
|
+
readonly fn: Fn<number, T>;
|
|
18
|
+
constructor(mem: IWasmMemoryAccess, base: number, fn: Fn<number, T>);
|
|
19
|
+
get addr(): number;
|
|
20
|
+
set addr(addr: number);
|
|
21
|
+
deref(): T;
|
|
22
|
+
}
|
|
23
|
+
//# sourceMappingURL=pointer.d.ts.map
|
package/pointer.js
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Generic pointer facility which on {@link Pointer.deref()} calls wrapper
|
|
3
|
+
* function (provided as ctor arg) to realise the pointer's target value. The
|
|
4
|
+
* pointer's target address can be accessed via {@link Pointer.addr}
|
|
5
|
+
* (read/write).
|
|
6
|
+
*
|
|
7
|
+
* @remarks
|
|
8
|
+
* The pointer always behaves like `volatile`, i.e. memoization of target values
|
|
9
|
+
* is purposfully avoided and the wrapper function is executed anew _each_ time
|
|
10
|
+
* the pointer is deref'd.
|
|
11
|
+
*/
|
|
12
|
+
export class Pointer {
|
|
13
|
+
constructor(mem, base, fn) {
|
|
14
|
+
this.mem = mem;
|
|
15
|
+
this.base = base;
|
|
16
|
+
this.fn = fn;
|
|
17
|
+
}
|
|
18
|
+
get addr() {
|
|
19
|
+
return this.mem.u32[this.base >>> 2];
|
|
20
|
+
}
|
|
21
|
+
set addr(addr) {
|
|
22
|
+
this.mem.u32[this.base >>> 2] = addr;
|
|
23
|
+
}
|
|
24
|
+
deref() {
|
|
25
|
+
return this.fn(this.addr);
|
|
26
|
+
}
|
|
27
|
+
}
|
package/string.d.ts
ADDED
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import type { IDeref } from "@thi.ng/api";
|
|
2
|
+
import type { IWasmMemoryAccess } from "./api.js";
|
|
3
|
+
/**
|
|
4
|
+
* Memory mapped string wrapper for Zig-style UTF-8 encoded byte slices (aka
|
|
5
|
+
* pointer & length pair). The actual JS string can be obtained via
|
|
6
|
+
* {@link WasmStringSlice.deref} and mutated via {@link WasmStringSlice.set}.
|
|
7
|
+
*/
|
|
8
|
+
export declare class WasmStringSlice implements IDeref<string> {
|
|
9
|
+
readonly mem: IWasmMemoryAccess;
|
|
10
|
+
readonly base: number;
|
|
11
|
+
readonly isConst: boolean;
|
|
12
|
+
readonly max: number;
|
|
13
|
+
constructor(mem: IWasmMemoryAccess, base: number, isConst?: boolean);
|
|
14
|
+
/**
|
|
15
|
+
* Returns string start address (deref'd pointer).
|
|
16
|
+
*/
|
|
17
|
+
get addr(): number;
|
|
18
|
+
/**
|
|
19
|
+
* Returns string length (read from memory)
|
|
20
|
+
*/
|
|
21
|
+
get length(): number;
|
|
22
|
+
/**
|
|
23
|
+
* Returns memory as JS string (aka wrapper for
|
|
24
|
+
* {@link WasmBridge.getString}).
|
|
25
|
+
*/
|
|
26
|
+
deref(): string;
|
|
27
|
+
/**
|
|
28
|
+
* If given a JS string as arg (and if **not** a const slice), attempts to
|
|
29
|
+
* overwrite this wrapped string's memory with bytes from given string. If
|
|
30
|
+
* given another {@link WasmStringSlice} as arg, only the slice pointer &
|
|
31
|
+
* new length will be updated (always succeeds).
|
|
32
|
+
*
|
|
33
|
+
* @remarks
|
|
34
|
+
* When copying bytes from a JS string, an error will be thrown if the new
|
|
35
|
+
* string is longer than the _original_ length of the slice (i.e. from when
|
|
36
|
+
* this `WasmStringSlice` wrapper instance was created). Also updates the
|
|
37
|
+
* slice's length field to new string length.
|
|
38
|
+
*
|
|
39
|
+
* Passing a `WasmString` instance as arg is faster than JS string since
|
|
40
|
+
* only the slice definition itself will be updated.
|
|
41
|
+
*
|
|
42
|
+
* @param str
|
|
43
|
+
*/
|
|
44
|
+
set(str: string | WasmStringSlice): void;
|
|
45
|
+
toJSON(): string;
|
|
46
|
+
toString(): string;
|
|
47
|
+
valueOf(): string;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Memory mapped string wrapper for C-style UTF-8 encoded and zero-terminated
|
|
51
|
+
* char pointers. The actual JS string can be obtained via
|
|
52
|
+
* {@link WasmStringSlice.deref} and mutated via {@link WasmStringSlice.set}.
|
|
53
|
+
*/
|
|
54
|
+
export declare class WasmStringPtr implements IDeref<string> {
|
|
55
|
+
readonly mem: IWasmMemoryAccess;
|
|
56
|
+
readonly base: number;
|
|
57
|
+
readonly isConst: boolean;
|
|
58
|
+
constructor(mem: IWasmMemoryAccess, base: number, isConst?: boolean);
|
|
59
|
+
/**
|
|
60
|
+
* Returns string start address (deref'd pointer).
|
|
61
|
+
*/
|
|
62
|
+
get addr(): number;
|
|
63
|
+
set addr(addr: number);
|
|
64
|
+
/**
|
|
65
|
+
* Returns computed string length (scanning memory for zero sentinel)
|
|
66
|
+
*/
|
|
67
|
+
get length(): number;
|
|
68
|
+
/**
|
|
69
|
+
* Returns memory as JS string (aka wrapper for
|
|
70
|
+
* {@link WasmBridge.getString}).
|
|
71
|
+
*/
|
|
72
|
+
deref(): string;
|
|
73
|
+
/**
|
|
74
|
+
* If given a JS string as arg (and if not a const pointer), attempts to
|
|
75
|
+
* overwrite this wrapped string's memory with bytes from given string. If
|
|
76
|
+
* given another {@link WasmStringPtr}, it merely overrides the pointer to
|
|
77
|
+
* the new one (always succeeds).
|
|
78
|
+
*
|
|
79
|
+
* @remarks
|
|
80
|
+
* Unlike with {@link WasmStringSlice.set} this implementation which
|
|
81
|
+
* performs bounds checking when copying bytes from a JS string, this method
|
|
82
|
+
* only throws an error if the new string is longer than the available
|
|
83
|
+
* memory (from the start address until the end of the WASM memory).
|
|
84
|
+
* **Therefore, this is as (un)safe as a C pointer and should be used with
|
|
85
|
+
* caution!**
|
|
86
|
+
*
|
|
87
|
+
* Passing a `WasmStringPtr` instance as arg is faster than JS string since
|
|
88
|
+
* only the pointer itself will be updated.
|
|
89
|
+
*
|
|
90
|
+
* @param str
|
|
91
|
+
*/
|
|
92
|
+
set(str: string | WasmStringPtr): void;
|
|
93
|
+
toJSON(): string;
|
|
94
|
+
toString(): string;
|
|
95
|
+
valueOf(): string;
|
|
96
|
+
}
|
|
97
|
+
//# sourceMappingURL=string.d.ts.map
|
package/string.js
ADDED
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
import { unsupported } from "@thi.ng/errors/unsupported";
|
|
2
|
+
/**
|
|
3
|
+
* Memory mapped string wrapper for Zig-style UTF-8 encoded byte slices (aka
|
|
4
|
+
* pointer & length pair). The actual JS string can be obtained via
|
|
5
|
+
* {@link WasmStringSlice.deref} and mutated via {@link WasmStringSlice.set}.
|
|
6
|
+
*/
|
|
7
|
+
export class WasmStringSlice {
|
|
8
|
+
constructor(mem, base, isConst = true) {
|
|
9
|
+
this.mem = mem;
|
|
10
|
+
this.base = base;
|
|
11
|
+
this.isConst = isConst;
|
|
12
|
+
this.max = this.length;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Returns string start address (deref'd pointer).
|
|
16
|
+
*/
|
|
17
|
+
get addr() {
|
|
18
|
+
return this.mem.u32[this.base >>> 2];
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Returns string length (read from memory)
|
|
22
|
+
*/
|
|
23
|
+
get length() {
|
|
24
|
+
return this.mem.u32[(this.base + 4) >>> 2];
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Returns memory as JS string (aka wrapper for
|
|
28
|
+
* {@link WasmBridge.getString}).
|
|
29
|
+
*/
|
|
30
|
+
deref() {
|
|
31
|
+
return this.mem.getString(this.addr, this.length);
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* If given a JS string as arg (and if **not** a const slice), attempts to
|
|
35
|
+
* overwrite this wrapped string's memory with bytes from given string. If
|
|
36
|
+
* given another {@link WasmStringSlice} as arg, only the slice pointer &
|
|
37
|
+
* new length will be updated (always succeeds).
|
|
38
|
+
*
|
|
39
|
+
* @remarks
|
|
40
|
+
* When copying bytes from a JS string, an error will be thrown if the new
|
|
41
|
+
* string is longer than the _original_ length of the slice (i.e. from when
|
|
42
|
+
* this `WasmStringSlice` wrapper instance was created). Also updates the
|
|
43
|
+
* slice's length field to new string length.
|
|
44
|
+
*
|
|
45
|
+
* Passing a `WasmString` instance as arg is faster than JS string since
|
|
46
|
+
* only the slice definition itself will be updated.
|
|
47
|
+
*
|
|
48
|
+
* @param str
|
|
49
|
+
*/
|
|
50
|
+
set(str) {
|
|
51
|
+
if (typeof str === "string") {
|
|
52
|
+
if (this.isConst)
|
|
53
|
+
unsupported("can't mutate const string");
|
|
54
|
+
this.mem.u32[(this.base + 4) >>> 2] = this.mem.setString(str, this.addr, this.max + 1, true);
|
|
55
|
+
}
|
|
56
|
+
else {
|
|
57
|
+
this.mem.u32[this.base >>> 2] = str.addr;
|
|
58
|
+
this.mem.u32[(this.base + 4) >>> 2] = str.length;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
toJSON() {
|
|
62
|
+
return this.deref();
|
|
63
|
+
}
|
|
64
|
+
toString() {
|
|
65
|
+
return this.deref();
|
|
66
|
+
}
|
|
67
|
+
valueOf() {
|
|
68
|
+
return this.deref();
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Memory mapped string wrapper for C-style UTF-8 encoded and zero-terminated
|
|
73
|
+
* char pointers. The actual JS string can be obtained via
|
|
74
|
+
* {@link WasmStringSlice.deref} and mutated via {@link WasmStringSlice.set}.
|
|
75
|
+
*/
|
|
76
|
+
export class WasmStringPtr {
|
|
77
|
+
constructor(mem, base, isConst = true) {
|
|
78
|
+
this.mem = mem;
|
|
79
|
+
this.base = base;
|
|
80
|
+
this.isConst = isConst;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Returns string start address (deref'd pointer).
|
|
84
|
+
*/
|
|
85
|
+
get addr() {
|
|
86
|
+
return this.mem.u32[this.base >>> 2];
|
|
87
|
+
}
|
|
88
|
+
set addr(addr) {
|
|
89
|
+
this.mem.u32[this.base >>> 2] = addr;
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Returns computed string length (scanning memory for zero sentinel)
|
|
93
|
+
*/
|
|
94
|
+
get length() {
|
|
95
|
+
const addr = this.addr;
|
|
96
|
+
const idx = this.mem.u8.indexOf(0, addr);
|
|
97
|
+
return idx >= 0 ? idx - addr : 0;
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Returns memory as JS string (aka wrapper for
|
|
101
|
+
* {@link WasmBridge.getString}).
|
|
102
|
+
*/
|
|
103
|
+
deref() {
|
|
104
|
+
return this.mem.getString(this.addr, this.length);
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* If given a JS string as arg (and if not a const pointer), attempts to
|
|
108
|
+
* overwrite this wrapped string's memory with bytes from given string. If
|
|
109
|
+
* given another {@link WasmStringPtr}, it merely overrides the pointer to
|
|
110
|
+
* the new one (always succeeds).
|
|
111
|
+
*
|
|
112
|
+
* @remarks
|
|
113
|
+
* Unlike with {@link WasmStringSlice.set} this implementation which
|
|
114
|
+
* performs bounds checking when copying bytes from a JS string, this method
|
|
115
|
+
* only throws an error if the new string is longer than the available
|
|
116
|
+
* memory (from the start address until the end of the WASM memory).
|
|
117
|
+
* **Therefore, this is as (un)safe as a C pointer and should be used with
|
|
118
|
+
* caution!**
|
|
119
|
+
*
|
|
120
|
+
* Passing a `WasmStringPtr` instance as arg is faster than JS string since
|
|
121
|
+
* only the pointer itself will be updated.
|
|
122
|
+
*
|
|
123
|
+
* @param str
|
|
124
|
+
*/
|
|
125
|
+
set(str) {
|
|
126
|
+
const addr = this.addr;
|
|
127
|
+
if (typeof str === "string") {
|
|
128
|
+
if (this.isConst)
|
|
129
|
+
unsupported("can't mutate const string");
|
|
130
|
+
this.mem.setString(str, addr, this.mem.u8.byteLength - addr, true);
|
|
131
|
+
}
|
|
132
|
+
else {
|
|
133
|
+
this.addr = str.addr;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
toJSON() {
|
|
137
|
+
return this.deref();
|
|
138
|
+
}
|
|
139
|
+
toString() {
|
|
140
|
+
return this.deref();
|
|
141
|
+
}
|
|
142
|
+
valueOf() {
|
|
143
|
+
return this.deref();
|
|
144
|
+
}
|
|
145
|
+
}
|