@thi.ng/wasm-api 1.4.36 → 1.4.38

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/string.js CHANGED
@@ -1,224 +1,207 @@
1
1
  import { isNumber } from "@thi.ng/checks/is-number";
2
2
  import { unsupported } from "@thi.ng/errors/unsupported";
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 possibly mutated via
7
- * {@link WasmStringSlice.set}.
8
- *
9
- * @remarks
10
- * Currently only supports wasm32 target, need alt. solution for 64bit (possibly
11
- * diff implementation) using bigint addresses (TODO)
12
- */
13
- export class WasmStringSlice {
14
- mem;
15
- base;
16
- isConst;
17
- terminated;
18
- maxLen;
19
- constructor(mem, base, isConst = true, terminated = true) {
20
- this.mem = mem;
21
- this.base = base;
22
- this.isConst = isConst;
23
- this.terminated = terminated;
24
- this.maxLen = this.length;
25
- }
26
- /**
27
- * Returns string start address (deref'd pointer).
28
- */
29
- get addr() {
30
- this.mem.ensureMemory();
31
- return this.mem.u32[this.base >>> 2];
32
- }
33
- /**
34
- * Returns string length (read from memory)
35
- */
36
- get length() {
37
- this.mem.ensureMemory();
38
- return this.mem.u32[(this.base + 4) >>> 2];
39
- }
40
- /**
41
- * Returns memory as JS string (aka wrapper for
42
- * {@link WasmBridge.getString}).
43
- */
44
- deref() {
45
- return this.mem.getString(this.addr, this.length);
46
- }
47
- /**
48
- * If given a JS string as arg (and if **not** a const slice), attempts to
49
- * overwrite this wrapped string's memory with bytes from given string. If
50
- * given another {@link WasmStringSlice} as arg, only the slice pointer &
51
- * new length will be updated (always succeeds).
52
- *
53
- * @remarks
54
- * When copying bytes from a JS string, an error will be thrown if the new
55
- * string is longer than the _original_ length of the slice (i.e. from when
56
- * this `WasmStringSlice` wrapper instance was created). Also updates the
57
- * slice's length field to new string length.
58
- *
59
- * Passing a `WasmString` instance as arg is faster than JS string since
60
- * only the slice definition itself will be updated.
61
- *
62
- * @param str
63
- */
64
- set(str) {
65
- this.mem.ensureMemory();
66
- if (typeof str === "string") {
67
- if (this.isConst)
68
- unsupported("can't mutate const string");
69
- this.mem.u32[(this.base + 4) >>> 2] = this.mem.setString(str, this.addr, this.maxLen + ~~this.terminated, this.terminated);
70
- }
71
- else {
72
- this.mem.u32[this.base >>> 2] = str.addr;
73
- this.mem.u32[(this.base + 4) >>> 2] = str.length;
74
- }
75
- }
76
- setSlice(...args) {
77
- this.mem.ensureMemory();
78
- const [slice, terminated] = ((isNumber(args[0])
79
- ? [[args[0], args[1]], args[2]]
80
- : [args[0], args[1]]));
81
- this.mem.u32[this.base >>> 2] = slice[0];
82
- this.mem.u32[(this.base + 4) >>> 2] = slice[1];
83
- this.terminated = terminated;
84
- return slice;
85
- }
86
- /**
87
- * Encodes given string to UTF-8 (by default zero terminated), allocates
88
- * memory for it, updates this slice and returns a {@link MemorySlice} of
89
- * the allocated region.
90
- *
91
- * @remarks
92
- * If `terminated` is true, the stored slice length will **NOT** include the
93
- * sentinel! E.g. the slice length of zero-terminated string `"abc"` is 3,
94
- * but the number of allocated bytes is 4. This is done for compatibility
95
- * with Zig's sentinel-terminated slice handling (e.g. `[:0]u8` slices).
96
- *
97
- * Regardless of `terminated` setting, the returned `MemorySlice` **always**
98
- * covers the entire allocated region!
99
- *
100
- * @param str
101
- * @param terminate
102
- */
103
- setAlloc(str, terminate = true) {
104
- const slice = __alloc(this.mem, str, terminate);
105
- this.setSlice(terminate ? [slice[0], slice[1] - 1] : slice, terminate);
106
- return slice;
107
- }
108
- toJSON() {
109
- return this.deref();
110
- }
111
- toString() {
112
- return this.deref();
113
- }
114
- valueOf() {
115
- return this.deref();
116
- }
3
+ class WasmStringSlice {
4
+ constructor(mem, base, isConst = true, terminated = true) {
5
+ this.mem = mem;
6
+ this.base = base;
7
+ this.isConst = isConst;
8
+ this.terminated = terminated;
9
+ this.maxLen = this.length;
10
+ }
11
+ maxLen;
12
+ /**
13
+ * Returns string start address (deref'd pointer).
14
+ */
15
+ get addr() {
16
+ this.mem.ensureMemory();
17
+ return this.mem.u32[this.base >>> 2];
18
+ }
19
+ /**
20
+ * Returns string length (read from memory)
21
+ */
22
+ get length() {
23
+ this.mem.ensureMemory();
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
+ this.mem.ensureMemory();
52
+ if (typeof str === "string") {
53
+ if (this.isConst)
54
+ unsupported("can't mutate const string");
55
+ this.mem.u32[this.base + 4 >>> 2] = this.mem.setString(
56
+ str,
57
+ this.addr,
58
+ this.maxLen + ~~this.terminated,
59
+ this.terminated
60
+ );
61
+ } else {
62
+ this.mem.u32[this.base >>> 2] = str.addr;
63
+ this.mem.u32[this.base + 4 >>> 2] = str.length;
64
+ }
65
+ }
66
+ setSlice(...args) {
67
+ this.mem.ensureMemory();
68
+ const [slice, terminated] = isNumber(args[0]) ? [[args[0], args[1]], args[2]] : [args[0], args[1]];
69
+ this.mem.u32[this.base >>> 2] = slice[0];
70
+ this.mem.u32[this.base + 4 >>> 2] = slice[1];
71
+ this.terminated = terminated;
72
+ return slice;
73
+ }
74
+ /**
75
+ * Encodes given string to UTF-8 (by default zero terminated), allocates
76
+ * memory for it, updates this slice and returns a {@link MemorySlice} of
77
+ * the allocated region.
78
+ *
79
+ * @remarks
80
+ * If `terminated` is true, the stored slice length will **NOT** include the
81
+ * sentinel! E.g. the slice length of zero-terminated string `"abc"` is 3,
82
+ * but the number of allocated bytes is 4. This is done for compatibility
83
+ * with Zig's sentinel-terminated slice handling (e.g. `[:0]u8` slices).
84
+ *
85
+ * Regardless of `terminated` setting, the returned `MemorySlice` **always**
86
+ * covers the entire allocated region!
87
+ *
88
+ * @param str
89
+ * @param terminate
90
+ */
91
+ setAlloc(str, terminate = true) {
92
+ const slice = __alloc(this.mem, str, terminate);
93
+ this.setSlice(terminate ? [slice[0], slice[1] - 1] : slice, terminate);
94
+ return slice;
95
+ }
96
+ toJSON() {
97
+ return this.deref();
98
+ }
99
+ toString() {
100
+ return this.deref();
101
+ }
102
+ valueOf() {
103
+ return this.deref();
104
+ }
117
105
  }
118
- /**
119
- * Memory mapped string wrapper for C-style UTF-8 encoded and **always**
120
- * zero-terminated char pointers. The actual JS string can be obtained via
121
- * {@link WasmStringSlice.deref} and mutated via {@link WasmStringSlice.set}.
122
- */
123
- export class WasmStringPtr {
124
- mem;
125
- base;
126
- isConst;
127
- constructor(mem, base, isConst = true) {
128
- this.mem = mem;
129
- this.base = base;
130
- this.isConst = isConst;
131
- }
132
- /**
133
- * Returns string start address (deref'd pointer).
134
- */
135
- get addr() {
136
- this.mem.ensureMemory();
137
- return this.mem.u32[this.base >>> 2];
138
- }
139
- set addr(addr) {
140
- this.mem.ensureMemory();
141
- this.mem.u32[this.base >>> 2] = addr;
142
- }
143
- /**
144
- * Returns computed string length (scanning memory for zero sentinel)
145
- */
146
- get length() {
147
- this.mem.ensureMemory();
148
- const idx = this.mem.u8.indexOf(0, this.addr);
149
- return idx >= 0 ? idx - this.addr : 0;
150
- }
151
- /**
152
- * Returns memory as JS string (aka wrapper for
153
- * {@link WasmBridge.getString}).
154
- */
155
- deref() {
156
- return this.mem.getString(this.addr, this.length);
157
- }
158
- /**
159
- * If given a JS string as arg (and if this `WasmStringPtr` instance itself
160
- * is not a `const` pointer), attempts to overwrite this wrapped string's
161
- * memory with bytes from given string. If given another
162
- * {@link WasmStringPtr}, it merely overrides the pointer to the new one
163
- * (always succeeds).
164
- *
165
- * @remarks
166
- * Unlike with {@link WasmStringSlice.set} this implementation which
167
- * performs bounds checking when copying bytes from a JS string, this method
168
- * only throws an error if the new string is longer than the available
169
- * memory (from the start address until the end of the WASM memory).
170
- * **Therefore, this is as (un)safe as a C pointer and should be used with
171
- * caution!**
172
- *
173
- * Passing a `WasmStringPtr` instance as arg is faster than JS string since
174
- * only the pointer itself will be updated.
175
- *
176
- * @param str
177
- */
178
- set(str) {
179
- const addr = this.addr;
180
- if (typeof str === "string") {
181
- if (this.isConst)
182
- unsupported("can't mutate const string");
183
- this.mem.ensureMemory();
184
- this.mem.setString(str, addr, this.mem.u8.byteLength - addr, true);
185
- }
186
- else {
187
- this.addr = str.addr;
188
- this.isConst = str.isConst;
189
- }
190
- }
191
- /**
192
- * Encodes given string to UTF-8 (by default zero terminated), allocates
193
- * memory for it, updates this pointer to new address and returns allocated
194
- * {@link MemorySlice}.
195
- *
196
- * @remarks
197
- * See {@link WasmStringSlice.setAlloc} for important details.
198
- *
199
- * @param str
200
- */
201
- setAlloc(str) {
202
- const slice = __alloc(this.mem, str, true);
203
- this.mem.u32[this.base >>> 2] = slice[0];
204
- return slice;
205
- }
206
- toJSON() {
207
- return this.deref();
208
- }
209
- toString() {
210
- return this.deref();
211
- }
212
- valueOf() {
213
- return this.deref();
214
- }
106
+ class WasmStringPtr {
107
+ constructor(mem, base, isConst = true) {
108
+ this.mem = mem;
109
+ this.base = base;
110
+ this.isConst = isConst;
111
+ }
112
+ /**
113
+ * Returns string start address (deref'd pointer).
114
+ */
115
+ get addr() {
116
+ this.mem.ensureMemory();
117
+ return this.mem.u32[this.base >>> 2];
118
+ }
119
+ set addr(addr) {
120
+ this.mem.ensureMemory();
121
+ this.mem.u32[this.base >>> 2] = addr;
122
+ }
123
+ /**
124
+ * Returns computed string length (scanning memory for zero sentinel)
125
+ */
126
+ get length() {
127
+ this.mem.ensureMemory();
128
+ const idx = this.mem.u8.indexOf(0, this.addr);
129
+ return idx >= 0 ? idx - this.addr : 0;
130
+ }
131
+ /**
132
+ * Returns memory as JS string (aka wrapper for
133
+ * {@link WasmBridge.getString}).
134
+ */
135
+ deref() {
136
+ return this.mem.getString(this.addr, this.length);
137
+ }
138
+ /**
139
+ * If given a JS string as arg (and if this `WasmStringPtr` instance itself
140
+ * is not a `const` pointer), attempts to overwrite this wrapped string's
141
+ * memory with bytes from given string. If given another
142
+ * {@link WasmStringPtr}, it merely overrides the pointer to the new one
143
+ * (always succeeds).
144
+ *
145
+ * @remarks
146
+ * Unlike with {@link WasmStringSlice.set} this implementation which
147
+ * performs bounds checking when copying bytes from a JS string, this method
148
+ * only throws an error if the new string is longer than the available
149
+ * memory (from the start address until the end of the WASM memory).
150
+ * **Therefore, this is as (un)safe as a C pointer and should be used with
151
+ * caution!**
152
+ *
153
+ * Passing a `WasmStringPtr` instance as arg is faster than JS string since
154
+ * only the pointer itself will be updated.
155
+ *
156
+ * @param str
157
+ */
158
+ set(str) {
159
+ const addr = this.addr;
160
+ if (typeof str === "string") {
161
+ if (this.isConst)
162
+ unsupported("can't mutate const string");
163
+ this.mem.ensureMemory();
164
+ this.mem.setString(str, addr, this.mem.u8.byteLength - addr, true);
165
+ } else {
166
+ this.addr = str.addr;
167
+ this.isConst = str.isConst;
168
+ }
169
+ }
170
+ /**
171
+ * Encodes given string to UTF-8 (by default zero terminated), allocates
172
+ * memory for it, updates this pointer to new address and returns allocated
173
+ * {@link MemorySlice}.
174
+ *
175
+ * @remarks
176
+ * See {@link WasmStringSlice.setAlloc} for important details.
177
+ *
178
+ * @param str
179
+ */
180
+ setAlloc(str) {
181
+ const slice = __alloc(this.mem, str, true);
182
+ this.mem.u32[this.base >>> 2] = slice[0];
183
+ return slice;
184
+ }
185
+ toJSON() {
186
+ return this.deref();
187
+ }
188
+ toString() {
189
+ return this.deref();
190
+ }
191
+ valueOf() {
192
+ return this.deref();
193
+ }
215
194
  }
216
195
  const __alloc = (mem, str, terminate) => {
217
- const buf = new TextEncoder().encode(str);
218
- const slice = mem.allocate(buf.length + ~~terminate);
219
- if (slice[1] > 0) {
220
- mem.u8.set(buf, slice[0]);
221
- terminate && (mem.u8[slice[0] + buf.length] = 0);
222
- }
223
- return slice;
196
+ const buf = new TextEncoder().encode(str);
197
+ const slice = mem.allocate(buf.length + ~~terminate);
198
+ if (slice[1] > 0) {
199
+ mem.u8.set(buf, slice[0]);
200
+ terminate && (mem.u8[slice[0] + buf.length] = 0);
201
+ }
202
+ return slice;
203
+ };
204
+ export {
205
+ WasmStringPtr,
206
+ WasmStringSlice
224
207
  };