koda-format 1.0.2 → 1.0.4
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 +92 -61
- package/SPEC.md +1 -1
- package/dist/decode-async.d.ts +26 -0
- package/dist/decode-async.d.ts.map +1 -0
- package/dist/decode-async.js +121 -0
- package/dist/decode-async.js.map +1 -0
- package/dist/decoderV2.d.ts +11 -0
- package/dist/decoderV2.d.ts.map +1 -0
- package/dist/decoderV2.js +142 -0
- package/dist/decoderV2.js.map +1 -0
- package/dist/encoderV2.d.ts +10 -0
- package/dist/encoderV2.d.ts.map +1 -0
- package/dist/encoderV2.js +159 -0
- package/dist/encoderV2.js.map +1 -0
- package/dist/index.d.ts +10 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +11 -2
- package/dist/index.js.map +1 -1
- package/dist/varint.d.ts +17 -0
- package/dist/varint.d.ts.map +1 -0
- package/dist/varint.js +48 -0
- package/dist/varint.js.map +1 -0
- package/dist/view.d.ts +46 -0
- package/dist/view.d.ts.map +1 -0
- package/dist/view.js +162 -0
- package/dist/view.js.map +1 -0
- package/dist/worker/decoder-worker.d.ts +20 -0
- package/dist/worker/decoder-worker.d.ts.map +1 -0
- package/dist/worker/decoder-worker.js +42 -0
- package/dist/worker/decoder-worker.js.map +1 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,104 +1,135 @@
|
|
|
1
|
-
#
|
|
1
|
+
# koda-format
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Compact Object Data Architecture: a structured data format with a human-readable text syntax and a canonical binary encoding. Optimized for compact storage and scalable backend processing.
|
|
4
4
|
|
|
5
|
-
[](https://www.npmjs.com/package/koda-format)
|
|
6
|
-
**License:** MIT
|
|
5
|
+
[](https://www.npmjs.com/package/koda-format)
|
|
7
6
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
## Quick start
|
|
7
|
+
## Installation
|
|
11
8
|
|
|
12
9
|
```bash
|
|
13
10
|
npm install koda-format
|
|
14
11
|
```
|
|
15
12
|
|
|
13
|
+
Requires Node.js 18 or later.
|
|
14
|
+
|
|
15
|
+
## Quick example
|
|
16
|
+
|
|
16
17
|
```ts
|
|
17
18
|
import { parse, stringify, encode, decode } from 'koda-format';
|
|
18
19
|
|
|
19
|
-
// Text
|
|
20
|
+
// Text format (.koda): key-value, optional commas, comments
|
|
20
21
|
const value = parse(`
|
|
21
22
|
name: "my-app"
|
|
22
23
|
version: 1
|
|
23
24
|
enabled: true
|
|
24
25
|
`);
|
|
25
|
-
const back = stringify(value);
|
|
26
26
|
|
|
27
|
-
// Binary (canonical,
|
|
27
|
+
// Binary format (.kod): canonical, deterministic
|
|
28
28
|
const bytes = encode(value);
|
|
29
|
-
const decoded = decode(bytes);
|
|
29
|
+
const decoded = await decode(bytes);
|
|
30
30
|
```
|
|
31
31
|
|
|
32
|
-
|
|
32
|
+
## When to use KODA
|
|
33
33
|
|
|
34
|
-
|
|
34
|
+
KODA is suited to:
|
|
35
35
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
| **Optional C++ addon** | Faster encode/decode when built; same API, pure JS fallback. |
|
|
36
|
+
- **Large payloads** — configuration, event batches, log datasets
|
|
37
|
+
- **Repetitive structures** — arrays of objects with repeated keys
|
|
38
|
+
- **Storage-heavy workloads** — databases, caches, bulk export/import
|
|
39
|
+
- **IO-bound systems** — smaller payloads reduce disk and network transfer
|
|
40
|
+
- **Backend services** — where non-blocking decode and parallel processing matter
|
|
42
41
|
|
|
43
|
-
|
|
42
|
+
KODA is not a drop-in replacement for JSON in all contexts. It is optimized for compact binary storage and scalable backend processing. Use JSON where interoperability, tooling, or simple string exchange are the main requirements.
|
|
44
43
|
|
|
45
|
-
|
|
44
|
+
## Non-blocking decode and multithreading
|
|
46
45
|
|
|
47
|
-
|
|
46
|
+
**Why it matters**
|
|
48
47
|
|
|
49
|
-
|
|
50
|
-
|----------|-------------|
|
|
51
|
-
| `parse(text, options?)` | Parse KODA text → value. Options: `maxDepth`, `maxInputLength`. |
|
|
52
|
-
| `stringify(value, options?)` | Value → KODA text. Options: `indent`, `newline`. |
|
|
53
|
-
| `encode(value, options?)` | Value → canonical binary `Uint8Array`. Options: `maxDepth`. |
|
|
54
|
-
| `decode(buffer, options?)` | Binary → value. Options: `maxDepth`, `maxDictionarySize`, `maxStringLength`. |
|
|
55
|
-
| `loadFile(path, options?)` | Read file (UTF-8) and parse. |
|
|
56
|
-
| `saveFile(path, value, options?)` | Stringify and write file. |
|
|
57
|
-
| `toJSON(value)` | Same as `JSON.stringify(value)`. |
|
|
58
|
-
| `fromJSON(json)` | Same as `JSON.parse(json)`. |
|
|
59
|
-
| `parseWithLexer(text, options?)` | Lexer-based parse (better error positions). |
|
|
60
|
-
| `isNativeAvailable()` | `true` if the C++ addon is loaded. |
|
|
48
|
+
`JSON.parse` is synchronous: it blocks the Node.js event loop until the parse finishes. For large payloads or many concurrent requests, that can stall I/O, timers, and other work. KODA’s default binary decode is **non-blocking** and can run in **worker threads**, so the main thread stays responsive.
|
|
61
49
|
|
|
62
|
-
|
|
50
|
+
**How it works**
|
|
63
51
|
|
|
64
|
-
|
|
52
|
+
- **`decode(buffer)`** — Returns a `Promise<KodaValue>`. Each call runs decode in a separate worker thread. The main thread only schedules the job and receives the result; it does not perform the parse. Use this for normal async usage.
|
|
53
|
+
- **`decodeSync(buffer)`** — Synchronous decode on the main thread. Use only when you cannot use async (e.g. some legacy code paths) or for very small payloads.
|
|
54
|
+
- **`createDecoderPool({ poolSize })`** — Creates a fixed pool of worker threads. `pool.decode(buffer)` dispatches to a worker from the pool and returns a promise. Reusing workers avoids per-call worker startup cost and allows **parallel decoding across multiple CPU cores**. Suited to high-throughput backends (e.g. many decode requests in parallel).
|
|
65
55
|
|
|
66
|
-
|
|
56
|
+
**Summary**
|
|
67
57
|
|
|
68
|
-
-
|
|
69
|
-
-
|
|
70
|
-
-
|
|
71
|
-
- **Data:** Root value with type tags: null, false, true, int64, float64, string, array, object. Objects use key indices into the dictionary. Same value → same bytes.
|
|
58
|
+
- Non-blocking: decode work runs off the main thread; the event loop is not blocked.
|
|
59
|
+
- Multithreading: decoding runs in Node.js worker threads; a decoder pool uses multiple workers and cores.
|
|
60
|
+
- Suited to backends and batch jobs where throughput and main-thread latency matter.
|
|
72
61
|
|
|
73
|
-
|
|
62
|
+
## Benchmark results
|
|
74
63
|
|
|
75
|
-
|
|
64
|
+
Size comparison for workloads that match KODA’s design: large documents, repeated keys, and tabular data.
|
|
76
65
|
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
66
|
+
| Scenario | JSON | KODA binary | Reduction |
|
|
67
|
+
|----------|------|-------------|-----------|
|
|
68
|
+
| Large (500 items) | 54.4 KB | 26.2 KB | 52% |
|
|
69
|
+
| 1000 rows × 100 items | 10.2 MB | 4.65 MB | 54% |
|
|
70
|
+
| 1 document, 10k long keys | 1.55 MB | 488 KB | 68% |
|
|
71
|
+
|
|
72
|
+
The binary format stores each key once in a dictionary; documents with many repeated keys see the largest size reduction.
|
|
73
|
+
|
|
74
|
+
## Performance characteristics
|
|
75
|
+
|
|
76
|
+
**Event loop and concurrency**
|
|
77
|
+
|
|
78
|
+
`JSON.parse` is synchronous and blocks the Node.js event loop for the duration of the parse. KODA’s primary decode API is asynchronous: decoding runs in worker threads, so the main thread remains responsive. This reduces latency impact on the rest of the application.
|
|
79
|
+
|
|
80
|
+
**Parallel processing**
|
|
81
|
+
|
|
82
|
+
Decoding can be distributed across multiple worker threads. A decoder pool (`createDecoderPool`) allows many decode operations to run in parallel and use multiple CPU cores. This suits high-throughput backends and batch processing where many payloads are decoded concurrently.
|
|
83
|
+
|
|
84
|
+
**Summary**
|
|
85
|
+
|
|
86
|
+
- Non-blocking decode: work runs off the main thread.
|
|
87
|
+
- Parallel scalability: multiple workers and cores can be used.
|
|
88
|
+
- No claim is made about raw single-thread parse speed versus JSON; the advantages are non-blocking behavior and parallel scalability.
|
|
82
89
|
|
|
83
|
-
|
|
90
|
+
## API overview
|
|
84
91
|
|
|
85
|
-
|
|
92
|
+
**Text**
|
|
86
93
|
|
|
87
|
-
|
|
94
|
+
| Method | Description |
|
|
95
|
+
|--------|-------------|
|
|
96
|
+
| `parse(text, options?)` | Parse KODA text to a value. Options: `maxDepth`, `maxInputLength`. |
|
|
97
|
+
| `stringify(value, options?)` | Serialize value to KODA text. Options: `indent`, `newline`. |
|
|
98
|
+
|
|
99
|
+
**Binary**
|
|
100
|
+
|
|
101
|
+
| Method | Description |
|
|
102
|
+
|--------|-------------|
|
|
103
|
+
| `encode(value, options?)` | Encode value to canonical binary. Returns `Uint8Array`. Options: `maxDepth`. |
|
|
104
|
+
| `decode(buffer, options?)` | Decode binary to value. Returns `Promise<KodaValue>`. Runs in a worker thread. |
|
|
105
|
+
| `decodeSync(buffer, options?)` | Synchronous decode. Blocks the event loop. |
|
|
106
|
+
| `createDecoderPool(options?)` | Create a pool of decoder workers. Returns `{ decode, destroy }`. Options: `poolSize`. |
|
|
107
|
+
|
|
108
|
+
**Decode options:** `maxDepth`, `maxDictionarySize`, `maxStringLength`.
|
|
109
|
+
|
|
110
|
+
**Utilities**
|
|
111
|
+
|
|
112
|
+
| Method | Description |
|
|
113
|
+
|--------|-------------|
|
|
114
|
+
| `loadFile(path, options?)` | Read and parse a `.koda` file. |
|
|
115
|
+
| `saveFile(path, value, options?)` | Serialize and write a `.koda` file. |
|
|
116
|
+
| `isNativeAvailable()` | Whether the optional C++ addon is loaded. |
|
|
117
|
+
|
|
118
|
+
**Errors:** `KodaParseError`, `KodaEncodeError`, `KodaDecodeError` (with `.position` or `.byteOffset` where applicable).
|
|
119
|
+
|
|
120
|
+
Full specification (grammar, binary layout, canonicalization): [SPEC.md](./SPEC.md).
|
|
121
|
+
|
|
122
|
+
## Building the native addon
|
|
123
|
+
|
|
124
|
+
The package works with pure JavaScript. An optional C++ addon improves encode/decode performance when built:
|
|
88
125
|
|
|
89
126
|
```bash
|
|
127
|
+
npm run build
|
|
90
128
|
npm run build:addon
|
|
91
|
-
# or
|
|
92
|
-
npm run build:all
|
|
93
129
|
```
|
|
94
130
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
## Repo
|
|
98
|
-
|
|
99
|
-
- **[SPEC.md](./SPEC.md)** — Grammar, data model, binary layout, canonicalization, security.
|
|
100
|
-
- **Source:** `src/` (TypeScript). **Native:** `native/` (C++ N-API). **Tests:** `test/`. **Examples:** `examples/*.koda`.
|
|
131
|
+
Requires Node.js build tools and a C++ compiler. The addon is used automatically when present.
|
|
101
132
|
|
|
102
|
-
|
|
133
|
+
## License
|
|
103
134
|
|
|
104
|
-
|
|
135
|
+
MIT
|
package/SPEC.md
CHANGED
|
@@ -18,7 +18,7 @@ KODA (Compact Object Data Architecture) is a structured data format designed for
|
|
|
18
18
|
|
|
19
19
|
KODA addresses limitations of JSON (verbosity, no comments, non-deterministic key order), YAML (complexity, security issues), and binary formats like MessagePack (non-canonical, key repetition).
|
|
20
20
|
|
|
21
|
-
**Positioning:** KODA is a **compact binary data format** first. It is optimized for **smaller payloads**, **efficient storage**, **reduced IO**, and **fast binary encode/decode** — not for beating JSON on raw text parsing speed. In real systems, KODA wins on size, IO efficiency, storage, and scalability (see
|
|
21
|
+
**Positioning:** KODA is a **compact binary data format** first. It is optimized for **smaller payloads**, **efficient storage**, **reduced IO**, and **fast binary encode/decode** — not for beating JSON on raw text parsing speed. In real systems, KODA wins on size, IO efficiency, storage, and scalability (see [README.md](./README.md)).
|
|
22
22
|
|
|
23
23
|
---
|
|
24
24
|
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Non-blocking decode: runs in a worker thread. Uses transferable buffer when possible.
|
|
3
|
+
*/
|
|
4
|
+
import type { KodaValue } from './ast.js';
|
|
5
|
+
import type { DecodeOptions } from './decoder.js';
|
|
6
|
+
export interface DecoderPoolOptions {
|
|
7
|
+
/** Number of worker threads (default 1). */
|
|
8
|
+
poolSize?: number;
|
|
9
|
+
}
|
|
10
|
+
export interface DecoderPool {
|
|
11
|
+
/** Decode buffer in a worker; does not block the event loop. */
|
|
12
|
+
decode(buffer: Uint8Array, options?: DecodeOptions): Promise<KodaValue>;
|
|
13
|
+
/** Stop all workers. */
|
|
14
|
+
destroy(): void;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Decode binary in a worker thread. Main thread stays responsive.
|
|
18
|
+
* Uses transferable ArrayBuffer when possible to avoid copy.
|
|
19
|
+
*/
|
|
20
|
+
export declare function decodeAsync(buffer: Uint8Array, options?: DecodeOptions): Promise<KodaValue>;
|
|
21
|
+
/**
|
|
22
|
+
* Create a pool of decoder workers for high throughput. Decode jobs are
|
|
23
|
+
* distributed round-robin across workers.
|
|
24
|
+
*/
|
|
25
|
+
export declare function createDecoderPool(options?: DecoderPoolOptions): DecoderPool;
|
|
26
|
+
//# sourceMappingURL=decode-async.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"decode-async.d.ts","sourceRoot":"","sources":["../src/decode-async.ts"],"names":[],"mappings":"AAAA;;GAEG;AAOH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAC1C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAgBlD,MAAM,WAAW,kBAAkB;IACjC,4CAA4C;IAC5C,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,WAAW;IAC1B,gEAAgE;IAChE,MAAM,CAAC,MAAM,EAAE,UAAU,EAAE,OAAO,CAAC,EAAE,aAAa,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC;IACxE,wBAAwB;IACxB,OAAO,IAAI,IAAI,CAAC;CACjB;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,MAAM,EAAE,UAAU,EAAE,OAAO,CAAC,EAAE,aAAa,GAAG,OAAO,CAAC,SAAS,CAAC,CAsC3F;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,GAAE,kBAAuB,GAAG,WAAW,CAiD/E"}
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Non-blocking decode: runs in a worker thread. Uses transferable buffer when possible.
|
|
3
|
+
*/
|
|
4
|
+
import { existsSync } from 'node:fs';
|
|
5
|
+
import { dirname, join } from 'node:path';
|
|
6
|
+
import { pathToFileURL } from 'node:url';
|
|
7
|
+
import { fileURLToPath } from 'node:url';
|
|
8
|
+
import { Worker } from 'node:worker_threads';
|
|
9
|
+
import { KodaDecodeError } from './errors.js';
|
|
10
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
11
|
+
const __dirname = dirname(__filename);
|
|
12
|
+
function getWorkerURL() {
|
|
13
|
+
const fromModule = join(__dirname, 'worker', 'decoder-worker.js');
|
|
14
|
+
if (existsSync(fromModule))
|
|
15
|
+
return pathToFileURL(fromModule);
|
|
16
|
+
const fromDist = join(process.cwd(), 'dist', 'worker', 'decoder-worker.js');
|
|
17
|
+
if (existsSync(fromDist))
|
|
18
|
+
return pathToFileURL(fromDist);
|
|
19
|
+
return pathToFileURL(fromModule);
|
|
20
|
+
}
|
|
21
|
+
let nextId = 0;
|
|
22
|
+
/**
|
|
23
|
+
* Decode binary in a worker thread. Main thread stays responsive.
|
|
24
|
+
* Uses transferable ArrayBuffer when possible to avoid copy.
|
|
25
|
+
*/
|
|
26
|
+
export function decodeAsync(buffer, options) {
|
|
27
|
+
const id = nextId++;
|
|
28
|
+
const ab = buffer.buffer.slice(buffer.byteOffset, buffer.byteOffset + buffer.byteLength);
|
|
29
|
+
return new Promise((resolve, reject) => {
|
|
30
|
+
const worker = new Worker(getWorkerURL(), { workerData: null, eval: false });
|
|
31
|
+
const onMessage = (msg) => {
|
|
32
|
+
if (msg.id !== id)
|
|
33
|
+
return;
|
|
34
|
+
cleanup();
|
|
35
|
+
if ('error' in msg && msg.error) {
|
|
36
|
+
reject(new KodaDecodeError(msg.error));
|
|
37
|
+
}
|
|
38
|
+
else if ('value' in msg && msg.value !== undefined) {
|
|
39
|
+
resolve(msg.value);
|
|
40
|
+
}
|
|
41
|
+
else {
|
|
42
|
+
reject(new KodaDecodeError('Worker did not return value'));
|
|
43
|
+
}
|
|
44
|
+
};
|
|
45
|
+
const onError = (err) => {
|
|
46
|
+
cleanup();
|
|
47
|
+
reject(err);
|
|
48
|
+
};
|
|
49
|
+
const onExit = (code) => {
|
|
50
|
+
if (code !== 0) {
|
|
51
|
+
cleanup();
|
|
52
|
+
reject(new KodaDecodeError(`Worker exited with code ${code}`));
|
|
53
|
+
}
|
|
54
|
+
};
|
|
55
|
+
const cleanup = () => {
|
|
56
|
+
worker.off('message', onMessage);
|
|
57
|
+
worker.off('error', onError);
|
|
58
|
+
worker.off('exit', onExit);
|
|
59
|
+
worker.terminate().catch(() => { });
|
|
60
|
+
};
|
|
61
|
+
worker.on('message', onMessage);
|
|
62
|
+
worker.on('error', onError);
|
|
63
|
+
worker.on('exit', onExit);
|
|
64
|
+
worker.postMessage({ id, buffer: ab, options }, [ab]);
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Create a pool of decoder workers for high throughput. Decode jobs are
|
|
69
|
+
* distributed round-robin across workers.
|
|
70
|
+
*/
|
|
71
|
+
export function createDecoderPool(options = {}) {
|
|
72
|
+
const poolSize = Math.max(1, options.poolSize ?? 1);
|
|
73
|
+
const workers = [];
|
|
74
|
+
const pendingByWorker = new Map();
|
|
75
|
+
let nextIndex = 0;
|
|
76
|
+
let destroyed = false;
|
|
77
|
+
for (let i = 0; i < poolSize; i++) {
|
|
78
|
+
const w = new Worker(getWorkerURL(), { workerData: null, eval: false });
|
|
79
|
+
pendingByWorker.set(w, new Map());
|
|
80
|
+
w.on('message', (msg) => {
|
|
81
|
+
const pending = pendingByWorker.get(w);
|
|
82
|
+
const entry = pending.get(msg.id);
|
|
83
|
+
if (!entry)
|
|
84
|
+
return;
|
|
85
|
+
pending.delete(msg.id);
|
|
86
|
+
if ('error' in msg && msg.error) {
|
|
87
|
+
entry.reject(new KodaDecodeError(msg.error));
|
|
88
|
+
}
|
|
89
|
+
else if ('value' in msg && msg.value !== undefined) {
|
|
90
|
+
entry.resolve(msg.value);
|
|
91
|
+
}
|
|
92
|
+
else {
|
|
93
|
+
entry.reject(new KodaDecodeError('Worker did not return value'));
|
|
94
|
+
}
|
|
95
|
+
});
|
|
96
|
+
workers.push(w);
|
|
97
|
+
}
|
|
98
|
+
function decode(buffer, options) {
|
|
99
|
+
if (destroyed)
|
|
100
|
+
return Promise.reject(new KodaDecodeError('Decoder pool has been destroyed'));
|
|
101
|
+
const id = nextId++;
|
|
102
|
+
const ab = buffer.buffer.slice(buffer.byteOffset, buffer.byteOffset + buffer.byteLength);
|
|
103
|
+
return new Promise((resolve, reject) => {
|
|
104
|
+
const worker = workers[nextIndex % workers.length];
|
|
105
|
+
nextIndex++;
|
|
106
|
+
pendingByWorker.get(worker).set(id, { resolve, reject });
|
|
107
|
+
worker.postMessage({ id, buffer: ab, options }, [ab]);
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
function destroy() {
|
|
111
|
+
if (destroyed)
|
|
112
|
+
return;
|
|
113
|
+
destroyed = true;
|
|
114
|
+
for (const w of workers) {
|
|
115
|
+
w.terminate().catch(() => { });
|
|
116
|
+
}
|
|
117
|
+
workers.length = 0;
|
|
118
|
+
}
|
|
119
|
+
return { decode, destroy };
|
|
120
|
+
}
|
|
121
|
+
//# sourceMappingURL=decode-async.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"decode-async.js","sourceRoot":"","sources":["../src/decode-async.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* KODA binary v2 decoding (BINARY-V2.md).
|
|
3
|
+
*/
|
|
4
|
+
import type { KodaValue } from './ast.js';
|
|
5
|
+
export interface DecodeV2Options {
|
|
6
|
+
maxDepth?: number;
|
|
7
|
+
maxDictionarySize?: number;
|
|
8
|
+
maxStringLength?: number;
|
|
9
|
+
}
|
|
10
|
+
export declare function decodeV2(buffer: Uint8Array, options?: DecodeV2Options): KodaValue;
|
|
11
|
+
//# sourceMappingURL=decoderV2.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"decoderV2.d.ts","sourceRoot":"","sources":["../src/decoderV2.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAmB1C,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAMD,wBAAgB,QAAQ,CAAC,MAAM,EAAE,UAAU,EAAE,OAAO,GAAE,eAAoB,GAAG,SAAS,CAuHrF"}
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* KODA binary v2 decoding (BINARY-V2.md).
|
|
3
|
+
*/
|
|
4
|
+
import { KodaDecodeError } from './errors.js';
|
|
5
|
+
import { readUvarint as readUvarintFrom, zigzagDecode } from './varint.js';
|
|
6
|
+
const MAGIC_V2 = new Uint8Array([0x4b, 0x44]);
|
|
7
|
+
const VERSION_V2 = 0x02;
|
|
8
|
+
var Tag;
|
|
9
|
+
(function (Tag) {
|
|
10
|
+
Tag[Tag["Null"] = 0] = "Null";
|
|
11
|
+
Tag[Tag["False"] = 1] = "False";
|
|
12
|
+
Tag[Tag["True"] = 2] = "True";
|
|
13
|
+
Tag[Tag["IntVarint"] = 3] = "IntVarint";
|
|
14
|
+
Tag[Tag["Int64"] = 4] = "Int64";
|
|
15
|
+
Tag[Tag["Float"] = 5] = "Float";
|
|
16
|
+
Tag[Tag["String"] = 6] = "String";
|
|
17
|
+
Tag[Tag["Array"] = 8] = "Array";
|
|
18
|
+
Tag[Tag["Object"] = 9] = "Object";
|
|
19
|
+
})(Tag || (Tag = {}));
|
|
20
|
+
const DEFAULT_MAX_DEPTH = 256;
|
|
21
|
+
const DEFAULT_MAX_DICT = 65536;
|
|
22
|
+
const DEFAULT_MAX_STRING = 1_000_000;
|
|
23
|
+
export function decodeV2(buffer, options = {}) {
|
|
24
|
+
const maxDepth = options.maxDepth ?? DEFAULT_MAX_DEPTH;
|
|
25
|
+
const maxDict = options.maxDictionarySize ?? DEFAULT_MAX_DICT;
|
|
26
|
+
const maxStr = options.maxStringLength ?? DEFAULT_MAX_STRING;
|
|
27
|
+
let offset = 0;
|
|
28
|
+
const view = new DataView(buffer.buffer, buffer.byteOffset, buffer.length);
|
|
29
|
+
function fail(message) {
|
|
30
|
+
throw new KodaDecodeError(message, { byteOffset: offset });
|
|
31
|
+
}
|
|
32
|
+
function ensure(n) {
|
|
33
|
+
if (offset + n > buffer.length)
|
|
34
|
+
fail('Truncated input');
|
|
35
|
+
}
|
|
36
|
+
function readByte() {
|
|
37
|
+
ensure(1);
|
|
38
|
+
return buffer[offset++];
|
|
39
|
+
}
|
|
40
|
+
function readUvarint() {
|
|
41
|
+
const r = readUvarintFrom(buffer, offset);
|
|
42
|
+
offset = r.offset;
|
|
43
|
+
return r.value;
|
|
44
|
+
}
|
|
45
|
+
function readBytes(n) {
|
|
46
|
+
ensure(n);
|
|
47
|
+
const slice = buffer.subarray(offset, offset + n);
|
|
48
|
+
offset += n;
|
|
49
|
+
return slice;
|
|
50
|
+
}
|
|
51
|
+
function readI64() {
|
|
52
|
+
ensure(8);
|
|
53
|
+
const v = view.getBigInt64(offset, false);
|
|
54
|
+
offset += 8;
|
|
55
|
+
if (v >= Number.MIN_SAFE_INTEGER && v <= Number.MAX_SAFE_INTEGER)
|
|
56
|
+
return Number(v);
|
|
57
|
+
return Number(v);
|
|
58
|
+
}
|
|
59
|
+
function readF64() {
|
|
60
|
+
ensure(8);
|
|
61
|
+
const v = view.getFloat64(offset, false);
|
|
62
|
+
offset += 8;
|
|
63
|
+
return v;
|
|
64
|
+
}
|
|
65
|
+
function decodeUtf8(bytes) {
|
|
66
|
+
return new TextDecoder('utf-8', { fatal: true }).decode(bytes);
|
|
67
|
+
}
|
|
68
|
+
// Header
|
|
69
|
+
ensure(3);
|
|
70
|
+
if (buffer[offset] !== MAGIC_V2[0] || buffer[offset + 1] !== MAGIC_V2[1])
|
|
71
|
+
fail('Invalid magic (expected v2)');
|
|
72
|
+
offset += 2;
|
|
73
|
+
const version = readByte();
|
|
74
|
+
if (version !== VERSION_V2)
|
|
75
|
+
fail(`Unsupported version: ${version}`);
|
|
76
|
+
const dictLen = readUvarint();
|
|
77
|
+
if (dictLen > maxDict)
|
|
78
|
+
fail('Dictionary too large');
|
|
79
|
+
const dictionary = new Array(dictLen);
|
|
80
|
+
for (let i = 0; i < dictLen; i++) {
|
|
81
|
+
const keyLen = readUvarint();
|
|
82
|
+
if (keyLen > maxStr)
|
|
83
|
+
fail('Key string too long');
|
|
84
|
+
const keyBytes = readBytes(keyLen);
|
|
85
|
+
dictionary[i] = decodeUtf8(keyBytes);
|
|
86
|
+
}
|
|
87
|
+
function decodeValue(depth) {
|
|
88
|
+
if (depth > maxDepth)
|
|
89
|
+
fail('Maximum nesting depth exceeded');
|
|
90
|
+
ensure(1);
|
|
91
|
+
const tag = readByte();
|
|
92
|
+
switch (tag) {
|
|
93
|
+
case Tag.Null:
|
|
94
|
+
return null;
|
|
95
|
+
case Tag.False:
|
|
96
|
+
return false;
|
|
97
|
+
case Tag.True:
|
|
98
|
+
return true;
|
|
99
|
+
case Tag.IntVarint: {
|
|
100
|
+
const z = readUvarint();
|
|
101
|
+
return zigzagDecode(z);
|
|
102
|
+
}
|
|
103
|
+
case Tag.Int64:
|
|
104
|
+
return readI64();
|
|
105
|
+
case Tag.Float:
|
|
106
|
+
return readF64();
|
|
107
|
+
case Tag.String: {
|
|
108
|
+
const len = readUvarint();
|
|
109
|
+
if (len > maxStr)
|
|
110
|
+
fail('String too long');
|
|
111
|
+
const bytes = readBytes(len);
|
|
112
|
+
return decodeUtf8(bytes);
|
|
113
|
+
}
|
|
114
|
+
case Tag.Array: {
|
|
115
|
+
const count = readUvarint();
|
|
116
|
+
const arr = new Array(count);
|
|
117
|
+
for (let i = 0; i < count; i++)
|
|
118
|
+
arr[i] = decodeValue(depth + 1);
|
|
119
|
+
return arr;
|
|
120
|
+
}
|
|
121
|
+
case Tag.Object: {
|
|
122
|
+
const count = readUvarint();
|
|
123
|
+
const obj = {};
|
|
124
|
+
for (let i = 0; i < count; i++) {
|
|
125
|
+
const keyIdx = readUvarint();
|
|
126
|
+
if (keyIdx >= dictionary.length)
|
|
127
|
+
fail('Invalid key index');
|
|
128
|
+
const key = dictionary[keyIdx];
|
|
129
|
+
obj[key] = decodeValue(depth + 1);
|
|
130
|
+
}
|
|
131
|
+
return obj;
|
|
132
|
+
}
|
|
133
|
+
default:
|
|
134
|
+
fail(`Unknown type tag: 0x${tag.toString(16)}`);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
const value = decodeValue(0);
|
|
138
|
+
if (offset !== buffer.length)
|
|
139
|
+
fail('Trailing bytes after root value');
|
|
140
|
+
return value;
|
|
141
|
+
}
|
|
142
|
+
//# sourceMappingURL=decoderV2.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"decoderV2.js","sourceRoot":"","sources":["../src/decoderV2.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* KODA binary v2 — compact storage-oriented encoding (BINARY-V2.md).
|
|
3
|
+
* Varints, minimal header, dictionary with varint lengths.
|
|
4
|
+
*/
|
|
5
|
+
import type { KodaValue } from './ast.js';
|
|
6
|
+
export interface EncodeV2Options {
|
|
7
|
+
maxDepth?: number;
|
|
8
|
+
}
|
|
9
|
+
export declare function encodeV2(value: KodaValue, options?: EncodeV2Options): Uint8Array;
|
|
10
|
+
//# sourceMappingURL=encoderV2.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"encoderV2.d.ts","sourceRoot":"","sources":["../src/encoderV2.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAgD1C,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAID,wBAAgB,QAAQ,CAAC,KAAK,EAAE,SAAS,EAAE,OAAO,GAAE,eAAoB,GAAG,UAAU,CAwHpF"}
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* KODA binary v2 — compact storage-oriented encoding (BINARY-V2.md).
|
|
3
|
+
* Varints, minimal header, dictionary with varint lengths.
|
|
4
|
+
*/
|
|
5
|
+
import { KodaEncodeError } from './errors.js';
|
|
6
|
+
import { uvarintSize, writeUvarint, zigzagEncode } from './varint.js';
|
|
7
|
+
const MAGIC_V2 = new Uint8Array([0x4b, 0x44]); // "KD"
|
|
8
|
+
const VERSION_V2 = 0x02;
|
|
9
|
+
var Tag;
|
|
10
|
+
(function (Tag) {
|
|
11
|
+
Tag[Tag["Null"] = 0] = "Null";
|
|
12
|
+
Tag[Tag["False"] = 1] = "False";
|
|
13
|
+
Tag[Tag["True"] = 2] = "True";
|
|
14
|
+
Tag[Tag["IntVarint"] = 3] = "IntVarint";
|
|
15
|
+
Tag[Tag["Int64"] = 4] = "Int64";
|
|
16
|
+
Tag[Tag["Float"] = 5] = "Float";
|
|
17
|
+
Tag[Tag["String"] = 6] = "String";
|
|
18
|
+
Tag[Tag["Array"] = 8] = "Array";
|
|
19
|
+
Tag[Tag["Object"] = 9] = "Object";
|
|
20
|
+
})(Tag || (Tag = {}));
|
|
21
|
+
const MIN_INT32 = -0x8000_0000;
|
|
22
|
+
const MAX_INT32 = 0x7fff_ffff;
|
|
23
|
+
function collectKeys(value, set) {
|
|
24
|
+
if (value === null || typeof value !== 'object')
|
|
25
|
+
return;
|
|
26
|
+
if (Array.isArray(value)) {
|
|
27
|
+
for (const v of value)
|
|
28
|
+
collectKeys(v, set);
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
const obj = value;
|
|
32
|
+
for (const k of Object.keys(obj)) {
|
|
33
|
+
set.add(k);
|
|
34
|
+
collectKeys(obj[k], set);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
function encodeUtf8(s) {
|
|
38
|
+
return new TextEncoder().encode(s);
|
|
39
|
+
}
|
|
40
|
+
function compareKeys(a, b) {
|
|
41
|
+
const aa = encodeUtf8(a);
|
|
42
|
+
const bb = encodeUtf8(b);
|
|
43
|
+
for (let i = 0; i < Math.min(aa.length, bb.length); i++) {
|
|
44
|
+
if (aa[i] !== bb[i])
|
|
45
|
+
return aa[i] - bb[i];
|
|
46
|
+
}
|
|
47
|
+
return aa.length - bb.length;
|
|
48
|
+
}
|
|
49
|
+
const DEFAULT_MAX_DEPTH = 256;
|
|
50
|
+
export function encodeV2(value, options = {}) {
|
|
51
|
+
const maxDepth = options.maxDepth ?? DEFAULT_MAX_DEPTH;
|
|
52
|
+
const keysSet = new Set();
|
|
53
|
+
collectKeys(value, keysSet);
|
|
54
|
+
const dictionary = [...keysSet].sort(compareKeys);
|
|
55
|
+
const keyToIndex = new Map();
|
|
56
|
+
dictionary.forEach((k, i) => keyToIndex.set(k, i));
|
|
57
|
+
const INITIAL = 4096;
|
|
58
|
+
let buf = new Uint8Array(INITIAL);
|
|
59
|
+
let off = 0;
|
|
60
|
+
function ensure(n) {
|
|
61
|
+
if (off + n > buf.length) {
|
|
62
|
+
const next = new Uint8Array(Math.max(buf.length * 2, off + n));
|
|
63
|
+
next.set(buf.subarray(0, off));
|
|
64
|
+
buf = next;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
function writeByte(x) {
|
|
68
|
+
ensure(1);
|
|
69
|
+
buf[off++] = x;
|
|
70
|
+
}
|
|
71
|
+
function writeBytes(b) {
|
|
72
|
+
ensure(b.length);
|
|
73
|
+
buf.set(b, off);
|
|
74
|
+
off += b.length;
|
|
75
|
+
}
|
|
76
|
+
function appendUvarint(v) {
|
|
77
|
+
ensure(uvarintSize(v));
|
|
78
|
+
off = writeUvarint(buf, off, v);
|
|
79
|
+
}
|
|
80
|
+
// Header
|
|
81
|
+
buf.set(MAGIC_V2, off);
|
|
82
|
+
off += 2;
|
|
83
|
+
writeByte(VERSION_V2);
|
|
84
|
+
// Dictionary
|
|
85
|
+
appendUvarint(dictionary.length);
|
|
86
|
+
for (const k of dictionary) {
|
|
87
|
+
const bytes = encodeUtf8(k);
|
|
88
|
+
appendUvarint(bytes.length);
|
|
89
|
+
writeBytes(bytes);
|
|
90
|
+
}
|
|
91
|
+
function encodeValue(v, depth) {
|
|
92
|
+
if (depth > maxDepth) {
|
|
93
|
+
throw new KodaEncodeError('Maximum nesting depth exceeded', { byteOffset: off });
|
|
94
|
+
}
|
|
95
|
+
if (v === null) {
|
|
96
|
+
writeByte(Tag.Null);
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
if (v === false) {
|
|
100
|
+
writeByte(Tag.False);
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
if (v === true) {
|
|
104
|
+
writeByte(Tag.True);
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
if (typeof v === 'number') {
|
|
108
|
+
if (Number.isInteger(v) && v >= MIN_INT32 && v <= MAX_INT32) {
|
|
109
|
+
writeByte(Tag.IntVarint);
|
|
110
|
+
const z = zigzagEncode(v);
|
|
111
|
+
ensure(uvarintSize(z));
|
|
112
|
+
off = writeUvarint(buf, off, z);
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
115
|
+
// Float or int64
|
|
116
|
+
if (Number.isInteger(v) && v >= Number.MIN_SAFE_INTEGER && v <= Number.MAX_SAFE_INTEGER) {
|
|
117
|
+
writeByte(Tag.Int64);
|
|
118
|
+
ensure(8);
|
|
119
|
+
const view = new DataView(buf.buffer, buf.byteOffset + off, 8);
|
|
120
|
+
view.setBigInt64(0, BigInt(Math.floor(v)), false);
|
|
121
|
+
off += 8;
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
|
+
writeByte(Tag.Float);
|
|
125
|
+
ensure(8);
|
|
126
|
+
new DataView(buf.buffer, buf.byteOffset + off, 8).setFloat64(0, v, false);
|
|
127
|
+
off += 8;
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
if (typeof v === 'string') {
|
|
131
|
+
const bytes = encodeUtf8(v);
|
|
132
|
+
writeByte(Tag.String);
|
|
133
|
+
appendUvarint(bytes.length);
|
|
134
|
+
writeBytes(bytes);
|
|
135
|
+
return;
|
|
136
|
+
}
|
|
137
|
+
if (Array.isArray(v)) {
|
|
138
|
+
writeByte(Tag.Array);
|
|
139
|
+
appendUvarint(v.length);
|
|
140
|
+
for (const item of v)
|
|
141
|
+
encodeValue(item, depth + 1);
|
|
142
|
+
return;
|
|
143
|
+
}
|
|
144
|
+
const obj = v;
|
|
145
|
+
const sortedKeys = Object.keys(obj).sort(compareKeys);
|
|
146
|
+
writeByte(Tag.Object);
|
|
147
|
+
appendUvarint(sortedKeys.length);
|
|
148
|
+
for (const key of sortedKeys) {
|
|
149
|
+
const idx = keyToIndex.get(key);
|
|
150
|
+
if (idx === undefined)
|
|
151
|
+
throw new KodaEncodeError('Key not in dictionary', { byteOffset: off });
|
|
152
|
+
appendUvarint(idx);
|
|
153
|
+
encodeValue(obj[key], depth + 1);
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
encodeValue(value, 0);
|
|
157
|
+
return off === buf.length ? buf : buf.subarray(0, off);
|
|
158
|
+
}
|
|
159
|
+
//# sourceMappingURL=encoderV2.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"encoderV2.js","sourceRoot":"","sources":["../src/encoderV2.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -17,6 +17,8 @@ export type { ParseOptions } from './parser.js';
|
|
|
17
17
|
export type { StringifyOptions } from './stringify.js';
|
|
18
18
|
export type { EncodeOptions } from './encoder.js';
|
|
19
19
|
export type { DecodeOptions } from './decoder.js';
|
|
20
|
+
export { decodeAsync, createDecoderPool } from './decode-async.js';
|
|
21
|
+
export type { DecoderPool, DecoderPoolOptions } from './decode-async.js';
|
|
20
22
|
/** True if the C++ native addon is in use. */
|
|
21
23
|
export declare function isNativeAvailable(): boolean;
|
|
22
24
|
/**
|
|
@@ -35,10 +37,15 @@ export declare function stringify(value: KodaValue, options?: StringifyOptions):
|
|
|
35
37
|
*/
|
|
36
38
|
export declare function encode(value: KodaValue, options?: EncodeOptions): Uint8Array;
|
|
37
39
|
/**
|
|
38
|
-
* Decode binary (.kod) to a value.
|
|
39
|
-
*
|
|
40
|
+
* Decode binary (.kod) to a value. Non-blocking: runs in a worker thread so the
|
|
41
|
+
* main thread stays responsive. Prefer this over decodeSync for large payloads.
|
|
40
42
|
*/
|
|
41
|
-
export declare function decode(buffer: Uint8Array, options?: DecodeOptions): KodaValue
|
|
43
|
+
export declare function decode(buffer: Uint8Array, options?: DecodeOptions): Promise<KodaValue>;
|
|
44
|
+
/**
|
|
45
|
+
* Synchronous decode. Blocks the event loop; use sparingly or for small payloads.
|
|
46
|
+
* Uses native C++ when addon is built, otherwise JS fallback.
|
|
47
|
+
*/
|
|
48
|
+
export declare function decodeSync(buffer: Uint8Array, options?: DecodeOptions): KodaValue;
|
|
42
49
|
/**
|
|
43
50
|
* Load and parse a .koda text file (UTF-8).
|
|
44
51
|
*/
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAKH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAE1C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAElD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAIlD,OAAO,EAAE,KAAK,IAAI,cAAc,EAAE,MAAM,aAAa,CAAC;AACtD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAKH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAE1C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAElD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAIlD,OAAO,EAAE,KAAK,IAAI,cAAc,EAAE,MAAM,aAAa,CAAC;AACtD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAGhD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAEvD,YAAY,EAAE,SAAS,EAAE,UAAU,EAAE,SAAS,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AACjF,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,YAAY,EAAE,YAAY,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAC5G,OAAO,EAAE,SAAS,EAAE,cAAc,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAC1F,YAAY,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAChD,YAAY,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AACvD,YAAY,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAClD,YAAY,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAClD,OAAO,EAAE,WAAW,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AACnE,YAAY,EAAE,WAAW,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAQzE,8CAA8C;AAC9C,wBAAgB,iBAAiB,IAAI,OAAO,CAE3C;AAED;;;GAGG;AACH,wBAAgB,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,YAAY,GAAG,SAAS,CAUrE;AAED;;;GAGG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,SAAS,EAAE,OAAO,CAAC,EAAE,gBAAgB,GAAG,MAAM,CAM9E;AAED;;;GAGG;AACH,wBAAgB,MAAM,CAAC,KAAK,EAAE,SAAS,EAAE,OAAO,CAAC,EAAE,aAAa,GAAG,UAAU,CAM5E;AAED;;;GAGG;AACH,wBAAgB,MAAM,CAAC,MAAM,EAAE,UAAU,EAAE,OAAO,CAAC,EAAE,aAAa,GAAG,OAAO,CAAC,SAAS,CAAC,CAEtF;AAED;;;GAGG;AACH,wBAAgB,UAAU,CAAC,MAAM,EAAE,UAAU,EAAE,OAAO,CAAC,EAAE,aAAa,GAAG,SAAS,CAejF;AAED;;GAEG;AACH,wBAAsB,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,YAAY,GAAG,OAAO,CAAC,SAAS,CAAC,CAGvF;AAED,gGAAgG;AAChG,OAAO,EAAE,cAAc,EAAE,CAAC;AAE1B;;GAEG;AACH,wBAAsB,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,EAAE,OAAO,CAAC,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC,CAGxG;AAED;;GAEG;AACH,wBAAgB,MAAM,CAAC,KAAK,EAAE,SAAS,GAAG,MAAM,CAE/C;AAED;;GAEG;AACH,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,CAEhD"}
|
package/dist/index.js
CHANGED
|
@@ -13,9 +13,11 @@ import { KodaDecodeError, KodaParseError } from './errors.js';
|
|
|
13
13
|
import { loadNative } from './native.js';
|
|
14
14
|
import { parseFast } from './parseFast.js';
|
|
15
15
|
import { parse as parseWithLexer } from './parser.js';
|
|
16
|
+
import { decodeAsync } from './decode-async.js';
|
|
16
17
|
import { stringify as stringifyText } from './stringify.js';
|
|
17
18
|
export { isKodaObject, isKodaArray, isKodaString, isKodaNumber, isKodaBoolean, isKodaNull } from './ast.js';
|
|
18
19
|
export { KodaError, KodaParseError, KodaEncodeError, KodaDecodeError } from './errors.js';
|
|
20
|
+
export { decodeAsync, createDecoderPool } from './decode-async.js';
|
|
19
21
|
const _addonPath = join(dirname(dirname(fileURLToPath(import.meta.url))), 'build', 'Release', 'koda_format.node');
|
|
20
22
|
function getNative() {
|
|
21
23
|
return loadNative(import.meta.url, _addonPath);
|
|
@@ -63,10 +65,17 @@ export function encode(value, options) {
|
|
|
63
65
|
return encodeBinary(value, options);
|
|
64
66
|
}
|
|
65
67
|
/**
|
|
66
|
-
* Decode binary (.kod) to a value.
|
|
67
|
-
*
|
|
68
|
+
* Decode binary (.kod) to a value. Non-blocking: runs in a worker thread so the
|
|
69
|
+
* main thread stays responsive. Prefer this over decodeSync for large payloads.
|
|
68
70
|
*/
|
|
69
71
|
export function decode(buffer, options) {
|
|
72
|
+
return decodeAsync(buffer, options);
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Synchronous decode. Blocks the event loop; use sparingly or for small payloads.
|
|
76
|
+
* Uses native C++ when addon is built, otherwise JS fallback.
|
|
77
|
+
*/
|
|
78
|
+
export function decodeSync(buffer, options) {
|
|
70
79
|
const native = getNative();
|
|
71
80
|
if (native) {
|
|
72
81
|
try {
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AACvD,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAEzC,OAAO,EAAE,MAAM,IAAI,YAAY,EAAE,MAAM,cAAc,CAAC;AAEtD,OAAO,EAAE,MAAM,IAAI,YAAY,EAAE,MAAM,cAAc,CAAC;AAEtD,OAAO,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC9D,OAAO,EAAE,UAAU,EAAsB,MAAM,aAAa,CAAC;AAC7D,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3C,OAAO,EAAE,KAAK,IAAI,cAAc,EAAE,MAAM,aAAa,CAAC;AAEtD,OAAO,EAAE,SAAS,IAAI,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAI5D,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,YAAY,EAAE,YAAY,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAC5G,OAAO,EAAE,SAAS,EAAE,cAAc,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/varint.d.ts
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Unsigned and zigzag signed varint encoding for KODA binary v2.
|
|
3
|
+
*/
|
|
4
|
+
/** Encode unsigned integer as varint; write into buf at off; return new offset. */
|
|
5
|
+
export declare function writeUvarint(buf: Uint8Array, off: number, v: number): number;
|
|
6
|
+
/** Read unsigned varint from buf at off; return value and new offset. */
|
|
7
|
+
export declare function readUvarint(buf: Uint8Array, off: number): {
|
|
8
|
+
value: number;
|
|
9
|
+
offset: number;
|
|
10
|
+
};
|
|
11
|
+
/** Zigzag encode: 0->0, -1->1, 1->2, -2->3. Fits 32-bit signed int. */
|
|
12
|
+
export declare function zigzagEncode(n: number): number;
|
|
13
|
+
/** Zigzag decode. */
|
|
14
|
+
export declare function zigzagDecode(z: number): number;
|
|
15
|
+
/** Return number of bytes needed to encode v as unsigned varint. */
|
|
16
|
+
export declare function uvarintSize(v: number): number;
|
|
17
|
+
//# sourceMappingURL=varint.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"varint.d.ts","sourceRoot":"","sources":["../src/varint.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,mFAAmF;AACnF,wBAAgB,YAAY,CAAC,GAAG,EAAE,UAAU,EAAE,GAAG,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAO5E;AAED,yEAAyE;AACzE,wBAAgB,WAAW,CAAC,GAAG,EAAE,UAAU,EAAE,GAAG,EAAE,MAAM,GAAG;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAW3F;AAED,uEAAuE;AACvE,wBAAgB,YAAY,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAE9C;AAED,qBAAqB;AACrB,wBAAgB,YAAY,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAE9C;AAED,oEAAoE;AACpE,wBAAgB,WAAW,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAQ7C"}
|
package/dist/varint.js
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Unsigned and zigzag signed varint encoding for KODA binary v2.
|
|
3
|
+
*/
|
|
4
|
+
/** Encode unsigned integer as varint; write into buf at off; return new offset. */
|
|
5
|
+
export function writeUvarint(buf, off, v) {
|
|
6
|
+
while (v > 0x7f) {
|
|
7
|
+
buf[off++] = (v & 0x7f) | 0x80;
|
|
8
|
+
v >>>= 7;
|
|
9
|
+
}
|
|
10
|
+
buf[off++] = v & 0x7f;
|
|
11
|
+
return off;
|
|
12
|
+
}
|
|
13
|
+
/** Read unsigned varint from buf at off; return value and new offset. */
|
|
14
|
+
export function readUvarint(buf, off) {
|
|
15
|
+
let value = 0;
|
|
16
|
+
let shift = 0;
|
|
17
|
+
for (;;) {
|
|
18
|
+
if (off >= buf.length)
|
|
19
|
+
throw new Error('Truncated varint');
|
|
20
|
+
const b = buf[off++];
|
|
21
|
+
value |= (b & 0x7f) << shift;
|
|
22
|
+
if ((b & 0x80) === 0)
|
|
23
|
+
return { value, offset: off };
|
|
24
|
+
shift += 7;
|
|
25
|
+
if (shift >= 35)
|
|
26
|
+
throw new Error('Varint overflow');
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
/** Zigzag encode: 0->0, -1->1, 1->2, -2->3. Fits 32-bit signed int. */
|
|
30
|
+
export function zigzagEncode(n) {
|
|
31
|
+
return (n << 1) ^ (n >> 31);
|
|
32
|
+
}
|
|
33
|
+
/** Zigzag decode. */
|
|
34
|
+
export function zigzagDecode(z) {
|
|
35
|
+
return (z >>> 1) ^ -(z & 1);
|
|
36
|
+
}
|
|
37
|
+
/** Return number of bytes needed to encode v as unsigned varint. */
|
|
38
|
+
export function uvarintSize(v) {
|
|
39
|
+
if (v === 0)
|
|
40
|
+
return 1;
|
|
41
|
+
let n = 0;
|
|
42
|
+
while (v > 0) {
|
|
43
|
+
n++;
|
|
44
|
+
v >>>= 7;
|
|
45
|
+
}
|
|
46
|
+
return n;
|
|
47
|
+
}
|
|
48
|
+
//# sourceMappingURL=varint.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"varint.js","sourceRoot":"","sources":["../src/varint.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,mFAAmF;AACnF,MAAM,UAAU,YAAY,CAAC,GAAe,EAAE,GAAW,EAAE,CAAS;IAClE,OAAO,CAAC,GAAG,IAAI,EAAE,CAAC;QAChB,GAAG,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,GAAG,IAAI,CAAC;QAC/B,CAAC,MAAM,CAAC,CAAC;IACX,CAAC;IACD,GAAG,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC;IACtB,OAAO,GAAG,CAAC;AACb,CAAC;AAED,yEAAyE;AACzE,MAAM,UAAU,WAAW,CAAC,GAAe,EAAE,GAAW;IACtD,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,SAAS,CAAC;QACR,IAAI,GAAG,IAAI,GAAG,CAAC,MAAM;YAAE,MAAM,IAAI,KAAK,CAAC,kBAAkB,CAAC,CAAC;QAC3D,MAAM,CAAC,GAAG,GAAG,CAAC,GAAG,EAAE,CAAE,CAAC;QACtB,KAAK,IAAI,CAAC,CAAC,GAAG,IAAI,CAAC,IAAI,KAAK,CAAC;QAC7B,IAAI,CAAC,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC;YAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC;QACpD,KAAK,IAAI,CAAC,CAAC;QACX,IAAI,KAAK,IAAI,EAAE;YAAE,MAAM,IAAI,KAAK,CAAC,iBAAiB,CAAC,CAAC;IACtD,CAAC;AACH,CAAC;AAED,uEAAuE;AACvE,MAAM,UAAU,YAAY,CAAC,CAAS;IACpC,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;AAC9B,CAAC;AAED,qBAAqB;AACrB,MAAM,UAAU,YAAY,CAAC,CAAS;IACpC,OAAO,CAAC,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;AAC9B,CAAC;AAED,oEAAoE;AACpE,MAAM,UAAU,WAAW,CAAC,CAAS;IACnC,IAAI,CAAC,KAAK,CAAC;QAAE,OAAO,CAAC,CAAC;IACtB,IAAI,CAAC,GAAG,CAAC,CAAC;IACV,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;QACb,CAAC,EAAE,CAAC;QACJ,CAAC,MAAM,CAAC,CAAC;IACX,CAAC;IACD,OAAO,CAAC,CAAC;AACX,CAAC"}
|
package/dist/view.d.ts
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* KodaView — direct-access API over KODA binary (v3) or wrapper over decoded value (v2).
|
|
3
|
+
*
|
|
4
|
+
* For v3 format: parses only header + dictionary + root directory; get(key) seeks and
|
|
5
|
+
* decodes one value. See BINARY-DIRECT-ACCESS.md.
|
|
6
|
+
*
|
|
7
|
+
* For v2 format: full decode then wrap (same API, no direct access). Enables consistent
|
|
8
|
+
* API until v3 encoder exists.
|
|
9
|
+
*/
|
|
10
|
+
import type { KodaValue } from './ast.js';
|
|
11
|
+
export interface ViewOptions {
|
|
12
|
+
/** Reserved for v3 options (e.g. maxDictionarySize). */
|
|
13
|
+
maxDictionarySize?: number;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* View over a KODA value: direct-access style API (get/has/keys/getAt) without
|
|
17
|
+
* building a full object unless toObject() is called.
|
|
18
|
+
*/
|
|
19
|
+
export interface KodaView {
|
|
20
|
+
/** Get value by key (object) or index (array). Returns KodaView for nested object/array. */
|
|
21
|
+
get(key: string | number): KodaValue | KodaView | undefined;
|
|
22
|
+
/** True if key exists (object) or index in range (array). */
|
|
23
|
+
has(key: string | number): boolean;
|
|
24
|
+
/** Keys of this object (canonical order). For array, returns indices as strings. */
|
|
25
|
+
keys(): string[];
|
|
26
|
+
/** Get array element by index. Same as get(index) for arrays. */
|
|
27
|
+
getAt(index: number): KodaValue | KodaView | undefined;
|
|
28
|
+
/** Number of keys (object) or length (array). */
|
|
29
|
+
readonly length: number;
|
|
30
|
+
/** Node type. */
|
|
31
|
+
readonly type: 'object' | 'array' | 'scalar';
|
|
32
|
+
/** Decode this subtree to a plain KodaValue (object/array/primitive). */
|
|
33
|
+
toObject(): KodaValue;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Open a KODA binary buffer as a KodaView.
|
|
37
|
+
* - v3 (future): direct access; only directory parsed until get().
|
|
38
|
+
* - v2 (current): full decode then wrap; same API, no direct access.
|
|
39
|
+
*/
|
|
40
|
+
export declare function view(buffer: Uint8Array, _options?: ViewOptions): KodaView;
|
|
41
|
+
/**
|
|
42
|
+
* Wrap a decoded KodaValue in the KodaView API. Used for v2 buffers.
|
|
43
|
+
* No direct access; all data already in memory.
|
|
44
|
+
*/
|
|
45
|
+
export declare function wrapAsView(value: KodaValue): KodaView;
|
|
46
|
+
//# sourceMappingURL=view.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"view.d.ts","sourceRoot":"","sources":["../src/view.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAO1C,MAAM,WAAW,WAAW;IAC1B,wDAAwD;IACxD,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC5B;AAED;;;GAGG;AACH,MAAM,WAAW,QAAQ;IACvB,4FAA4F;IAC5F,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,GAAG,QAAQ,GAAG,SAAS,CAAC;IAC5D,6DAA6D;IAC7D,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC;IACnC,oFAAoF;IACpF,IAAI,IAAI,MAAM,EAAE,CAAC;IACjB,iEAAiE;IACjE,KAAK,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,QAAQ,GAAG,SAAS,CAAC;IACvD,iDAAiD;IACjD,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,iBAAiB;IACjB,QAAQ,CAAC,IAAI,EAAE,QAAQ,GAAG,OAAO,GAAG,QAAQ,CAAC;IAC7C,yEAAyE;IACzE,QAAQ,IAAI,SAAS,CAAC;CACvB;AAED;;;;GAIG;AACH,wBAAgB,IAAI,CAAC,MAAM,EAAE,UAAU,EAAE,QAAQ,GAAE,WAAgB,GAAG,QAAQ,CAc7E;AAED;;;GAGG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,SAAS,GAAG,QAAQ,CAQrD"}
|
package/dist/view.js
ADDED
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* KodaView — direct-access API over KODA binary (v3) or wrapper over decoded value (v2).
|
|
3
|
+
*
|
|
4
|
+
* For v3 format: parses only header + dictionary + root directory; get(key) seeks and
|
|
5
|
+
* decodes one value. See BINARY-DIRECT-ACCESS.md.
|
|
6
|
+
*
|
|
7
|
+
* For v2 format: full decode then wrap (same API, no direct access). Enables consistent
|
|
8
|
+
* API until v3 encoder exists.
|
|
9
|
+
*/
|
|
10
|
+
import { decodeV2 } from './decoderV2.js';
|
|
11
|
+
const MAGIC_V2 = new Uint8Array([0x4b, 0x44]);
|
|
12
|
+
const VERSION_V2 = 0x02;
|
|
13
|
+
const VERSION_V3 = 0x03;
|
|
14
|
+
/**
|
|
15
|
+
* Open a KODA binary buffer as a KodaView.
|
|
16
|
+
* - v3 (future): direct access; only directory parsed until get().
|
|
17
|
+
* - v2 (current): full decode then wrap; same API, no direct access.
|
|
18
|
+
*/
|
|
19
|
+
export function view(buffer, _options = {}) {
|
|
20
|
+
if (buffer.length < 3)
|
|
21
|
+
throw new Error('KODA buffer too short');
|
|
22
|
+
if (buffer[0] !== MAGIC_V2[0] || buffer[1] !== MAGIC_V2[1]) {
|
|
23
|
+
throw new Error('Invalid KODA magic');
|
|
24
|
+
}
|
|
25
|
+
const version = buffer[2];
|
|
26
|
+
if (version === VERSION_V3) {
|
|
27
|
+
throw new Error('KODA binary v3 direct-access not yet implemented. See BINARY-DIRECT-ACCESS.md.');
|
|
28
|
+
}
|
|
29
|
+
if (version === VERSION_V2) {
|
|
30
|
+
const value = decodeV2(buffer);
|
|
31
|
+
return wrapAsView(value);
|
|
32
|
+
}
|
|
33
|
+
throw new Error(`Unsupported KODA binary version: ${version}`);
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Wrap a decoded KodaValue in the KodaView API. Used for v2 buffers.
|
|
37
|
+
* No direct access; all data already in memory.
|
|
38
|
+
*/
|
|
39
|
+
export function wrapAsView(value) {
|
|
40
|
+
if (value === null || typeof value !== 'object') {
|
|
41
|
+
return new ScalarView(value);
|
|
42
|
+
}
|
|
43
|
+
if (Array.isArray(value)) {
|
|
44
|
+
return new ArrayView(value);
|
|
45
|
+
}
|
|
46
|
+
return new ObjectView(value);
|
|
47
|
+
}
|
|
48
|
+
function asView(v) {
|
|
49
|
+
if (v === null || typeof v !== 'object')
|
|
50
|
+
return new ScalarView(v);
|
|
51
|
+
if (Array.isArray(v))
|
|
52
|
+
return new ArrayView(v);
|
|
53
|
+
return new ObjectView(v);
|
|
54
|
+
}
|
|
55
|
+
class ScalarView {
|
|
56
|
+
value;
|
|
57
|
+
constructor(value) {
|
|
58
|
+
this.value = value;
|
|
59
|
+
}
|
|
60
|
+
get() {
|
|
61
|
+
return this.value;
|
|
62
|
+
}
|
|
63
|
+
has() {
|
|
64
|
+
return false;
|
|
65
|
+
}
|
|
66
|
+
keys() {
|
|
67
|
+
return [];
|
|
68
|
+
}
|
|
69
|
+
getAt() {
|
|
70
|
+
return undefined;
|
|
71
|
+
}
|
|
72
|
+
get length() {
|
|
73
|
+
return 0;
|
|
74
|
+
}
|
|
75
|
+
get type() {
|
|
76
|
+
return 'scalar';
|
|
77
|
+
}
|
|
78
|
+
toObject() {
|
|
79
|
+
return this.value;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
class ObjectView {
|
|
83
|
+
obj;
|
|
84
|
+
keyList;
|
|
85
|
+
constructor(obj) {
|
|
86
|
+
this.obj = obj;
|
|
87
|
+
this.keyList = Object.keys(obj).sort((a, b) => a.localeCompare(b, 'en', { sensitivity: 'base' }));
|
|
88
|
+
}
|
|
89
|
+
get(key) {
|
|
90
|
+
if (typeof key !== 'string')
|
|
91
|
+
return undefined;
|
|
92
|
+
const v = this.obj[key];
|
|
93
|
+
if (v === undefined)
|
|
94
|
+
return undefined;
|
|
95
|
+
if (v === null || typeof v !== 'object')
|
|
96
|
+
return v;
|
|
97
|
+
if (Array.isArray(v))
|
|
98
|
+
return new ArrayView(v);
|
|
99
|
+
return new ObjectView(v);
|
|
100
|
+
}
|
|
101
|
+
has(key) {
|
|
102
|
+
return typeof key === 'string' && key in this.obj;
|
|
103
|
+
}
|
|
104
|
+
keys() {
|
|
105
|
+
return this.keyList;
|
|
106
|
+
}
|
|
107
|
+
getAt(index) {
|
|
108
|
+
const k = this.keyList[index];
|
|
109
|
+
return k === undefined ? undefined : this.get(k);
|
|
110
|
+
}
|
|
111
|
+
get length() {
|
|
112
|
+
return this.keyList.length;
|
|
113
|
+
}
|
|
114
|
+
get type() {
|
|
115
|
+
return 'object';
|
|
116
|
+
}
|
|
117
|
+
toObject() {
|
|
118
|
+
return this.obj;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
class ArrayView {
|
|
122
|
+
arr;
|
|
123
|
+
constructor(arr) {
|
|
124
|
+
this.arr = arr;
|
|
125
|
+
}
|
|
126
|
+
get(key) {
|
|
127
|
+
const i = typeof key === 'number' ? key : parseInt(key, 10);
|
|
128
|
+
if (Number.isNaN(i) || i < 0 || i >= this.arr.length)
|
|
129
|
+
return undefined;
|
|
130
|
+
const v = this.arr[i];
|
|
131
|
+
if (v === undefined)
|
|
132
|
+
return undefined;
|
|
133
|
+
if (v === null || typeof v !== 'object')
|
|
134
|
+
return v;
|
|
135
|
+
return asView(v);
|
|
136
|
+
}
|
|
137
|
+
has(key) {
|
|
138
|
+
const i = typeof key === 'number' ? key : parseInt(key, 10);
|
|
139
|
+
return !Number.isNaN(i) && i >= 0 && i < this.arr.length;
|
|
140
|
+
}
|
|
141
|
+
keys() {
|
|
142
|
+
return this.arr.map((_, i) => String(i));
|
|
143
|
+
}
|
|
144
|
+
getAt(index) {
|
|
145
|
+
const v = this.arr[index];
|
|
146
|
+
if (v === undefined)
|
|
147
|
+
return undefined;
|
|
148
|
+
if (v === null || typeof v !== 'object')
|
|
149
|
+
return v;
|
|
150
|
+
return asView(v);
|
|
151
|
+
}
|
|
152
|
+
get length() {
|
|
153
|
+
return this.arr.length;
|
|
154
|
+
}
|
|
155
|
+
get type() {
|
|
156
|
+
return 'array';
|
|
157
|
+
}
|
|
158
|
+
toObject() {
|
|
159
|
+
return this.arr;
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
//# sourceMappingURL=view.js.map
|
package/dist/view.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"view.js","sourceRoot":"","sources":["../src/view.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* KODA decoder worker. Runs in a Worker Thread; loads native addon or uses JS fallback.
|
|
3
|
+
* Receives binary buffer (transferable), decodes, posts result. Keeps main thread non-blocking.
|
|
4
|
+
*/
|
|
5
|
+
import type { KodaValue } from '../ast.js';
|
|
6
|
+
import type { DecodeOptions } from '../decoder.js';
|
|
7
|
+
export interface DecoderWorkerMessageIn {
|
|
8
|
+
id: number;
|
|
9
|
+
buffer: ArrayBuffer;
|
|
10
|
+
options?: DecodeOptions;
|
|
11
|
+
}
|
|
12
|
+
export interface DecoderWorkerMessageOutSuccess {
|
|
13
|
+
id: number;
|
|
14
|
+
value: KodaValue;
|
|
15
|
+
}
|
|
16
|
+
export interface DecoderWorkerMessageOutError {
|
|
17
|
+
id: number;
|
|
18
|
+
error: string;
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=decoder-worker.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"decoder-worker.d.ts","sourceRoot":"","sources":["../../src/worker/decoder-worker.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAKH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAE3C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAcnD,MAAM,WAAW,sBAAsB;IACrC,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,WAAW,CAAC;IACpB,OAAO,CAAC,EAAE,aAAa,CAAC;CACzB;AAED,MAAM,WAAW,8BAA8B;IAC7C,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,SAAS,CAAC;CAClB;AAED,MAAM,WAAW,4BAA4B;IAC3C,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;CACf"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* KODA decoder worker. Runs in a Worker Thread; loads native addon or uses JS fallback.
|
|
3
|
+
* Receives binary buffer (transferable), decodes, posts result. Keeps main thread non-blocking.
|
|
4
|
+
*/
|
|
5
|
+
import { dirname, join } from 'node:path';
|
|
6
|
+
import { fileURLToPath } from 'node:url';
|
|
7
|
+
import { parentPort } from 'node:worker_threads';
|
|
8
|
+
import { decode as decodeJS } from '../decoder.js';
|
|
9
|
+
import { loadNative } from '../native.js';
|
|
10
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
11
|
+
const addonPath = join(__dirname, '..', '..', 'build', 'Release', 'koda_format.node');
|
|
12
|
+
let cachedNative = undefined;
|
|
13
|
+
function getNative() {
|
|
14
|
+
if (cachedNative !== undefined)
|
|
15
|
+
return cachedNative;
|
|
16
|
+
cachedNative = loadNative(import.meta.url, addonPath);
|
|
17
|
+
return cachedNative;
|
|
18
|
+
}
|
|
19
|
+
function doDecode(buffer, options) {
|
|
20
|
+
const buf = Buffer.from(buffer);
|
|
21
|
+
const binding = getNative();
|
|
22
|
+
if (binding) {
|
|
23
|
+
return binding.decode(buf, {
|
|
24
|
+
maxDepth: options?.maxDepth,
|
|
25
|
+
maxDictionarySize: options?.maxDictionarySize,
|
|
26
|
+
maxStringLength: options?.maxStringLength,
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
return decodeJS(new Uint8Array(buffer), options);
|
|
30
|
+
}
|
|
31
|
+
parentPort.on('message', (msg) => {
|
|
32
|
+
const { id, buffer, options } = msg;
|
|
33
|
+
try {
|
|
34
|
+
const value = doDecode(buffer, options);
|
|
35
|
+
parentPort.postMessage({ id, value });
|
|
36
|
+
}
|
|
37
|
+
catch (err) {
|
|
38
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
39
|
+
parentPort.postMessage({ id, error: message });
|
|
40
|
+
}
|
|
41
|
+
});
|
|
42
|
+
//# sourceMappingURL=decoder-worker.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"decoder-worker.js","sourceRoot":"","sources":["../../src/worker/decoder-worker.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAEjD,OAAO,EAAE,MAAM,IAAI,QAAQ,EAAE,MAAM,eAAe,CAAC;AAEnD,OAAO,EAAE,UAAU,EAAsB,MAAM,cAAc,CAAC;AAE9D,MAAM,SAAS,GAAG,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AAC1D,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,SAAS,EAAE,kBAAkB,CAAC,CAAC;AAEtF,IAAI,YAAY,GAAqC,SAAS,CAAC;AAE/D,SAAS,SAAS;IAChB,IAAI,YAAY,KAAK,SAAS;QAAE,OAAO,YAAY,CAAC;IACpD,YAAY,GAAG,UAAU,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC;IACtD,OAAO,YAAY,CAAC;AACtB,CAAC;AAkBD,SAAS,QAAQ,CAAC,MAAmB,EAAE,OAAuB;IAC5D,MAAM,GAAG,GAAG,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAChC,MAAM,OAAO,GAAG,SAAS,EAAE,CAAC;IAC5B,IAAI,OAAO,EAAE,CAAC;QACZ,OAAO,OAAO,CAAC,MAAM,CAAC,GAAG,EAAE;YACzB,QAAQ,EAAE,OAAO,EAAE,QAAQ;YAC3B,iBAAiB,EAAE,OAAO,EAAE,iBAAiB;YAC7C,eAAe,EAAE,OAAO,EAAE,eAAe;SAC1C,CAAc,CAAC;IAClB,CAAC;IACD,OAAO,QAAQ,CAAC,IAAI,UAAU,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC,CAAC;AACnD,CAAC;AAED,UAAW,CAAC,EAAE,CAAC,SAAS,EAAE,CAAC,GAA2B,EAAE,EAAE;IACxD,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG,GAAG,CAAC;IACpC,IAAI,CAAC;QACH,MAAM,KAAK,GAAG,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QAC5C,UAAW,CAAC,WAAW,CAAC,EAAE,EAAE,EAAE,KAAK,EAAoC,CAAC,CAAC;IACvE,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,OAAO,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QACjE,UAAW,CAAC,WAAW,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,OAAO,EAAkC,CAAC,CAAC;IAClF,CAAC;AACH,CAAC,CAAC,CAAC"}
|