@loradb/lora-node 0.5.6 → 0.8.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/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # lora-node
2
2
 
3
- Node.js / TypeScript bindings for the [Lora](../../README.md) graph
3
+ Node.js / TypeScript bindings for the [Lora](../../../README.md) graph
4
4
  engine. The package exposes a first-class typed API: query results are
5
5
  modelled as discriminated unions, temporal values carry `kind` tags, and the
6
6
  `Database` class is strongly typed in both directions (params and rows).
@@ -11,12 +11,12 @@ stays free for the full duration of a query — a 2 000-node MATCH happily
11
11
  interleaves with `setImmediate` ticks on the main thread (proven by a
12
12
  dedicated vitest).
13
13
 
14
- > **Status:** prototype / feasibility check. Not published to npm.
14
+ > **Package:** `@loradb/lora-node`.
15
15
 
16
16
  ## Install (local dev)
17
17
 
18
18
  ```bash
19
- cd crates/lora-node
19
+ cd crates/bindings/lora-node
20
20
  npm install
21
21
  npm run build # builds the Rust cdylib + TypeScript declarations
22
22
  npm test # runs the vitest suite
@@ -33,7 +33,7 @@ to `package.json`.
33
33
  `Database.create()` static; `Database` is a type-only export.
34
34
 
35
35
  ```ts
36
- import { createDatabase, isNode, type LoraNode } from "lora-node";
36
+ import { createDatabase, isNode, type LoraNode } from "@loradb/lora-node";
37
37
 
38
38
  const db = await createDatabase(); // in-memory by default
39
39
  await db.execute("CREATE (:Person {name: $n, age: $a})", { n: "Alice", a: 30 });
@@ -46,10 +46,42 @@ for (const row of res.rows) {
46
46
  }
47
47
  ```
48
48
 
49
+ ### Explain & Profile
50
+
51
+ `db.explain()` and `db.profile()` are first-class methods alongside
52
+ `db.execute()`. They are intentionally *separate calls*, not a flag on
53
+ `execute()`, so you have to opt in explicitly to plan inspection or
54
+ metrics collection.
55
+
56
+ ```ts
57
+ const plan = await db.explain(
58
+ "MATCH (p:Person) WHERE p.name = $name RETURN p",
59
+ { name: "Alice" },
60
+ );
61
+ console.log(plan.shape); // "readOnly"
62
+ console.log(plan.tree.operator); // top-most operator label
63
+
64
+ const profile = await db.profile(
65
+ "MATCH (p:Person) WHERE p.name = $name RETURN p",
66
+ { name: "Alice" },
67
+ );
68
+ console.log(profile.metrics.totalElapsedNs);
69
+ console.log(profile.metrics.perOperator);
70
+ ```
71
+
72
+ `explain()` never invokes the executor — calling it on a mutating
73
+ query (`CREATE`, `MERGE`, `SET`, `DELETE`, `REMOVE`) leaves the graph
74
+ untouched.
75
+
76
+ > **`profile()` executes the query for real.** Mutating queries
77
+ > produce the same side effects as `execute()`: the WAL is written,
78
+ > snapshots observe the commit, and the live store advances. Use
79
+ > `explain()` to inspect a mutating plan without running it.
80
+
49
81
  The initialization rule is:
50
82
 
51
83
  ```ts
52
- import { createDatabase } from "lora-node";
84
+ import { createDatabase } from "@loradb/lora-node";
53
85
 
54
86
  const inMemory = await createDatabase(); // in-memory only
55
87
  const defaultPersistent = await createDatabase("app"); // ./app.loradb
@@ -70,7 +102,7 @@ copying the portable `.loradb` archive while the database is still open.
70
102
  Node also has an archive-backed convenience overload:
71
103
 
72
104
  ```ts
73
- import { createDatabase } from "lora-node";
105
+ import { createDatabase } from "@loradb/lora-node";
74
106
 
75
107
  const db = await createDatabase("app", { databaseDir: "./data" });
76
108
  ```
@@ -86,12 +118,30 @@ single live native engine. Call `db.dispose()` when you need to release a handle
86
118
  eagerly; cross-process opens of the same archive are blocked to prevent
87
119
  split-brain writers.
88
120
 
121
+ For explicit WAL directories with managed snapshots, use `openWalDatabase`:
122
+
123
+ ```ts
124
+ import { openWalDatabase } from "@loradb/lora-node";
125
+
126
+ const db = await openWalDatabase({
127
+ walDir: "./data/wal",
128
+ snapshotDir: "./data/snapshots",
129
+ snapshotEveryCommits: 1000,
130
+ snapshotKeepOld: 2,
131
+ });
132
+ ```
133
+
134
+ `snapshotOptions` accepts the same compression/encryption options as
135
+ `saveSnapshot`.
136
+
89
137
  ## Snapshots
90
138
 
91
- `saveSnapshot(path)` writes the current graph to a local file. It also accepts
92
- typed formats: `"binary"` returns a Node `Buffer`, `"base64"` returns base64
93
- text, and `{ format: "path", path }` accepts either a path string or `file:`
94
- URL.
139
+ `saveSnapshot(path)` writes the current graph to a local file. Plain strings
140
+ are always treated as paths. Calling `saveSnapshot()` returns a Node `Buffer`;
141
+ object formats such as `{ format: "base64" }`, `{ format: "arrayBuffer" }`,
142
+ `{ format: "uint8Array" }`, and `{ format: "stream" }` return in-memory
143
+ snapshot data in that shape. `{ format: "path", path }` accepts either a path
144
+ string or `file:` URL.
95
145
 
