teptris 0.3.11 → 0.3.13
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/README.md +2 -0
- package/dist/teptris.wasm +0 -0
- package/package.json +2 -1
- package/src/index.js +48 -18
package/README.md
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# teptris (JavaScript/TypeScript)
|
|
2
2
|
|
|
3
|
+
[](https://github.com/leptris/teptris-ts/actions/workflows/ci.yml)
|
|
4
|
+
|
|
3
5
|
**Mission: be the best TOML parser and builder ever made — in C, Ruby,
|
|
4
6
|
Rust, and JS — measured, not claimed.** The bar and the family ledger:
|
|
5
7
|
[BEST-EVER.md](https://github.com/leptris/teptris/blob/main/BEST-EVER.md).
|
package/dist/teptris.wasm
CHANGED
|
Binary file
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "teptris",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.13",
|
|
4
4
|
"description": "TOML for JavaScript/TypeScript at libteptris speed (WebAssembly, no fallback) - version tracks the engine ({engine}.{iteration}; npm semver is 3-part)",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "src/index.js",
|
|
@@ -29,6 +29,7 @@
|
|
|
29
29
|
"types": "src/index.d.ts",
|
|
30
30
|
"devDependencies": {
|
|
31
31
|
"@iarna/toml": "^2.2.5",
|
|
32
|
+
"@ltd/j-toml": "^1.38.0",
|
|
32
33
|
"smol-toml": "^1.9.1"
|
|
33
34
|
}
|
|
34
35
|
}
|
package/src/index.js
CHANGED
|
@@ -28,7 +28,9 @@ function parseDateTime(str) {
|
|
|
28
28
|
return {
|
|
29
29
|
kind, year: +m[1], month: +m[2], day: +m[3], hour: +m[4],
|
|
30
30
|
minute: +m[5], second: +m[6],
|
|
31
|
-
|
|
31
|
+
// integer string padding, not FP: 0.507029 * 1e9 floors to
|
|
32
|
+
// 507028999 (off by one)
|
|
33
|
+
nanosecond: m[7] ? +((m[7] + "000000000").slice(0, 9)) : 0,
|
|
32
34
|
offset_seconds: offset,
|
|
33
35
|
};
|
|
34
36
|
}
|
|
@@ -42,7 +44,7 @@ function parseDateTime(str) {
|
|
|
42
44
|
if (m) {
|
|
43
45
|
return { kind: KIND_TIME, year: 0, month: 0, day: 0, hour: +m[1],
|
|
44
46
|
minute: +m[2], second: +m[3],
|
|
45
|
-
nanosecond: m[4] ?
|
|
47
|
+
nanosecond: m[4] ? +((m[4] + "000000000").slice(0, 9)) : 0,
|
|
46
48
|
offset_seconds: 0 };
|
|
47
49
|
}
|
|
48
50
|
return null;
|
|
@@ -53,16 +55,15 @@ const RFC3339 =
|
|
|
53
55
|
|
|
54
56
|
// cheap charset pre-check before the RFC 3339 regex: datetimes start
|
|
55
57
|
// with a digit and only ever contain digits, date/time punctuation
|
|
56
|
-
// and TZ marks - rejects nearly all plain strings without the regex
|
|
57
|
-
|
|
58
|
+
// and TZ marks - rejects nearly all plain strings without the regex.
|
|
59
|
+
// One whole-string regex pass (the per-char loop allocated a
|
|
60
|
+
// single-char string per character).
|
|
61
|
+
const DATETIME_CHARS = /^[0-9Tt: .+Zz-]*$/;
|
|
58
62
|
const utf8 = new TextDecoder("utf-8");
|
|
63
|
+
const utf8enc = new TextEncoder();
|
|
59
64
|
function maybeRfc3339(v) {
|
|
60
65
|
const c0 = v.charCodeAt(0);
|
|
61
|
-
|
|
62
|
-
for (let i = 1; i < v.length; i++) {
|
|
63
|
-
if (!DATETIME_CHARS.test(v[i])) return false;
|
|
64
|
-
}
|
|
65
|
-
return true;
|
|
66
|
+
return c0 >= 48 && c0 <= 57 && DATETIME_CHARS.test(v);
|
|
66
67
|
}
|
|
67
68
|
|
|
68
69
|
function buildValue(mod, b, key, v, errs) {
|
|
@@ -177,7 +178,9 @@ export function initApi(mod) {
|
|
|
177
178
|
}
|
|
178
179
|
|
|
179
180
|
function readOut(ptr) {
|
|
180
|
-
|
|
181
|
+
// explicit length: the emit buffer is not NUL-terminated for us,
|
|
182
|
+
// and a full strlen scan over the output is measurable
|
|
183
|
+
const out = UTF8ToString(ptr, mod._teptris_wasm_toml_len());
|
|
181
184
|
mod._teptris_wasm_free(ptr);
|
|
182
185
|
return out;
|
|
183
186
|
}
|
|
@@ -189,7 +192,7 @@ export function initApi(mod) {
|
|
|
189
192
|
if (obj === null || typeof obj !== "object" || Array.isArray(obj)) {
|
|
190
193
|
throw new TypeError("dump expects a table object (TOML roots are tables)");
|
|
191
194
|
}
|
|
192
|
-
|
|
195
|
+
|
|
193
196
|
let buf = new Uint8Array(1 << 16);
|
|
194
197
|
let n = 0;
|
|
195
198
|
let dv = new DataView(buf.buffer);
|
|
@@ -226,9 +229,23 @@ export function initApi(mod) {
|
|
|
226
229
|
const wkey = (k) => {
|
|
227
230
|
ensure(2 + k.length * 3);
|
|
228
231
|
buf[n++] = 1;
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
+
// ASCII fast path: keys are tiny, so TextEncoder.encodeInto's
|
|
233
|
+
// per-call view allocation costs more than the copy itself;
|
|
234
|
+
// non-ASCII falls back to encodeInto (overwrites from offset 1)
|
|
235
|
+
let ascii = true;
|
|
236
|
+
for (let i = 0; i < k.length; i++) {
|
|
237
|
+
const c = k.charCodeAt(i);
|
|
238
|
+
if (c > 127) { ascii = false; break; }
|
|
239
|
+
buf[n + 1 + i] = c;
|
|
240
|
+
}
|
|
241
|
+
if (ascii) {
|
|
242
|
+
buf[n] = k.length;
|
|
243
|
+
n += 1 + k.length;
|
|
244
|
+
} else {
|
|
245
|
+
const { written } = utf8enc.encodeInto(k, buf.subarray(n + 1));
|
|
246
|
+
buf[n] = written;
|
|
247
|
+
n += 1 + written;
|
|
248
|
+
}
|
|
232
249
|
};
|
|
233
250
|
const scalar = (k, v) => {
|
|
234
251
|
if (k === null) { ensure(2); buf[n++] = 1; buf[n++] = 0; }
|
|
@@ -243,7 +260,9 @@ export function initApi(mod) {
|
|
|
243
260
|
if (typeof v === "string") {
|
|
244
261
|
if (maybeRfc3339(v) && RFC3339.test(v)) {
|
|
245
262
|
const dt = parseDateTime(v);
|
|
246
|
-
|
|
263
|
+
// the key prefix is already written (top of scalar()); the
|
|
264
|
+
// datetime record is value-only - re-sending the key here
|
|
265
|
+
// crashed bare array elements (k === null)
|
|
247
266
|
ensure(27);
|
|
248
267
|
buf[n++] = 7;
|
|
249
268
|
buf[n++] = dt.kind;
|
|
@@ -256,9 +275,20 @@ export function initApi(mod) {
|
|
|
256
275
|
}
|
|
257
276
|
ensure(5 + v.length * 3);
|
|
258
277
|
buf[n++] = 2;
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
278
|
+
let ascii = true;
|
|
279
|
+
for (let i = 0; i < v.length; i++) {
|
|
280
|
+
const c = v.charCodeAt(i);
|
|
281
|
+
if (c > 127) { ascii = false; break; }
|
|
282
|
+
buf[n + 4 + i] = c;
|
|
283
|
+
}
|
|
284
|
+
if (ascii) {
|
|
285
|
+
dv.setUint32(n, v.length, true);
|
|
286
|
+
n += 4 + v.length;
|
|
287
|
+
} else {
|
|
288
|
+
const { written } = utf8enc.encodeInto(v, buf.subarray(n + 4));
|
|
289
|
+
dv.setUint32(n, written, true);
|
|
290
|
+
n += 4 + written;
|
|
291
|
+
}
|
|
262
292
|
return;
|
|
263
293
|
}
|
|
264
294
|
throw new Error("null/undefined cannot round-trip through TOML");
|