96
146
  `loadSnapshot` accepts a `NodeSnapshotSource`: a filesystem path, `file:` URL,
97
147
  HTTP(S) or `data:` URL, `Buffer`, `Uint8Array`, `ArrayBuffer`, Node
@@ -101,25 +151,24 @@ HTTP(S) or `data:` URL, `Buffer`, `Uint8Array`, `ArrayBuffer`, Node
101
151
  import { readFile } from "node:fs/promises";
102
152
  import { createReadStream } from "node:fs";
103
153
  import { pathToFileURL } from "node:url";
104
- import { createDatabase } from "lora-node";
154
+ import { createDatabase } from "@loradb/lora-node";
105
155
 
106
156
  const db = await createDatabase();
107
157
  await db.execute("CREATE (:Person {name: 'Alice'})");
108
158
  await db.saveSnapshot("./graph.lorasnap");
109
- const bytes = await db.saveSnapshot("binary");
159
+ const bytes = await db.saveSnapshot();
110
160
  const base64 = await db.saveSnapshot({ format: "base64" });
161
+ const stream = await db.saveSnapshot({ format: "stream" });
111
162
 
112
163
  await db.loadSnapshot("./graph.lorasnap");
113
164
  await db.loadSnapshot(pathToFileURL("./graph.lorasnap"));
114
165
  await db.loadSnapshot(await readFile("./graph.lorasnap"));
115
166
  await db.loadSnapshot(createReadStream("./graph.lorasnap"));
116
167
  await db.loadSnapshot(bytes);
168
+ await db.loadSnapshot(stream);
117
169
  await db.loadSnapshot(new URL("https://example.com/graph.lorasnap"));
118
170
  ```
119
171
 
120
- Use `loadSnapshotFromBytes(bytes)` when you already have in-memory bytes and
121
- want to make that intent explicit.
122
-
123
172
  ## Typed value model
124
173
 
125
174
  | TS type | Runtime shape |
@@ -147,7 +196,7 @@ narrowing guards (`isNode`, `isRelationship`, `isPath`, `isPoint`, `isTemporal`)
147
196
  are exported from `lora-node`.
148
197
 
149
198
  > `distance()` on WGS-84-3D points ignores `height` — see
150
- > [functions reference](../../apps/loradb.com/docs/functions/overview.md) for the full spatial
199
+ > [functions reference](../../../apps/loradb.com/docs/functions/overview.md) for the full spatial
151
200
  > reference and known limitations.
152
201
 
153
202
  ## Architecture
@@ -156,7 +205,7 @@ are exported from `lora-node`.
156
205
  lora-database (Rust)
157
206
  └── lora-node (crate, cdylib) <- napi-rs bindings, AsyncTask
158
207
  └── ts/index.ts <- strongly-typed async wrapper
159
- └── ../shared-ts/types.ts <- shared TS contract (with lora-wasm)
208
+ └── ../shared-ts/types.ts <- shared TS contract (with lora-wasm)
160
209
  ```
161
210
 
162
211
  Query execution path:
@@ -179,10 +228,22 @@ identical to `lora-wasm`.
179
228
 
180
229
  ## Errors
181
230
 
182
- `db.execute(...)` throws `LoraError` with a narrowed `code`:
231
+ `db.execute(...)` throws `LoraError` with a narrowed `code` from the
232
+ `LoraErrorCode` union — these mirror `lora_database::LoraErrorCode` 1:1.
233
+
234
+ Common ones:
235
+
236
+ - `LORA_PARSE` — Cypher syntax could not be parsed
237
+ - `LORA_SEMANTIC` — analysis failure (unknown variable, label, type mismatch, …)
238
+ - `LORA_INVALID_PARAMS` — a parameter value could not be coerced to a `LoraValue`
239
+ - `LORA_INVALID_VECTOR` — vector value failed dimension / coordinate-type validation
240
+ - `LORA_TIMEOUT` — query exceeded its cooperative deadline
241
+ - `LORA_DATABASE_NAME` — logical database name violates the portable-path rules
242
+ - `LORA_IO`, `LORA_WAL_CORRUPTION`, `LORA_WAL_POISONED` — storage failures
243
+ - `LORA_SNAPSHOT_CODEC`, `LORA_SNAPSHOT_CRYPTO` — snapshot codec / crypto failures
244
+ - `LORA_INTERNAL` — last-resort fallback when the engine cannot classify the failure
183
245
 
184
- - `LORA_ERROR` — parse / analyze / execute failure
185
- - `INVALID_PARAMS` — a param value could not be mapped to a `LoraValue`
246
+ See `ts/types.ts` (`LoraErrorCode`) for the full list.
186
247
 
187
248
  ## Known limitations
188
249
 
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Decoder for the binary result format produced by the native side.
3
+ *
4
+ * The native `execute()` ships a single `Uint8Array` whose layout is
5
+ * defined by `crates/bindings/lora-binding-buffer/src/lib.rs`. This
6
+ * file is the sole reader; it must stay byte-compatible with the
7
+ * encoder there.
8
+ *
9
+ * Why this exists: each FFI syscall costs ~150 ns; for a 10 000-row
10
+ * scan, the per-cell loop takes thousands of crossings and dominates
11
+ * wall-clock time. Transferring the whole result as one buffer and
12
+ * decoding it in JIT'd JavaScript is materially faster — V8 walks
13
+ * contiguous bytes far more cheaply than the FFI layer can hand
14
+ * values across one at a time.
15
+ *
16
+ * Shared between the `lora-node` and `lora-wasm` bindings; the source
17
+ * of truth lives in `crates/bindings/shared-ts/decode.ts` and is
18
+ * synced into each binding's `ts/` by their `npm run sync:types`
19
+ * script (mirrors how `types.ts` is shared).
20
+ */
21
+ /**
22
+ * Decode the wire format produced by `encode_rows` in the native crate
23
+ * into the public `{ columns, rows }` shape.
24
+ */
25
+ export declare function decodeResult(buf: Uint8Array): {
26
+ columns: string[];
27
+ rows: Array<Record<string, any>>;
28
+ };
29
+ //# sourceMappingURL=decode.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"decode.d.ts","sourceRoot":"","sources":["../ts/decode.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAsTH;;;GAGG;AACH,wBAAgB,YAAY,CAC1B,GAAG,EAAE,UAAU,GACd;IAAE,OAAO,EAAE,MAAM,EAAE,CAAC;IAAC,IAAI,EAAE,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,CAAA;CAAE,CA4BzD"}
package/dist/decode.js ADDED
@@ -0,0 +1,341 @@
1
+ "use strict";
2
+ /**
3
+ * Decoder for the binary result format produced by the native side.
4
+ *
5
+ * The native `execute()` ships a single `Uint8Array` whose layout is
6
+ * defined by `crates/bindings/lora-binding-buffer/src/lib.rs`. This
7
+ * file is the sole reader; it must stay byte-compatible with the
8
+ * encoder there.
9
+ *
10
+ * Why this exists: each FFI syscall costs ~150 ns; for a 10 000-row
11
+ * scan, the per-cell loop takes thousands of crossings and dominates
12
+ * wall-clock time. Transferring the whole result as one buffer and
13
+ * decoding it in JIT'd JavaScript is materially faster — V8 walks
14
+ * contiguous bytes far more cheaply than the FFI layer can hand
15
+ * values across one at a time.
16
+ *
17
+ * Shared between the `lora-node` and `lora-wasm` bindings; the source
18
+ * of truth lives in `crates/bindings/shared-ts/decode.ts` and is
19
+ * synced into each binding's `ts/` by their `npm run sync:types`
20
+ * script (mirrors how `types.ts` is shared).
21
+ */
22
+ /* eslint-disable @typescript-eslint/no-explicit-any */
23
+ Object.defineProperty(exports, "__esModule", { value: true });
24
+ exports.decodeResult = decodeResult;
25
+ const MAGIC_0 = 0x4c; // L
26
+ const MAGIC_1 = 0x52; // R
27
+ const MAGIC_2 = 0x31; // 1
28
+ const MAGIC_3 = 0x00;
29
+ // Cell tags — keep in sync with `tag::` constants in encode.rs.
30
+ const TAG_NULL = 0x00;
31
+ const TAG_FALSE = 0x01;
32
+ const TAG_TRUE = 0x02;
33
+ const TAG_I32 = 0x03;
34
+ const TAG_I64 = 0x04;
35
+ const TAG_F64 = 0x05;
36
+ const TAG_STRING = 0x06;
37
+ const TAG_LIST = 0x07;
38
+ const TAG_MAP = 0x08;
39
+ const TAG_NODE = 0x09;
40
+ const TAG_RELATIONSHIP = 0x0a;
41
+ const TAG_PATH = 0x0b;
42
+ const TAG_DATE = 0x0c;
43
+ const TAG_TIME = 0x0d;
44
+ const TAG_LOCAL_TIME = 0x0e;
45
+ const TAG_DATETIME = 0x0f;
46
+ const TAG_LOCAL_DATETIME = 0x10;
47
+ const TAG_DURATION = 0x11;
48
+ const TAG_POINT = 0x12;
49
+ const TAG_VECTOR = 0x13;
50
+ const TAG_BINARY = 0x14;
51
+ const VECTOR_FLOAT64 = 0;
52
+ const VECTOR_FLOAT32 = 1;
53
+ const VECTOR_INT64 = 2;
54
+ const VECTOR_INT32 = 3;
55
+ const VECTOR_INT16 = 4;
56
+ const VECTOR_INT8 = 5;
57
+ const SRID_CARTESIAN_2D = 7203;
58
+ const SRID_CARTESIAN_3D = 9157;
59
+ const SRID_WGS84_2D = 4326;
60
+ const SRID_WGS84_3D = 4979;
61
+ function sridToCrs(srid) {
62
+ switch (srid) {
63
+ case SRID_CARTESIAN_2D:
64
+ return "cartesian";
65
+ case SRID_CARTESIAN_3D:
66
+ return "cartesian-3D";
67
+ case SRID_WGS84_2D:
68
+ return "WGS-84-2D";
69
+ case SRID_WGS84_3D:
70
+ return "WGS-84-3D";
71
+ default:
72
+ return "cartesian";
73
+ }
74
+ }
75
+ const utf8 = new TextDecoder("utf-8");
76
+ class Reader {
77
+ view;
78
+ bytes;
79
+ off = 0;
80
+ constructor(buf) {
81
+ this.bytes = buf;
82
+ this.view = new DataView(buf.buffer, buf.byteOffset, buf.byteLength);
83
+ }
84
+ u8() {
85
+ // `noUncheckedIndexedAccess` says this might be undefined; we
86
+ // never read past the buffer because the encoder writes a
87
+ // bounded layout. The hot path can't afford a check.
88
+ return this.bytes[this.off++];
89
+ }
90
+ u32() {
91
+ const v = this.view.getUint32(this.off, true);
92
+ this.off += 4;
93
+ return v;
94
+ }
95
+ i32() {
96
+ const v = this.view.getInt32(this.off, true);
97
+ this.off += 4;
98
+ return v;
99
+ }
100
+ /**
101
+ * Reads an i64 LE and returns it as a JS Number. Values outside the
102
+ * `Number.MAX_SAFE_INTEGER` range silently lose precision — same
103
+ * behaviour the binding has always had on the read path. Callers that
104
+ * need exact representation of large ints should use a separate
105
+ * binding-side path; this is a hot loop.
106
+ */
107
+ i64AsNumber() {
108
+ // Two getInt32 calls beat getBigInt64 + Number(BigInt) by ~3× in V8.
109
+ // Manual reconstruction is exact for the |x| < 2^53 range.
110
+ const lo = this.view.getUint32(this.off, true);
111
+ const hi = this.view.getInt32(this.off + 4, true);
112
+ this.off += 8;
113
+ return hi * 0x1_0000_0000 + lo;
114
+ }
115
+ f64() {
116
+ const v = this.view.getFloat64(this.off, true);
117
+ this.off += 8;
118
+ return v;
119
+ }
120
+ str() {
121
+ const len = this.u32();
122
+ const start = this.off;
123
+ this.off += len;
124
+ if (len === 0)
125
+ return "";
126
+ // TextDecoder is a fused C++ path in V8; faster than Buffer.toString
127
+ // for short-to-medium strings and avoids hitting Buffer's own
128
+ // string-cache layer.
129
+ return utf8.decode(this.bytes.subarray(start, this.off));
130
+ }
131
+ }
132
+ function readValue(r) {
133
+ const tag = r.u8();
134
+ switch (tag) {
135
+ case TAG_NULL:
136
+ return null;
137
+ case TAG_FALSE:
138
+ return false;
139
+ case TAG_TRUE:
140
+ return true;
141
+ case TAG_I32:
142
+ return r.i32();
143
+ case TAG_I64:
144
+ return r.i64AsNumber();
145
+ case TAG_F64:
146
+ return r.f64();
147
+ case TAG_STRING:
148
+ return r.str();
149
+ case TAG_LIST: {
150
+ const n = r.u32();
151
+ const arr = new Array(n);
152
+ for (let i = 0; i < n; i++)
153
+ arr[i] = readValue(r);
154
+ return arr;
155
+ }
156
+ case TAG_MAP: {
157
+ const n = r.u32();
158
+ const obj = {};
159
+ for (let i = 0; i < n; i++) {
160
+ const k = r.str();
161
+ obj[k] = readValue(r);
162
+ }
163
+ return obj;
164
+ }
165
+ case TAG_NODE:
166
+ return {
167
+ kind: "node",
168
+ id: r.i64AsNumber(),
169
+ labels: [],
170
+ properties: {},
171
+ };
172
+ case TAG_RELATIONSHIP:
173
+ return { kind: "relationship", id: r.i64AsNumber() };
174
+ case TAG_PATH: {
175
+ const nN = r.u32();
176
+ const nodes = new Array(nN);
177
+ for (let i = 0; i < nN; i++)
178
+ nodes[i] = r.i64AsNumber();
179
+ const nR = r.u32();
180
+ const rels = new Array(nR);
181
+ for (let i = 0; i < nR; i++)
182
+ rels[i] = r.i64AsNumber();
183
+ return { kind: "path", nodes, rels };
184
+ }
185
+ case TAG_DATE:
186
+ return { kind: "date", iso: r.str() };
187
+ case TAG_TIME:
188
+ return { kind: "time", iso: r.str() };
189
+ case TAG_LOCAL_TIME:
190
+ return { kind: "localtime", iso: r.str() };
191
+ case TAG_DATETIME:
192
+ return { kind: "datetime", iso: r.str() };
193
+ case TAG_LOCAL_DATETIME:
194
+ return { kind: "localdatetime", iso: r.str() };
195
+ case TAG_DURATION:
196
+ return { kind: "duration", iso: r.str() };
197
+ case TAG_POINT: {
198
+ const hasZ = r.u8();
199
+ const srid = r.u32();
200
+ const x = r.f64();
201
+ const y = r.f64();
202
+ const point = {
203
+ kind: "point",
204
+ srid,
205
+ crs: sridToCrs(srid),
206
+ x,
207
+ y,
208
+ };
209
+ if (hasZ)
210
+ point.z = r.f64();
211
+ if (srid === SRID_WGS84_2D || srid === SRID_WGS84_3D) {
212
+ point.longitude = x;
213
+ point.latitude = y;
214
+ if (hasZ)
215
+ point.height = point.z;
216
+ }
217
+ return point;
218
+ }
219
+ case TAG_VECTOR:
220
+ return readVector(r);
221
+ case TAG_BINARY:
222
+ return readBinary(r);
223
+ default:
224
+ throw new Error(`unknown LoraValue tag: 0x${tag.toString(16)}`);
225
+ }
226
+ }
227
+ function readVector(r) {
228
+ const coordTag = r.u8();
229
+ const dim = r.u32();
230
+ const values = new Array(dim);
231
+ let coordinateType;
232
+ switch (coordTag) {
233
+ case VECTOR_FLOAT64:
234
+ coordinateType = "FLOAT64";
235
+ for (let i = 0; i < dim; i++)
236
+ values[i] = r.f64();
237
+ break;
238
+ case VECTOR_FLOAT32:
239
+ coordinateType = "FLOAT32";
240
+ for (let i = 0; i < dim; i++) {
241
+ values[i] = r.view.getFloat32(r.off, true);
242
+ r.off += 4;
243
+ }
244
+ break;
245
+ case VECTOR_INT64:
246
+ coordinateType = "INTEGER";
247
+ for (let i = 0; i < dim; i++)
248
+ values[i] = r.i64AsNumber();
249
+ break;
250
+ case VECTOR_INT32:
251
+ coordinateType = "INTEGER32";
252
+ for (let i = 0; i < dim; i++)
253
+ values[i] = r.i32();
254
+ break;
255
+ case VECTOR_INT16:
256
+ coordinateType = "INTEGER16";
257
+ for (let i = 0; i < dim; i++) {
258
+ values[i] = r.view.getInt16(r.off, true);
259
+ r.off += 2;
260
+ }
261
+ break;
262
+ case VECTOR_INT8:
263
+ coordinateType = "INTEGER8";
264
+ for (let i = 0; i < dim; i++) {
265
+ values[i] = r.view.getInt8(r.off);
266
+ r.off += 1;
267
+ }
268
+ break;
269
+ default:
270
+ throw new Error(`unknown vector coord type: ${coordTag}`);
271
+ }
272
+ return { kind: "vector", dimension: dim, coordinateType, values };
273
+ }
274
+ function readBinary(r) {
275
+ const segCount = r.u32();
276
+ const segments = new Array(segCount);
277
+ let total = 0;
278
+ for (let i = 0; i < segCount; i++) {
279
+ const len = r.u32();
280
+ const seg = new Array(len);
281
+ for (let j = 0; j < len; j++)
282
+ seg[j] = r.bytes[r.off + j];
283
+ r.off += len;
284
+ segments[i] = seg;
285
+ total += len;
286
+ }
287
+ return { kind: "binary", length: total, segments };
288
+ }
289
+ const factoryCache = new Map();
290
+ function rowFactory(columns) {
291
+ const key = columns.join("\x1f");
292
+ let factory = factoryCache.get(key);
293
+ if (factory)
294
+ return factory;
295
+ // Build:
296
+ // function (read, r) {
297
+ // const row = {};
298
+ // row[colA] = read(r);
299
+ // row[colB] = read(r);
300
+ // return row;
301
+ // }
302
+ const lines = ["const row = {};"];
303
+ for (const col of columns) {
304
+ lines.push(`row[${JSON.stringify(col)}] = read(r);`);
305
+ }
306
+ lines.push("return row;");
307
+ factory = new Function("read", "r", lines.join("\n"));
308
+ factoryCache.set(key, factory);
309
+ return factory;
310
+ }
311
+ /**
312
+ * Decode the wire format produced by `encode_rows` in the native crate
313
+ * into the public `{ columns, rows }` shape.
314
+ */
315
+ function decodeResult(buf) {
316
+ const r = new Reader(buf);
317
+ if (r.bytes[0] !== MAGIC_0 ||
318
+ r.bytes[1] !== MAGIC_1 ||
319
+ r.bytes[2] !== MAGIC_2 ||
320
+ r.bytes[3] !== MAGIC_3) {
321
+ throw new Error("lora-node: invalid result buffer magic");
322
+ }
323
+ r.off = 4;
324
+ const colCount = r.u32();
325
+ const columns = new Array(colCount);
326
+ for (let i = 0; i < colCount; i++)
327
+ columns[i] = r.str();
328
+ const rowCount = r.u32();
329
+ const rows = new Array(rowCount);
330
+ if (colCount === 0) {
331
+ for (let i = 0; i < rowCount; i++)
332
+ rows[i] = {};
333
+ return { columns, rows };
334
+ }
335
+ const factory = rowFactory(columns);
336
+ for (let i = 0; i < rowCount; i++) {
337
+ rows[i] = factory(readValue, r);
338
+ }
339
+ return { columns, rows };
340
+ }
341
+ //# sourceMappingURL=decode.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"decode.js","sourceRoot":"","sources":["../ts/decode.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AACH,uDAAuD;;AAyTvD,oCA8BC;AArVD,MAAM,OAAO,GAAG,IAAI,CAAC,CAAC,IAAI;AAC1B,MAAM,OAAO,GAAG,IAAI,CAAC,CAAC,IAAI;AAC1B,MAAM,OAAO,GAAG,IAAI,CAAC,CAAC,IAAI;AAC1B,MAAM,OAAO,GAAG,IAAI,CAAC;AAErB,gEAAgE;AAChE,MAAM,QAAQ,GAAG,IAAI,CAAC;AACtB,MAAM,SAAS,GAAG,IAAI,CAAC;AACvB,MAAM,QAAQ,GAAG,IAAI,CAAC;AACtB,MAAM,OAAO,GAAG,IAAI,CAAC;AACrB,MAAM,OAAO,GAAG,IAAI,CAAC;AACrB,MAAM,OAAO,GAAG,IAAI,CAAC;AACrB,MAAM,UAAU,GAAG,IAAI,CAAC;AACxB,MAAM,QAAQ,GAAG,IAAI,CAAC;AACtB,MAAM,OAAO,GAAG,IAAI,CAAC;AACrB,MAAM,QAAQ,GAAG,IAAI,CAAC;AACtB,MAAM,gBAAgB,GAAG,IAAI,CAAC;AAC9B,MAAM,QAAQ,GAAG,IAAI,CAAC;AACtB,MAAM,QAAQ,GAAG,IAAI,CAAC;AACtB,MAAM,QAAQ,GAAG,IAAI,CAAC;AACtB,MAAM,cAAc,GAAG,IAAI,CAAC;AAC5B,MAAM,YAAY,GAAG,IAAI,CAAC;AAC1B,MAAM,kBAAkB,GAAG,IAAI,CAAC;AAChC,MAAM,YAAY,GAAG,IAAI,CAAC;AAC1B,MAAM,SAAS,GAAG,IAAI,CAAC;AACvB,MAAM,UAAU,GAAG,IAAI,CAAC;AACxB,MAAM,UAAU,GAAG,IAAI,CAAC;AAExB,MAAM,cAAc,GAAG,CAAC,CAAC;AACzB,MAAM,cAAc,GAAG,CAAC,CAAC;AACzB,MAAM,YAAY,GAAG,CAAC,CAAC;AACvB,MAAM,YAAY,GAAG,CAAC,CAAC;AACvB,MAAM,YAAY,GAAG,CAAC,CAAC;AACvB,MAAM,WAAW,GAAG,CAAC,CAAC;AAEtB,MAAM,iBAAiB,GAAG,IAAI,CAAC;AAC/B,MAAM,iBAAiB,GAAG,IAAI,CAAC;AAC/B,MAAM,aAAa,GAAG,IAAI,CAAC;AAC3B,MAAM,aAAa,GAAG,IAAI,CAAC;AAE3B,SAAS,SAAS,CAAC,IAAY;IAC7B,QAAQ,IAAI,EAAE,CAAC;QACb,KAAK,iBAAiB;YACpB,OAAO,WAAW,CAAC;QACrB,KAAK,iBAAiB;YACpB,OAAO,cAAc,CAAC;QACxB,KAAK,aAAa;YAChB,OAAO,WAAW,CAAC;QACrB,KAAK,aAAa;YAChB,OAAO,WAAW,CAAC;QACrB;YACE,OAAO,WAAW,CAAC;IACvB,CAAC;AACH,CAAC;AAED,MAAM,IAAI,GAAG,IAAI,WAAW,CAAC,OAAO,CAAC,CAAC;AAEtC,MAAM,MAAM;IACD,IAAI,CAAW;IACf,KAAK,CAAa;IAC3B,GAAG,GAAG,CAAC,CAAC;IAER,YAAY,GAAe;QACzB,IAAI,CAAC,KAAK,GAAG,GAAG,CAAC;QACjB,IAAI,CAAC,IAAI,GAAG,IAAI,QAAQ,CAAC,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,UAAU,EAAE,GAAG,CAAC,UAAU,CAAC,CAAC;IACvE,CAAC;IAED,EAAE;QACA,8DAA8D;QAC9D,0DAA0D;QAC1D,qDAAqD;QACrD,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,CAAE,CAAC;IACjC,CAAC;IAED,GAAG;QACD,MAAM,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;QAC9C,IAAI,CAAC,GAAG,IAAI,CAAC,CAAC;QACd,OAAO,CAAC,CAAC;IACX,CAAC;IAED,GAAG;QACD,MAAM,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;QAC7C,IAAI,CAAC,GAAG,IAAI,CAAC,CAAC;QACd,OAAO,CAAC,CAAC;IACX,CAAC;IAED;;;;;;OAMG;IACH,WAAW;QACT,qEAAqE;QACrE,2DAA2D;QAC3D,MAAM,EAAE,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;QAC/C,MAAM,EAAE,GAAG,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,GAAG,GAAG,CAAC,EAAE,IAAI,CAAC,CAAC;QAClD,IAAI,CAAC,GAAG,IAAI,CAAC,CAAC;QACd,OAAO,EAAE,GAAG,aAAa,GAAG,EAAE,CAAC;IACjC,CAAC;IAED,GAAG;QACD,MAAM,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;QAC/C,IAAI,CAAC,GAAG,IAAI,CAAC,CAAC;QACd,OAAO,CAAC,CAAC;IACX,CAAC;IAED,GAAG;QACD,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACvB,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC;QACvB,IAAI,CAAC,GAAG,IAAI,GAAG,CAAC;QAChB,IAAI,GAAG,KAAK,CAAC;YAAE,OAAO,EAAE,CAAC;QACzB,qEAAqE;QACrE,8DAA8D;QAC9D,sBAAsB;QACtB,OAAO,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,KAAK,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;IAC3D,CAAC;CACF;AAED,SAAS,SAAS,CAAC,CAAS;IAC1B,MAAM,GAAG,GAAG,CAAC,CAAC,EAAE,EAAE,CAAC;IACnB,QAAQ,GAAG,EAAE,CAAC;QACZ,KAAK,QAAQ;YACX,OAAO,IAAI,CAAC;QACd,KAAK,SAAS;YACZ,OAAO,KAAK,CAAC;QACf,KAAK,QAAQ;YACX,OAAO,IAAI,CAAC;QACd,KAAK,OAAO;YACV,OAAO,CAAC,CAAC,GAAG,EAAE,CAAC;QACjB,KAAK,OAAO;YACV,OAAO,CAAC,CAAC,WAAW,EAAE,CAAC;QACzB,KAAK,OAAO;YACV,OAAO,CAAC,CAAC,GAAG,EAAE,CAAC;QACjB,KAAK,UAAU;YACb,OAAO,CAAC,CAAC,GAAG,EAAE,CAAC;QACjB,KAAK,QAAQ,CAAC,CAAC,CAAC;YACd,MAAM,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,CAAC;YAClB,MAAM,GAAG,GAAG,IAAI,KAAK,CAAC,CAAC,CAAC,CAAC;YACzB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE;gBAAE,GAAG,CAAC,CAAC,CAAC,GAAG,SAAS,CAAC,CAAC,CAAC,CAAC;YAClD,OAAO,GAAG,CAAC;QACb,CAAC;QACD,KAAK,OAAO,CAAC,CAAC,CAAC;YACb,MAAM,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,CAAC;YAClB,MAAM,GAAG,GAAwB,EAAE,CAAC;YACpC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;gBAC3B,MAAM,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,CAAC;gBAClB,GAAG,CAAC,CAAC,CAAC,GAAG,SAAS,CAAC,CAAC,CAAC,CAAC;YACxB,CAAC;YACD,OAAO,GAAG,CAAC;QACb,CAAC;QACD,KAAK,QAAQ;YACX,OAAO;gBACL,IAAI,EAAE,MAAM;gBACZ,EAAE,EAAE,CAAC,CAAC,WAAW,EAAE;gBACnB,MAAM,EAAE,EAAE;gBACV,UAAU,EAAE,EAAE;aACf,CAAC;QACJ,KAAK,gBAAgB;YACnB,OAAO,EAAE,IAAI,EAAE,cAAc,EAAE,EAAE,EAAE,CAAC,CAAC,WAAW,EAAE,EAAE,CAAC;QACvD,KAAK,QAAQ,CAAC,CAAC,CAAC;YACd,MAAM,EAAE,GAAG,CAAC,CAAC,GAAG,EAAE,CAAC;YACnB,MAAM,KAAK,GAAG,IAAI,KAAK,CAAS,EAAE,CAAC,CAAC;YACpC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,EAAE;gBAAE,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,WAAW,EAAE,CAAC;YACxD,MAAM,EAAE,GAAG,CAAC,CAAC,GAAG,EAAE,CAAC;YACnB,MAAM,IAAI,GAAG,IAAI,KAAK,CAAS,EAAE,CAAC,CAAC;YACnC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,EAAE;gBAAE,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,WAAW,EAAE,CAAC;YACvD,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;QACvC,CAAC;QACD,KAAK,QAAQ;YACX,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC;QACxC,KAAK,QAAQ;YACX,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC;QACxC,KAAK,cAAc;YACjB,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,GAAG,EAAE,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC;QAC7C,KAAK,YAAY;YACf,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,GAAG,EAAE,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC;QAC5C,KAAK,kBAAkB;YACrB,OAAO,EAAE,IAAI,EAAE,eAAe,EAAE,GAAG,EAAE,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC;QACjD,KAAK,YAAY;YACf,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,GAAG,EAAE,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC;QAC5C,KAAK,SAAS,CAAC,CAAC,CAAC;YACf,MAAM,IAAI,GAAG,CAAC,CAAC,EAAE,EAAE,CAAC;YACpB,MAAM,IAAI,GAAG,CAAC,CAAC,GAAG,EAAE,CAAC;YACrB,MAAM,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,CAAC;YAClB,MAAM,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,CAAC;YAClB,MAAM,KAAK,GAAwB;gBACjC,IAAI,EAAE,OAAO;gBACb,IAAI;gBACJ,GAAG,EAAE,SAAS,CAAC,IAAI,CAAC;gBACpB,CAAC;gBACD,CAAC;aACF,CAAC;YACF,IAAI,IAAI;gBAAE,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,CAAC;YAC5B,IAAI,IAAI,KAAK,aAAa,IAAI,IAAI,KAAK,aAAa,EAAE,CAAC;gBACrD,KAAK,CAAC,SAAS,GAAG,CAAC,CAAC;gBACpB,KAAK,CAAC,QAAQ,GAAG,CAAC,CAAC;gBACnB,IAAI,IAAI;oBAAE,KAAK,CAAC,MAAM,GAAG,KAAK,CAAC,CAAC,CAAC;YACnC,CAAC;YACD,OAAO,KAAK,CAAC;QACf,CAAC;QACD,KAAK,UAAU;YACb,OAAO,UAAU,CAAC,CAAC,CAAC,CAAC;QACvB,KAAK,UAAU;YACb,OAAO,UAAU,CAAC,CAAC,CAAC,CAAC;QACvB;YACE,MAAM,IAAI,KAAK,CAAC,4BAA4B,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;IACpE,CAAC;AACH,CAAC;AAED,SAAS,UAAU,CAAC,CAAS;IAC3B,MAAM,QAAQ,GAAG,CAAC,CAAC,EAAE,EAAE,CAAC;IACxB,MAAM,GAAG,GAAG,CAAC,CAAC,GAAG,EAAE,CAAC;IACpB,MAAM,MAAM,GAAG,IAAI,KAAK,CAAS,GAAG,CAAC,CAAC;IACtC,IAAI,cAAsB,CAAC;IAC3B,QAAQ,QAAQ,EAAE,CAAC;QACjB,KAAK,cAAc;YACjB,cAAc,GAAG,SAAS,CAAC;YAC3B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,GAAG,EAAE,CAAC,EAAE;gBAAE,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,CAAC;YAClD,MAAM;QACR,KAAK,cAAc;YACjB,cAAc,GAAG,SAAS,CAAC;YAC3B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC;gBAC7B,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;gBAC3C,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;YACb,CAAC;YACD,MAAM;QACR,KAAK,YAAY;YACf,cAAc,GAAG,SAAS,CAAC;YAC3B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,GAAG,EAAE,CAAC,EAAE;gBAAE,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,WAAW,EAAE,CAAC;YAC1D,MAAM;QACR,KAAK,YAAY;YACf,cAAc,GAAG,WAAW,CAAC;YAC7B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,GAAG,EAAE,CAAC,EAAE;gBAAE,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,CAAC;YAClD,MAAM;QACR,KAAK,YAAY;YACf,cAAc,GAAG,WAAW,CAAC;YAC7B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC;gBAC7B,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;gBACzC,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;YACb,CAAC;YACD,MAAM;QACR,KAAK,WAAW;YACd,cAAc,GAAG,UAAU,CAAC;YAC5B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC;gBAC7B,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;gBAClC,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;YACb,CAAC;YACD,MAAM;QACR;YACE,MAAM,IAAI,KAAK,CAAC,8BAA8B,QAAQ,EAAE,CAAC,CAAC;IAC9D,CAAC;IACD,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,SAAS,EAAE,GAAG,EAAE,cAAc,EAAE,MAAM,EAAE,CAAC;AACpE,CAAC;AAED,SAAS,UAAU,CAAC,CAAS;IAC3B,MAAM,QAAQ,GAAG,CAAC,CAAC,GAAG,EAAE,CAAC;IACzB,MAAM,QAAQ,GAAG,IAAI,KAAK,CAAW,QAAQ,CAAC,CAAC;IAC/C,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,QAAQ,EAAE,CAAC,EAAE,EAAE,CAAC;QAClC,MAAM,GAAG,GAAG,CAAC,CAAC,GAAG,EAAE,CAAC;QACpB,MAAM,GAAG,GAAG,IAAI,KAAK,CAAS,GAAG,CAAC,CAAC;QACnC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,GAAG,EAAE,CAAC,EAAE;YAAE,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAE,CAAC;QAC3D,CAAC,CAAC,GAAG,IAAI,GAAG,CAAC;QACb,QAAQ,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC;QAClB,KAAK,IAAI,GAAG,CAAC;IACf,CAAC;IACD,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC;AACrD,CAAC;AAeD,MAAM,YAAY,GAAG,IAAI,GAAG,EAAsB,CAAC;AAEnD,SAAS,UAAU,CAAC,OAA0B;IAC5C,MAAM,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IACjC,IAAI,OAAO,GAAG,YAAY,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IACpC,IAAI,OAAO;QAAE,OAAO,OAAO,CAAC;IAC5B,SAAS;IACT,yBAAyB;IACzB,sBAAsB;IACtB,2BAA2B;IAC3B,2BAA2B;IAC3B,kBAAkB;IAClB,MAAM;IACN,MAAM,KAAK,GAAa,CAAC,iBAAiB,CAAC,CAAC;IAC5C,KAAK,MAAM,GAAG,IAAI,OAAO,EAAE,CAAC;QAC1B,KAAK,CAAC,IAAI,CAAC,OAAO,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;IACvD,CAAC;IACD,KAAK,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;IAC1B,OAAO,GAAG,IAAI,QAAQ,CAAC,MAAM,EAAE,GAAG,EAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAe,CAAC;IACpE,YAAY,CAAC,GAAG,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;IAC/B,OAAO,OAAO,CAAC;AACjB,CAAC;AAED;;;GAGG;AACH,SAAgB,YAAY,CAC1B,GAAe;IAEf,MAAM,CAAC,GAAG,IAAI,MAAM,CAAC,GAAG,CAAC,CAAC;IAC1B,IACE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,OAAO;QACtB,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,OAAO;QACtB,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,OAAO;QACtB,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,OAAO,EACtB,CAAC;QACD,MAAM,IAAI,KAAK,CAAC,wCAAwC,CAAC,CAAC;IAC5D,CAAC;IACD,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC;IAEV,MAAM,QAAQ,GAAG,CAAC,CAAC,GAAG,EAAE,CAAC;IACzB,MAAM,OAAO,GAAG,IAAI,KAAK,CAAS,QAAQ,CAAC,CAAC;IAC5C,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,QAAQ,EAAE,CAAC,EAAE;QAAE,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,CAAC;IAExD,MAAM,QAAQ,GAAG,CAAC,CAAC,GAAG,EAAE,CAAC;IACzB,MAAM,IAAI,GAAG,IAAI,KAAK,CAAsB,QAAQ,CAAC,CAAC;IACtD,IAAI,QAAQ,KAAK,CAAC,EAAE,CAAC;QACnB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,QAAQ,EAAE,CAAC,EAAE;YAAE,IAAI,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC;QAChD,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;IAC3B,CAAC;IACD,MAAM,OAAO,GAAG,UAAU,CAAC,OAAO,CAAC,CAAC;IACpC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,QAAQ,EAAE,CAAC,EAAE,EAAE,CAAC;QAClC,IAAI,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC;IAClC,CAAC;IAED,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;AAC3B,CAAC"}