@g9tm/syncdata 1.2.1
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/LICENSE.md +21 -0
- package/PARITY.md +71 -0
- package/README.md +71 -0
- package/THIRD-PARTY-NOTICES.md +31 -0
- package/dist/abstractions/digest.d.ts +27 -0
- package/dist/abstractions/digest.js +78 -0
- package/dist/abstractions/digest.js.map +1 -0
- package/dist/abstractions/enums.d.ts +42 -0
- package/dist/abstractions/enums.js +60 -0
- package/dist/abstractions/enums.js.map +1 -0
- package/dist/abstractions/errors.d.ts +72 -0
- package/dist/abstractions/errors.js +90 -0
- package/dist/abstractions/errors.js.map +1 -0
- package/dist/abstractions/guid.d.ts +24 -0
- package/dist/abstractions/guid.js +93 -0
- package/dist/abstractions/guid.js.map +1 -0
- package/dist/abstractions/key.d.ts +16 -0
- package/dist/abstractions/key.js +47 -0
- package/dist/abstractions/key.js.map +1 -0
- package/dist/abstractions/long.d.ts +103 -0
- package/dist/abstractions/long.js +351 -0
- package/dist/abstractions/long.js.map +1 -0
- package/dist/abstractions/parameters.d.ts +49 -0
- package/dist/abstractions/parameters.js +153 -0
- package/dist/abstractions/parameters.js.map +1 -0
- package/dist/brotli-js/decode.d.ts +8 -0
- package/dist/brotli-js/decode.js +2004 -0
- package/dist/brotli-js/decode.js.map +1 -0
- package/dist/brotli-js/index.d.ts +5 -0
- package/dist/brotli-js/index.js +19 -0
- package/dist/brotli-js/index.js.map +1 -0
- package/dist/client/engine.d.ts +110 -0
- package/dist/client/engine.js +1158 -0
- package/dist/client/engine.js.map +1 -0
- package/dist/client/model.d.ts +61 -0
- package/dist/client/model.js +154 -0
- package/dist/client/model.js.map +1 -0
- package/dist/client/progress.d.ts +101 -0
- package/dist/client/progress.js +251 -0
- package/dist/client/progress.js.map +1 -0
- package/dist/client/runs.d.ts +219 -0
- package/dist/client/runs.js +239 -0
- package/dist/client/runs.js.map +1 -0
- package/dist/client/storeTypes.d.ts +428 -0
- package/dist/client/storeTypes.js +256 -0
- package/dist/client/storeTypes.js.map +1 -0
- package/dist/client/transport.d.ts +19 -0
- package/dist/client/transport.js +2 -0
- package/dist/client/transport.js.map +1 -0
- package/dist/index.d.ts +27 -0
- package/dist/index.js +35 -0
- package/dist/index.js.map +1 -0
- package/dist/internal/abort.d.ts +21 -0
- package/dist/internal/abort.js +125 -0
- package/dist/internal/abort.js.map +1 -0
- package/dist/internal/base64.d.ts +8 -0
- package/dist/internal/base64.js +85 -0
- package/dist/internal/base64.js.map +1 -0
- package/dist/internal/dotnetFormat.d.ts +32 -0
- package/dist/internal/dotnetFormat.js +207 -0
- package/dist/internal/dotnetFormat.js.map +1 -0
- package/dist/internal/md5.d.ts +2 -0
- package/dist/internal/md5.js +97 -0
- package/dist/internal/md5.js.map +1 -0
- package/dist/internal/sha256.d.ts +20 -0
- package/dist/internal/sha256.js +153 -0
- package/dist/internal/sha256.js.map +1 -0
- package/dist/internal/utf8.d.ts +8 -0
- package/dist/internal/utf8.js +143 -0
- package/dist/internal/utf8.js.map +1 -0
- package/dist/node/index.d.ts +9 -0
- package/dist/node/index.js +35 -0
- package/dist/node/index.js.map +1 -0
- package/dist/node/sqliteDriver.d.ts +11 -0
- package/dist/node/sqliteDriver.js +252 -0
- package/dist/node/sqliteDriver.js.map +1 -0
- package/dist/protocol/dtos.d.ts +280 -0
- package/dist/protocol/dtos.js +33 -0
- package/dist/protocol/dtos.js.map +1 -0
- package/dist/protocol/protocol.d.ts +36 -0
- package/dist/protocol/protocol.js +63 -0
- package/dist/protocol/protocol.js.map +1 -0
- package/dist/protocol/rowBatch/columnLayout.d.ts +4 -0
- package/dist/protocol/rowBatch/columnLayout.js +309 -0
- package/dist/protocol/rowBatch/columnLayout.js.map +1 -0
- package/dist/protocol/rowBatch/format.d.ts +74 -0
- package/dist/protocol/rowBatch/format.js +163 -0
- package/dist/protocol/rowBatch/format.js.map +1 -0
- package/dist/protocol/rowBatch/reader.d.ts +119 -0
- package/dist/protocol/rowBatch/reader.js +459 -0
- package/dist/protocol/rowBatch/reader.js.map +1 -0
- package/dist/protocol/rowBatch/writer.d.ts +101 -0
- package/dist/protocol/rowBatch/writer.js +412 -0
- package/dist/protocol/rowBatch/writer.js.map +1 -0
- package/dist/protocol/wire.d.ts +32 -0
- package/dist/protocol/wire.js +329 -0
- package/dist/protocol/wire.js.map +1 -0
- package/dist/signalr/index.d.ts +2 -0
- package/dist/signalr/index.js +5 -0
- package/dist/signalr/index.js.map +1 -0
- package/dist/signalr/protocols.d.ts +17 -0
- package/dist/signalr/protocols.js +109 -0
- package/dist/signalr/protocols.js.map +1 -0
- package/dist/signalr/transport.d.ts +67 -0
- package/dist/signalr/transport.js +286 -0
- package/dist/signalr/transport.js.map +1 -0
- package/dist/sqlite/apply.d.ts +91 -0
- package/dist/sqlite/apply.js +657 -0
- package/dist/sqlite/apply.js.map +1 -0
- package/dist/sqlite/commands.d.ts +24 -0
- package/dist/sqlite/commands.js +167 -0
- package/dist/sqlite/commands.js.map +1 -0
- package/dist/sqlite/connection.d.ts +81 -0
- package/dist/sqlite/connection.js +322 -0
- package/dist/sqlite/connection.js.map +1 -0
- package/dist/sqlite/driver.d.ts +63 -0
- package/dist/sqlite/driver.js +9 -0
- package/dist/sqlite/driver.js.map +1 -0
- package/dist/sqlite/index.d.ts +6 -0
- package/dist/sqlite/index.js +7 -0
- package/dist/sqlite/index.js.map +1 -0
- package/dist/sqlite/internals.d.ts +63 -0
- package/dist/sqlite/internals.js +194 -0
- package/dist/sqlite/internals.js.map +1 -0
- package/dist/sqlite/options.d.ts +78 -0
- package/dist/sqlite/options.js +78 -0
- package/dist/sqlite/options.js.map +1 -0
- package/dist/sqlite/push.d.ts +9 -0
- package/dist/sqlite/push.js +272 -0
- package/dist/sqlite/push.js.map +1 -0
- package/dist/sqlite/query.d.ts +38 -0
- package/dist/sqlite/query.js +476 -0
- package/dist/sqlite/query.js.map +1 -0
- package/dist/sqlite/revocation.d.ts +28 -0
- package/dist/sqlite/revocation.js +337 -0
- package/dist/sqlite/revocation.js.map +1 -0
- package/dist/sqlite/sql.d.ts +60 -0
- package/dist/sqlite/sql.js +324 -0
- package/dist/sqlite/sql.js.map +1 -0
- package/dist/sqlite/store.d.ts +116 -0
- package/dist/sqlite/store.js +664 -0
- package/dist/sqlite/store.js.map +1 -0
- package/dist/sqlite/values.d.ts +29 -0
- package/dist/sqlite/values.js +288 -0
- package/dist/sqlite/values.js.map +1 -0
- package/dist/testing/index.d.ts +61 -0
- package/dist/testing/index.js +175 -0
- package/dist/testing/index.js.map +1 -0
- package/package.json +104 -0
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import { G9Long } from '../../abstractions/long.js';
|
|
2
|
+
import type { DecimalParts } from '../../internal/dotnetFormat.js';
|
|
3
|
+
import type { G9DateTimeOffsetValue, G9DateTimeValue } from './writer.js';
|
|
4
|
+
/**
|
|
5
|
+
* Decompresses a Brotli frame body. Returns exactly `expectedLength` bytes or throws. Node: `nodeBrotliDecompressor()`
|
|
6
|
+
* (`@g9tm/syncdata/node`); Lynx: the native module of `@g9tm/syncdata-lynx`; anywhere: `jsBrotliDecompressor()`
|
|
7
|
+
* (`@g9tm/syncdata/brotli-js`, pure JavaScript, slower).
|
|
8
|
+
*/
|
|
9
|
+
export interface G9FrameDecompressor {
|
|
10
|
+
decompress(compressed: Uint8Array, expectedLength: number): Uint8Array | Promise<Uint8Array>;
|
|
11
|
+
}
|
|
12
|
+
/** The header of a frame, read without decoding the body. */
|
|
13
|
+
export interface G9FrameHeader {
|
|
14
|
+
version: number;
|
|
15
|
+
compression: number;
|
|
16
|
+
bodyLength: number;
|
|
17
|
+
}
|
|
18
|
+
/** Validates a frame's header (magic, version, compression, body length, budget). */
|
|
19
|
+
export declare function readFrameHeader(frame: Uint8Array, maxBodyBytes?: number): G9FrameHeader;
|
|
20
|
+
/**
|
|
21
|
+
* Sets the Brotli decoder used wherever none is passed explicitly (the store, the engine's reconciliation). Call it
|
|
22
|
+
* once at start-up: `useNodeBrotli()` (`@g9tm/syncdata/node`), `useLynxBrotli()` (`@g9tm/syncdata-lynx`) or
|
|
23
|
+
* `setDefaultFrameDecompressor(jsBrotliDecompressor())` (`@g9tm/syncdata/brotli-js`).
|
|
24
|
+
*/
|
|
25
|
+
export declare function setDefaultFrameDecompressor(decompressor: G9FrameDecompressor | null): void;
|
|
26
|
+
/** The decoder set with {@link setDefaultFrameDecompressor}, or null. */
|
|
27
|
+
export declare function getDefaultFrameDecompressor(): G9FrameDecompressor | null;
|
|
28
|
+
/** Options of {@link openRowBatch}. */
|
|
29
|
+
export interface G9OpenRowBatchOptions {
|
|
30
|
+
/** Brotli decoder for compressed frames (every frame the server sends over 128 bytes); the default decoder when omitted. */
|
|
31
|
+
decompressor?: G9FrameDecompressor | null;
|
|
32
|
+
/** The largest decoded body this caller allocates for (ADR-0051). */
|
|
33
|
+
maxBodyBytes?: number;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Validates, decompresses when needed, and opens a frame. Async because a Lynx decompressor crosses the native bridge;
|
|
37
|
+
* an uncompressed frame resolves without waiting on anything.
|
|
38
|
+
*/
|
|
39
|
+
export declare function openRowBatch(frame: Uint8Array, options?: G9OpenRowBatchOptions): Promise<G9RowBatchReader>;
|
|
40
|
+
/** Opens an uncompressed frame synchronously (throws for a compressed one). */
|
|
41
|
+
export declare function openRowBatchSync(frame: Uint8Array, maxBodyBytes?: number): G9RowBatchReader;
|
|
42
|
+
/** Reads the sections and rows of one G9RowBatch body. */
|
|
43
|
+
export declare class G9RowBatchReader {
|
|
44
|
+
private readonly _body;
|
|
45
|
+
private readonly _cursor;
|
|
46
|
+
private _sectionsRemaining;
|
|
47
|
+
private _sectionOpen;
|
|
48
|
+
private _rowsRemaining;
|
|
49
|
+
private _types;
|
|
50
|
+
private _offsets;
|
|
51
|
+
private _keyStart;
|
|
52
|
+
private _keyLength;
|
|
53
|
+
private _keyText;
|
|
54
|
+
private _versionPos;
|
|
55
|
+
private _sequencePos;
|
|
56
|
+
private _baseVersionPos;
|
|
57
|
+
private _hlcPos;
|
|
58
|
+
readonly sectionCount: number;
|
|
59
|
+
op: number;
|
|
60
|
+
tableId: number;
|
|
61
|
+
keyType: number;
|
|
62
|
+
rowCount: number;
|
|
63
|
+
version: number;
|
|
64
|
+
pushOp: number;
|
|
65
|
+
sequence: number;
|
|
66
|
+
baseVersion: number;
|
|
67
|
+
dirtyMask: G9Long;
|
|
68
|
+
hlcMs: number;
|
|
69
|
+
rowHash: G9Long;
|
|
70
|
+
hasValues: boolean;
|
|
71
|
+
private constructor();
|
|
72
|
+
/** Opens an already decompressed body of the given layout version. */
|
|
73
|
+
static fromBody(body: Uint8Array, version: number): G9RowBatchReader;
|
|
74
|
+
/** The decoded size of this frame's body (row-wise layout). */
|
|
75
|
+
get bodyBytes(): number;
|
|
76
|
+
get columnTypes(): readonly number[];
|
|
77
|
+
get columnCount(): number;
|
|
78
|
+
/** Moves to the next section, skipping unread rows of the current one. */
|
|
79
|
+
nextSection(): boolean;
|
|
80
|
+
/** Moves to the next row of the current section. */
|
|
81
|
+
readRow(): boolean;
|
|
82
|
+
/** The row's version, exact (the {@link version} number is exact below 2^53). */
|
|
83
|
+
get versionLong(): G9Long;
|
|
84
|
+
/** A push row's local sequence, exact. */
|
|
85
|
+
get sequenceLong(): G9Long;
|
|
86
|
+
/** A push row's base version, exact. */
|
|
87
|
+
get baseVersionLong(): G9Long;
|
|
88
|
+
/** A push row's HLC milliseconds, exact. */
|
|
89
|
+
get hlcLong(): G9Long;
|
|
90
|
+
/** Canonical key text (see G9SyncKey). */
|
|
91
|
+
get key(): string;
|
|
92
|
+
/** The integer key. */
|
|
93
|
+
get keyInt64(): G9Long;
|
|
94
|
+
/** UTF-8 bytes of a string key. */
|
|
95
|
+
get keyUtf8(): Uint8Array;
|
|
96
|
+
isNull(column: number): boolean;
|
|
97
|
+
getBoolean(column: number): boolean;
|
|
98
|
+
getInt32(column: number): number;
|
|
99
|
+
/** An Int64 value, exact. */
|
|
100
|
+
getInt64(column: number): G9Long;
|
|
101
|
+
getDouble(column: number): number;
|
|
102
|
+
getDecimal(column: number): DecimalParts;
|
|
103
|
+
getString(column: number): string;
|
|
104
|
+
getUtf8(column: number): Uint8Array;
|
|
105
|
+
/** A GUID in canonical text form. */
|
|
106
|
+
getGuid(column: number): string;
|
|
107
|
+
getDateTime(column: number): G9DateTimeValue;
|
|
108
|
+
getDateTimeOffset(column: number): G9DateTimeOffsetValue;
|
|
109
|
+
/** A TimeSpan as ticks, exact. */
|
|
110
|
+
getTimeSpan(column: number): G9Long;
|
|
111
|
+
/** The bytes of a Bytes column (a view into the body; copy it to keep it). */
|
|
112
|
+
getBytes(column: number): Uint8Array;
|
|
113
|
+
private _readValues;
|
|
114
|
+
private _offset;
|
|
115
|
+
private _ensureValues;
|
|
116
|
+
private _lengthPrefixed;
|
|
117
|
+
private _readByte;
|
|
118
|
+
private _ensure;
|
|
119
|
+
}
|
|
@@ -0,0 +1,459 @@
|
|
|
1
|
+
// Twin of G9SyncData.Protocol/RowBatch/G9CRowBatchReader.cs: reads a G9RowBatch frame in either body layout. Forward
|
|
2
|
+
// only; values are decoded from the body on demand.
|
|
3
|
+
import { G9ESyncColumnType } from '../../abstractions/enums.js';
|
|
4
|
+
import { readGuidBytes } from '../../abstractions/guid.js';
|
|
5
|
+
import { G9SyncKey } from '../../abstractions/key.js';
|
|
6
|
+
import { G9Long } from '../../abstractions/long.js';
|
|
7
|
+
import { utf8Decode } from '../../internal/utf8.js';
|
|
8
|
+
import { toRows } from './columnLayout.js';
|
|
9
|
+
import { G9ECompression, G9EPushRowOp, G9ERowBatchOp, G9RowBatchFormat, G9RowBatchFormatError, isRowBatchOp, readInt32LE, readVarint, readVarintInt32, readVarintLong, readZigZagLong, readZigZagNumber, } from './format.js';
|
|
10
|
+
/** Validates a frame's header (magic, version, compression, body length, budget). */
|
|
11
|
+
export function readFrameHeader(frame, maxBodyBytes = G9RowBatchFormat.MaxDecodedBytes) {
|
|
12
|
+
if (!(maxBodyBytes > 0))
|
|
13
|
+
throw new RangeError('maxBodyBytes must be positive.');
|
|
14
|
+
if (frame.length < G9RowBatchFormat.HeaderSize || frame[0] !== 0x47 || frame[1] !== 0x39 || frame[2] !== 0x52 || frame[3] !== 0x42) {
|
|
15
|
+
throw new G9RowBatchFormatError('Not a G9RowBatch frame.');
|
|
16
|
+
}
|
|
17
|
+
const version = frame[4];
|
|
18
|
+
if (version !== G9RowBatchFormat.Version && version !== G9RowBatchFormat.ColumnVersion) {
|
|
19
|
+
throw new G9RowBatchFormatError(`Unsupported G9RowBatch version ${version}.`);
|
|
20
|
+
}
|
|
21
|
+
const compression = frame[5];
|
|
22
|
+
const bodyLength = readInt32LE(frame, 6);
|
|
23
|
+
if (bodyLength < 4 || bodyLength > G9RowBatchFormat.MaxDecodedBytes)
|
|
24
|
+
throw new G9RowBatchFormatError('Invalid body length.');
|
|
25
|
+
if (bodyLength > maxBodyBytes) {
|
|
26
|
+
throw new G9RowBatchFormatError(`The frame declares a ${bodyLength}-byte body; this reader accepts at most ${maxBodyBytes} bytes.`);
|
|
27
|
+
}
|
|
28
|
+
if (compression !== G9ECompression.None && compression !== G9ECompression.Brotli) {
|
|
29
|
+
throw new G9RowBatchFormatError(`Unknown compression ${compression}.`);
|
|
30
|
+
}
|
|
31
|
+
if (compression === G9ECompression.None && frame.length - G9RowBatchFormat.HeaderSize !== bodyLength) {
|
|
32
|
+
throw new G9RowBatchFormatError('Body length mismatch.');
|
|
33
|
+
}
|
|
34
|
+
return { version, compression, bodyLength };
|
|
35
|
+
}
|
|
36
|
+
let defaultDecompressor = null;
|
|
37
|
+
/**
|
|
38
|
+
* Sets the Brotli decoder used wherever none is passed explicitly (the store, the engine's reconciliation). Call it
|
|
39
|
+
* once at start-up: `useNodeBrotli()` (`@g9tm/syncdata/node`), `useLynxBrotli()` (`@g9tm/syncdata-lynx`) or
|
|
40
|
+
* `setDefaultFrameDecompressor(jsBrotliDecompressor())` (`@g9tm/syncdata/brotli-js`).
|
|
41
|
+
*/
|
|
42
|
+
export function setDefaultFrameDecompressor(decompressor) {
|
|
43
|
+
defaultDecompressor = decompressor;
|
|
44
|
+
}
|
|
45
|
+
/** The decoder set with {@link setDefaultFrameDecompressor}, or null. */
|
|
46
|
+
export function getDefaultFrameDecompressor() {
|
|
47
|
+
return defaultDecompressor;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Validates, decompresses when needed, and opens a frame. Async because a Lynx decompressor crosses the native bridge;
|
|
51
|
+
* an uncompressed frame resolves without waiting on anything.
|
|
52
|
+
*/
|
|
53
|
+
export async function openRowBatch(frame, options) {
|
|
54
|
+
var _a;
|
|
55
|
+
const header = readFrameHeader(frame, options === null || options === void 0 ? void 0 : options.maxBodyBytes);
|
|
56
|
+
if (header.compression === G9ECompression.None)
|
|
57
|
+
return G9RowBatchReader.fromBody(frame.subarray(G9RowBatchFormat.HeaderSize), header.version);
|
|
58
|
+
const decompressor = (_a = options === null || options === void 0 ? void 0 : options.decompressor) !== null && _a !== void 0 ? _a : defaultDecompressor;
|
|
59
|
+
if (!decompressor) {
|
|
60
|
+
throw new G9RowBatchFormatError('The frame is Brotli-compressed and no decompressor is configured (see G9FrameDecompressor).');
|
|
61
|
+
}
|
|
62
|
+
let body;
|
|
63
|
+
try {
|
|
64
|
+
body = await decompressor.decompress(frame.subarray(G9RowBatchFormat.HeaderSize), header.bodyLength);
|
|
65
|
+
}
|
|
66
|
+
catch (error) {
|
|
67
|
+
throw new G9RowBatchFormatError(`Brotli body could not be decompressed: ${error instanceof Error ? error.message : String(error)}`);
|
|
68
|
+
}
|
|
69
|
+
if (!body || body.length !== header.bodyLength)
|
|
70
|
+
throw new G9RowBatchFormatError('Brotli body could not be decompressed.');
|
|
71
|
+
return G9RowBatchReader.fromBody(body, header.version);
|
|
72
|
+
}
|
|
73
|
+
/** Opens an uncompressed frame synchronously (throws for a compressed one). */
|
|
74
|
+
export function openRowBatchSync(frame, maxBodyBytes) {
|
|
75
|
+
const header = readFrameHeader(frame, maxBodyBytes);
|
|
76
|
+
if (header.compression !== G9ECompression.None)
|
|
77
|
+
throw new G9RowBatchFormatError('The frame is compressed; use openRowBatch.');
|
|
78
|
+
return G9RowBatchReader.fromBody(frame.subarray(G9RowBatchFormat.HeaderSize), header.version);
|
|
79
|
+
}
|
|
80
|
+
/** Reads the sections and rows of one G9RowBatch body. */
|
|
81
|
+
export class G9RowBatchReader {
|
|
82
|
+
constructor(body) {
|
|
83
|
+
this._cursor = { pos: 4 };
|
|
84
|
+
this._sectionOpen = false;
|
|
85
|
+
this._rowsRemaining = 0;
|
|
86
|
+
this._types = [];
|
|
87
|
+
this._offsets = [];
|
|
88
|
+
this._keyStart = 0;
|
|
89
|
+
this._keyLength = 0;
|
|
90
|
+
this._keyText = null;
|
|
91
|
+
this._versionPos = -1;
|
|
92
|
+
this._sequencePos = -1;
|
|
93
|
+
this._baseVersionPos = -1;
|
|
94
|
+
this._hlcPos = -1;
|
|
95
|
+
// section
|
|
96
|
+
this.op = 0;
|
|
97
|
+
this.tableId = 0;
|
|
98
|
+
this.keyType = 0;
|
|
99
|
+
this.rowCount = 0;
|
|
100
|
+
// row
|
|
101
|
+
this.version = 0;
|
|
102
|
+
this.pushOp = 0;
|
|
103
|
+
this.sequence = 0;
|
|
104
|
+
this.baseVersion = 0;
|
|
105
|
+
this.dirtyMask = G9Long.ZERO;
|
|
106
|
+
this.hlcMs = 0;
|
|
107
|
+
this.rowHash = G9Long.ZERO;
|
|
108
|
+
this.hasValues = false;
|
|
109
|
+
if (body.length < 4)
|
|
110
|
+
throw new G9RowBatchFormatError('Row batch body is too short.');
|
|
111
|
+
this._body = body;
|
|
112
|
+
this.sectionCount = readInt32LE(body, 0);
|
|
113
|
+
if (this.sectionCount < 0)
|
|
114
|
+
throw new G9RowBatchFormatError('Negative section count.');
|
|
115
|
+
this._sectionsRemaining = this.sectionCount;
|
|
116
|
+
}
|
|
117
|
+
/** Opens an already decompressed body of the given layout version. */
|
|
118
|
+
static fromBody(body, version) {
|
|
119
|
+
return new G9RowBatchReader(version === G9RowBatchFormat.ColumnVersion ? toRows(body) : body);
|
|
120
|
+
}
|
|
121
|
+
/** The decoded size of this frame's body (row-wise layout). */
|
|
122
|
+
get bodyBytes() {
|
|
123
|
+
return this._body.length;
|
|
124
|
+
}
|
|
125
|
+
get columnTypes() {
|
|
126
|
+
return this._types;
|
|
127
|
+
}
|
|
128
|
+
get columnCount() {
|
|
129
|
+
return this._types.length;
|
|
130
|
+
}
|
|
131
|
+
/** Moves to the next section, skipping unread rows of the current one. */
|
|
132
|
+
nextSection() {
|
|
133
|
+
if (this._sectionOpen) {
|
|
134
|
+
while (this.readRow()) {
|
|
135
|
+
// skip
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
if (this._sectionsRemaining === 0) {
|
|
139
|
+
this._sectionOpen = false;
|
|
140
|
+
return false;
|
|
141
|
+
}
|
|
142
|
+
const body = this._body;
|
|
143
|
+
const cursor = this._cursor;
|
|
144
|
+
this.op = this._readByte();
|
|
145
|
+
if (!isRowBatchOp(this.op))
|
|
146
|
+
throw new G9RowBatchFormatError(`Unknown op ${this.op}.`);
|
|
147
|
+
this.tableId = readVarintInt32(body, cursor);
|
|
148
|
+
this.keyType = this._readByte();
|
|
149
|
+
if (!G9SyncKey.isSupportedKeyType(this.keyType))
|
|
150
|
+
throw new G9RowBatchFormatError(`Unsupported key type ${this.keyType}.`);
|
|
151
|
+
const columnCount = readVarintInt32(body, cursor);
|
|
152
|
+
if (columnCount > 1024)
|
|
153
|
+
throw new G9RowBatchFormatError('Too many columns.');
|
|
154
|
+
this._ensure(columnCount + 4);
|
|
155
|
+
const types = [];
|
|
156
|
+
for (let i = 0; i < columnCount; i++)
|
|
157
|
+
types.push(body[cursor.pos++]);
|
|
158
|
+
this._types = types;
|
|
159
|
+
this.rowCount = readInt32LE(body, cursor.pos);
|
|
160
|
+
cursor.pos += 4;
|
|
161
|
+
if (this.rowCount < 0)
|
|
162
|
+
throw new G9RowBatchFormatError('Negative row count.');
|
|
163
|
+
if (this._offsets.length < columnCount)
|
|
164
|
+
this._offsets = new Array(columnCount);
|
|
165
|
+
this._rowsRemaining = this.rowCount;
|
|
166
|
+
this._sectionsRemaining--;
|
|
167
|
+
this._sectionOpen = true;
|
|
168
|
+
return true;
|
|
169
|
+
}
|
|
170
|
+
/** Moves to the next row of the current section. */
|
|
171
|
+
readRow() {
|
|
172
|
+
if (!this._sectionOpen || this._rowsRemaining === 0)
|
|
173
|
+
return false;
|
|
174
|
+
const body = this._body;
|
|
175
|
+
const cursor = this._cursor;
|
|
176
|
+
this._keyText = null;
|
|
177
|
+
this.hasValues = false;
|
|
178
|
+
this.version = 0;
|
|
179
|
+
this.rowHash = G9Long.ZERO;
|
|
180
|
+
switch (this.keyType) {
|
|
181
|
+
case G9ESyncColumnType.Guid:
|
|
182
|
+
this._ensure(16);
|
|
183
|
+
this._keyStart = cursor.pos;
|
|
184
|
+
this._keyLength = 16;
|
|
185
|
+
cursor.pos += 16;
|
|
186
|
+
break;
|
|
187
|
+
case G9ESyncColumnType.Int32:
|
|
188
|
+
case G9ESyncColumnType.Int64:
|
|
189
|
+
this._keyStart = cursor.pos;
|
|
190
|
+
readVarintLong(body, cursor);
|
|
191
|
+
this._keyLength = cursor.pos - this._keyStart;
|
|
192
|
+
break;
|
|
193
|
+
default: {
|
|
194
|
+
const length = readVarintInt32(body, cursor);
|
|
195
|
+
this._ensure(length);
|
|
196
|
+
this._keyStart = cursor.pos;
|
|
197
|
+
this._keyLength = length;
|
|
198
|
+
cursor.pos += length;
|
|
199
|
+
break;
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
switch (this.op) {
|
|
203
|
+
case G9ERowBatchOp.Upsert:
|
|
204
|
+
case G9ERowBatchOp.Backfill:
|
|
205
|
+
this._versionPos = cursor.pos;
|
|
206
|
+
this.version = readVarint(body, cursor);
|
|
207
|
+
this._readValues();
|
|
208
|
+
break;
|
|
209
|
+
case G9ERowBatchOp.Tombstone:
|
|
210
|
+
case G9ERowBatchOp.MoveOut:
|
|
211
|
+
this._versionPos = cursor.pos;
|
|
212
|
+
this.version = readVarint(body, cursor);
|
|
213
|
+
break;
|
|
214
|
+
case G9ERowBatchOp.KeyVersions:
|
|
215
|
+
this._versionPos = cursor.pos;
|
|
216
|
+
this.version = readVarint(body, cursor);
|
|
217
|
+
this._ensure(8);
|
|
218
|
+
this.rowHash = G9Long.readLE(body, cursor.pos);
|
|
219
|
+
cursor.pos += 8;
|
|
220
|
+
break;
|
|
221
|
+
case G9ERowBatchOp.Push:
|
|
222
|
+
this.pushOp = this._readByte();
|
|
223
|
+
if (this.pushOp !== G9EPushRowOp.Upsert && this.pushOp !== G9EPushRowOp.Delete)
|
|
224
|
+
throw new G9RowBatchFormatError(`Unknown push op ${this.pushOp}.`);
|
|
225
|
+
this._versionPos = -1;
|
|
226
|
+
this._sequencePos = cursor.pos;
|
|
227
|
+
this.sequence = readVarint(body, cursor);
|
|
228
|
+
this._baseVersionPos = cursor.pos;
|
|
229
|
+
this.baseVersion = readVarint(body, cursor);
|
|
230
|
+
this._ensure(8);
|
|
231
|
+
this.dirtyMask = G9Long.readLE(body, cursor.pos);
|
|
232
|
+
cursor.pos += 8;
|
|
233
|
+
this._hlcPos = cursor.pos;
|
|
234
|
+
this.hlcMs = readZigZagNumber(body, cursor);
|
|
235
|
+
if (this.pushOp === G9EPushRowOp.Upsert)
|
|
236
|
+
this._readValues();
|
|
237
|
+
break;
|
|
238
|
+
}
|
|
239
|
+
this._rowsRemaining--;
|
|
240
|
+
return true;
|
|
241
|
+
}
|
|
242
|
+
/** The row's version, exact (the {@link version} number is exact below 2^53). */
|
|
243
|
+
get versionLong() {
|
|
244
|
+
return this._versionPos < 0 ? G9Long.ZERO : readVarintLong(this._body, { pos: this._versionPos });
|
|
245
|
+
}
|
|
246
|
+
/** A push row's local sequence, exact. */
|
|
247
|
+
get sequenceLong() {
|
|
248
|
+
return readVarintLong(this._body, { pos: this._sequencePos });
|
|
249
|
+
}
|
|
250
|
+
/** A push row's base version, exact. */
|
|
251
|
+
get baseVersionLong() {
|
|
252
|
+
return readVarintLong(this._body, { pos: this._baseVersionPos });
|
|
253
|
+
}
|
|
254
|
+
/** A push row's HLC milliseconds, exact. */
|
|
255
|
+
get hlcLong() {
|
|
256
|
+
return readZigZagLong(this._body, { pos: this._hlcPos });
|
|
257
|
+
}
|
|
258
|
+
// ---------------------------------------------------------------- key
|
|
259
|
+
/** Canonical key text (see G9SyncKey). */
|
|
260
|
+
get key() {
|
|
261
|
+
if (this._keyText === null) {
|
|
262
|
+
switch (this.keyType) {
|
|
263
|
+
case G9ESyncColumnType.Guid:
|
|
264
|
+
this._keyText = readGuidBytes(this._body, this._keyStart);
|
|
265
|
+
break;
|
|
266
|
+
case G9ESyncColumnType.Int32:
|
|
267
|
+
case G9ESyncColumnType.Int64:
|
|
268
|
+
this._keyText = this.keyInt64.toString();
|
|
269
|
+
break;
|
|
270
|
+
default:
|
|
271
|
+
this._keyText = utf8Decode(this._body.subarray(this._keyStart, this._keyStart + this._keyLength));
|
|
272
|
+
break;
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
return this._keyText;
|
|
276
|
+
}
|
|
277
|
+
/** The integer key. */
|
|
278
|
+
get keyInt64() {
|
|
279
|
+
if (this.keyType !== G9ESyncColumnType.Int32 && this.keyType !== G9ESyncColumnType.Int64)
|
|
280
|
+
throw new Error(`Key type is ${this.keyType}.`);
|
|
281
|
+
return readZigZagLong(this._body, { pos: this._keyStart });
|
|
282
|
+
}
|
|
283
|
+
/** UTF-8 bytes of a string key. */
|
|
284
|
+
get keyUtf8() {
|
|
285
|
+
if (this.keyType !== G9ESyncColumnType.String)
|
|
286
|
+
throw new Error(`Key type is ${this.keyType}.`);
|
|
287
|
+
return this._body.subarray(this._keyStart, this._keyStart + this._keyLength);
|
|
288
|
+
}
|
|
289
|
+
// ---------------------------------------------------------------- values
|
|
290
|
+
isNull(column) {
|
|
291
|
+
this._ensureValues(column);
|
|
292
|
+
return this._offsets[column] < 0;
|
|
293
|
+
}
|
|
294
|
+
getBoolean(column) {
|
|
295
|
+
return this._body[this._offset(column, G9ESyncColumnType.Boolean)] !== 0;
|
|
296
|
+
}
|
|
297
|
+
getInt32(column) {
|
|
298
|
+
const value = readZigZagNumber(this._body, { pos: this._offset(column, G9ESyncColumnType.Int32) });
|
|
299
|
+
if (value < -2147483648 || value > 2147483647)
|
|
300
|
+
throw new G9RowBatchFormatError('Int32 value is out of range.');
|
|
301
|
+
return value;
|
|
302
|
+
}
|
|
303
|
+
/** An Int64 value, exact. */
|
|
304
|
+
getInt64(column) {
|
|
305
|
+
return readZigZagLong(this._body, { pos: this._offset(column, G9ESyncColumnType.Int64) });
|
|
306
|
+
}
|
|
307
|
+
getDouble(column) {
|
|
308
|
+
const at = this._offset(column, G9ESyncColumnType.Double);
|
|
309
|
+
for (let i = 0; i < 8; i++)
|
|
310
|
+
DOUBLE_BYTES[i] = this._body[at + i];
|
|
311
|
+
return DOUBLE_VIEW.getFloat64(0, true);
|
|
312
|
+
}
|
|
313
|
+
getDecimal(column) {
|
|
314
|
+
const at = this._offset(column, G9ESyncColumnType.Decimal);
|
|
315
|
+
const flags = readInt32LE(this._body, at + 12);
|
|
316
|
+
// decimal.GetBits: bits 0-15 and 24-30 of the flags are zero and the scale is at most 28.
|
|
317
|
+
if ((flags & 0x7f00ffff) !== 0 || ((flags >> 16) & 0xff) > 28)
|
|
318
|
+
throw new G9RowBatchFormatError('Invalid decimal value.');
|
|
319
|
+
return {
|
|
320
|
+
lo: readInt32LE(this._body, at) >>> 0,
|
|
321
|
+
mid: readInt32LE(this._body, at + 4) >>> 0,
|
|
322
|
+
hi: readInt32LE(this._body, at + 8) >>> 0,
|
|
323
|
+
scale: (flags >> 16) & 0xff,
|
|
324
|
+
negative: flags < 0,
|
|
325
|
+
};
|
|
326
|
+
}
|
|
327
|
+
getString(column) {
|
|
328
|
+
return utf8Decode(this.getUtf8(column));
|
|
329
|
+
}
|
|
330
|
+
getUtf8(column) {
|
|
331
|
+
return this._lengthPrefixed(this._offset(column, G9ESyncColumnType.String));
|
|
332
|
+
}
|
|
333
|
+
/** A GUID in canonical text form. */
|
|
334
|
+
getGuid(column) {
|
|
335
|
+
return readGuidBytes(this._body, this._offset(column, G9ESyncColumnType.Guid));
|
|
336
|
+
}
|
|
337
|
+
getDateTime(column) {
|
|
338
|
+
const at = this._offset(column, G9ESyncColumnType.DateTime);
|
|
339
|
+
const ticks = G9Long.readLE(this._body, at);
|
|
340
|
+
const kind = this._body[at + 8];
|
|
341
|
+
if (ticks.compare(G9Long.ZERO) < 0 || ticks.compare(MAX_TICKS) > 0 || kind > 2)
|
|
342
|
+
throw new G9RowBatchFormatError('Invalid DateTime value.');
|
|
343
|
+
return { ticks, kind };
|
|
344
|
+
}
|
|
345
|
+
getDateTimeOffset(column) {
|
|
346
|
+
const at = this._offset(column, G9ESyncColumnType.DateTimeOffset);
|
|
347
|
+
const utcTicks = G9Long.readLE(this._body, at);
|
|
348
|
+
const raw = this._body[at + 8] | (this._body[at + 9] << 8);
|
|
349
|
+
const minutes = raw >= 0x8000 ? raw - 0x10000 : raw;
|
|
350
|
+
const local = utcTicks.add(G9Long.fromNumber(minutes * 600000000));
|
|
351
|
+
if (minutes < -840 ||
|
|
352
|
+
minutes > 840 ||
|
|
353
|
+
utcTicks.compare(G9Long.ZERO) < 0 ||
|
|
354
|
+
utcTicks.compare(MAX_TICKS) > 0 ||
|
|
355
|
+
local.compare(G9Long.ZERO) < 0 ||
|
|
356
|
+
local.compare(MAX_TICKS) > 0) {
|
|
357
|
+
throw new G9RowBatchFormatError('Invalid DateTimeOffset value.');
|
|
358
|
+
}
|
|
359
|
+
return { utcTicks, offsetMinutes: minutes };
|
|
360
|
+
}
|
|
361
|
+
/** A TimeSpan as ticks, exact. */
|
|
362
|
+
getTimeSpan(column) {
|
|
363
|
+
return readZigZagLong(this._body, { pos: this._offset(column, G9ESyncColumnType.TimeSpan) });
|
|
364
|
+
}
|
|
365
|
+
/** The bytes of a Bytes column (a view into the body; copy it to keep it). */
|
|
366
|
+
getBytes(column) {
|
|
367
|
+
return this._lengthPrefixed(this._offset(column, G9ESyncColumnType.Bytes));
|
|
368
|
+
}
|
|
369
|
+
// ---------------------------------------------------------------- internals
|
|
370
|
+
_readValues() {
|
|
371
|
+
const body = this._body;
|
|
372
|
+
const cursor = this._cursor;
|
|
373
|
+
const count = this._types.length;
|
|
374
|
+
const bitmapBytes = (count + 7) >> 3;
|
|
375
|
+
this._ensure(bitmapBytes);
|
|
376
|
+
const bitmap = cursor.pos;
|
|
377
|
+
cursor.pos += bitmapBytes;
|
|
378
|
+
this.hasValues = true;
|
|
379
|
+
const offsets = this._offsets;
|
|
380
|
+
for (let column = 0; column < count; column++) {
|
|
381
|
+
if ((body[bitmap + (column >> 3)] & (1 << (column & 7))) !== 0) {
|
|
382
|
+
offsets[column] = -1;
|
|
383
|
+
continue;
|
|
384
|
+
}
|
|
385
|
+
offsets[column] = cursor.pos;
|
|
386
|
+
switch (this._types[column]) {
|
|
387
|
+
case G9ESyncColumnType.Boolean:
|
|
388
|
+
this._ensure(1);
|
|
389
|
+
cursor.pos += 1;
|
|
390
|
+
break;
|
|
391
|
+
case G9ESyncColumnType.Int32:
|
|
392
|
+
case G9ESyncColumnType.Int64:
|
|
393
|
+
case G9ESyncColumnType.TimeSpan:
|
|
394
|
+
readVarintLong(body, cursor);
|
|
395
|
+
break;
|
|
396
|
+
case G9ESyncColumnType.Double:
|
|
397
|
+
this._ensure(8);
|
|
398
|
+
cursor.pos += 8;
|
|
399
|
+
break;
|
|
400
|
+
case G9ESyncColumnType.Decimal:
|
|
401
|
+
case G9ESyncColumnType.Guid:
|
|
402
|
+
this._ensure(16);
|
|
403
|
+
cursor.pos += 16;
|
|
404
|
+
break;
|
|
405
|
+
case G9ESyncColumnType.DateTime:
|
|
406
|
+
this._ensure(9);
|
|
407
|
+
cursor.pos += 9;
|
|
408
|
+
break;
|
|
409
|
+
case G9ESyncColumnType.DateTimeOffset:
|
|
410
|
+
this._ensure(10);
|
|
411
|
+
cursor.pos += 10;
|
|
412
|
+
break;
|
|
413
|
+
case G9ESyncColumnType.String:
|
|
414
|
+
case G9ESyncColumnType.Bytes: {
|
|
415
|
+
const length = readVarintInt32(body, cursor);
|
|
416
|
+
this._ensure(length);
|
|
417
|
+
cursor.pos += length;
|
|
418
|
+
break;
|
|
419
|
+
}
|
|
420
|
+
default:
|
|
421
|
+
throw new G9RowBatchFormatError(`Unknown column type ${this._types[column]}.`);
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
_offset(column, expected) {
|
|
426
|
+
this._ensureValues(column);
|
|
427
|
+
if (this._types[column] !== expected)
|
|
428
|
+
throw new Error(`Column ${column} is ${this._types[column]}, not ${expected}.`);
|
|
429
|
+
const offset = this._offsets[column];
|
|
430
|
+
if (offset < 0)
|
|
431
|
+
throw new Error(`Column ${column} is NULL.`);
|
|
432
|
+
return offset;
|
|
433
|
+
}
|
|
434
|
+
_ensureValues(column) {
|
|
435
|
+
if (!this.hasValues)
|
|
436
|
+
throw new Error('The current row carries no column values.');
|
|
437
|
+
if (!(column >= 0 && column < this._types.length))
|
|
438
|
+
throw new RangeError(`Column ${column} is out of range.`);
|
|
439
|
+
}
|
|
440
|
+
_lengthPrefixed(position) {
|
|
441
|
+
const cursor = { pos: position };
|
|
442
|
+
const length = readVarintInt32(this._body, cursor);
|
|
443
|
+
return this._body.subarray(cursor.pos, cursor.pos + length);
|
|
444
|
+
}
|
|
445
|
+
_readByte() {
|
|
446
|
+
this._ensure(1);
|
|
447
|
+
return this._body[this._cursor.pos++];
|
|
448
|
+
}
|
|
449
|
+
_ensure(count) {
|
|
450
|
+
if (count < 0 || this._cursor.pos + count > this._body.length)
|
|
451
|
+
throw new G9RowBatchFormatError('Row batch is truncated.');
|
|
452
|
+
}
|
|
453
|
+
}
|
|
454
|
+
/** DateTime.MaxValue.Ticks. */
|
|
455
|
+
const MAX_TICKS = G9Long.parse('3155378975999999999');
|
|
456
|
+
const DOUBLE_BUFFER = new ArrayBuffer(8);
|
|
457
|
+
const DOUBLE_VIEW = new DataView(DOUBLE_BUFFER);
|
|
458
|
+
const DOUBLE_BYTES = new Uint8Array(DOUBLE_BUFFER);
|
|
459
|
+
//# sourceMappingURL=reader.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reader.js","sourceRoot":"","sources":["../../../src/protocol/rowBatch/reader.ts"],"names":[],"mappings":"AAAA,qHAAqH;AACrH,oDAAoD;AACpD,OAAO,EAAE,iBAAiB,EAAE,MAAM,6BAA6B,CAAC;AAChE,OAAO,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAC3D,OAAO,EAAE,SAAS,EAAE,MAAM,2BAA2B,CAAC;AACtD,OAAO,EAAE,MAAM,EAAE,MAAM,4BAA4B,CAAC;AAEpD,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AACpD,OAAO,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAC3C,OAAO,EAEL,cAAc,EACd,YAAY,EACZ,aAAa,EACb,gBAAgB,EAChB,qBAAqB,EACrB,YAAY,EACZ,WAAW,EACX,UAAU,EACV,eAAe,EACf,cAAc,EACd,cAAc,EACd,gBAAgB,GACjB,MAAM,aAAa,CAAC;AAmBrB,qFAAqF;AACrF,MAAM,UAAU,eAAe,CAAC,KAAiB,EAAE,eAAuB,gBAAgB,CAAC,eAAe;IACxG,IAAI,CAAC,CAAC,YAAY,GAAG,CAAC,CAAC;QAAE,MAAM,IAAI,UAAU,CAAC,gCAAgC,CAAC,CAAC;IAChF,IAAI,KAAK,CAAC,MAAM,GAAG,gBAAgB,CAAC,UAAU,IAAI,KAAK,CAAC,CAAC,CAAC,KAAK,IAAI,IAAI,KAAK,CAAC,CAAC,CAAC,KAAK,IAAI,IAAI,KAAK,CAAC,CAAC,CAAC,KAAK,IAAI,IAAI,KAAK,CAAC,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC;QACnI,MAAM,IAAI,qBAAqB,CAAC,yBAAyB,CAAC,CAAC;IAC7D,CAAC;IACD,MAAM,OAAO,GAAG,KAAK,CAAC,CAAC,CAAW,CAAC;IACnC,IAAI,OAAO,KAAK,gBAAgB,CAAC,OAAO,IAAI,OAAO,KAAK,gBAAgB,CAAC,aAAa,EAAE,CAAC;QACvF,MAAM,IAAI,qBAAqB,CAAC,kCAAkC,OAAO,GAAG,CAAC,CAAC;IAChF,CAAC;IACD,MAAM,WAAW,GAAG,KAAK,CAAC,CAAC,CAAW,CAAC;IACvC,MAAM,UAAU,GAAG,WAAW,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;IACzC,IAAI,UAAU,GAAG,CAAC,IAAI,UAAU,GAAG,gBAAgB,CAAC,eAAe;QAAE,MAAM,IAAI,qBAAqB,CAAC,sBAAsB,CAAC,CAAC;IAC7H,IAAI,UAAU,GAAG,YAAY,EAAE,CAAC;QAC9B,MAAM,IAAI,qBAAqB,CAAC,wBAAwB,UAAU,2CAA2C,YAAY,SAAS,CAAC,CAAC;IACtI,CAAC;IACD,IAAI,WAAW,KAAK,cAAc,CAAC,IAAI,IAAI,WAAW,KAAK,cAAc,CAAC,MAAM,EAAE,CAAC;QACjF,MAAM,IAAI,qBAAqB,CAAC,uBAAuB,WAAW,GAAG,CAAC,CAAC;IACzE,CAAC;IACD,IAAI,WAAW,KAAK,cAAc,CAAC,IAAI,IAAI,KAAK,CAAC,MAAM,GAAG,gBAAgB,CAAC,UAAU,KAAK,UAAU,EAAE,CAAC;QACrG,MAAM,IAAI,qBAAqB,CAAC,uBAAuB,CAAC,CAAC;IAC3D,CAAC;IACD,OAAO,EAAE,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,CAAC;AAC9C,CAAC;AAED,IAAI,mBAAmB,GAA+B,IAAI,CAAC;AAE3D;;;;GAIG;AACH,MAAM,UAAU,2BAA2B,CAAC,YAAwC;IAClF,mBAAmB,GAAG,YAAY,CAAC;AACrC,CAAC;AAED,yEAAyE;AACzE,MAAM,UAAU,2BAA2B;IACzC,OAAO,mBAAmB,CAAC;AAC7B,CAAC;AAUD;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,KAAiB,EAAE,OAA+B;;IACnF,MAAM,MAAM,GAAG,eAAe,CAAC,KAAK,EAAE,OAAO,aAAP,OAAO,uBAAP,OAAO,CAAE,YAAY,CAAC,CAAC;IAC7D,IAAI,MAAM,CAAC,WAAW,KAAK,cAAc,CAAC,IAAI;QAAE,OAAO,gBAAgB,CAAC,QAAQ,CAAC,KAAK,CAAC,QAAQ,CAAC,gBAAgB,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC,OAAO,CAAC,CAAC;IAC9I,MAAM,YAAY,GAAG,MAAA,OAAO,aAAP,OAAO,uBAAP,OAAO,CAAE,YAAY,mCAAI,mBAAmB,CAAC;IAClE,IAAI,CAAC,YAAY,EAAE,CAAC;QAClB,MAAM,IAAI,qBAAqB,CAAC,6FAA6F,CAAC,CAAC;IACjI,CAAC;IACD,IAAI,IAAgB,CAAC;IACrB,IAAI,CAAC;QACH,IAAI,GAAG,MAAM,YAAY,CAAC,UAAU,CAAC,KAAK,CAAC,QAAQ,CAAC,gBAAgB,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC,CAAC;IACvG,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,IAAI,qBAAqB,CAAC,0CAA0C,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IACtI,CAAC;IACD,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,MAAM,KAAK,MAAM,CAAC,UAAU;QAAE,MAAM,IAAI,qBAAqB,CAAC,wCAAwC,CAAC,CAAC;IAC1H,OAAO,gBAAgB,CAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,OAAO,CAAC,CAAC;AACzD,CAAC;AAED,+EAA+E;AAC/E,MAAM,UAAU,gBAAgB,CAAC,KAAiB,EAAE,YAAqB;IACvE,MAAM,MAAM,GAAG,eAAe,CAAC,KAAK,EAAE,YAAY,CAAC,CAAC;IACpD,IAAI,MAAM,CAAC,WAAW,KAAK,cAAc,CAAC,IAAI;QAAE,MAAM,IAAI,qBAAqB,CAAC,4CAA4C,CAAC,CAAC;IAC9H,OAAO,gBAAgB,CAAC,QAAQ,CAAC,KAAK,CAAC,QAAQ,CAAC,gBAAgB,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC,OAAO,CAAC,CAAC;AAChG,CAAC;AAED,0DAA0D;AAC1D,MAAM,OAAO,gBAAgB;IAkC3B,YAAoB,IAAgB;QAhCnB,YAAO,GAAW,EAAE,GAAG,EAAE,CAAC,EAAE,CAAC;QAEtC,iBAAY,GAAG,KAAK,CAAC;QACrB,mBAAc,GAAG,CAAC,CAAC;QACnB,WAAM,GAAa,EAAE,CAAC;QACtB,aAAQ,GAAa,EAAE,CAAC;QACxB,cAAS,GAAG,CAAC,CAAC;QACd,eAAU,GAAG,CAAC,CAAC;QACf,aAAQ,GAAkB,IAAI,CAAC;QAC/B,gBAAW,GAAG,CAAC,CAAC,CAAC;QACjB,iBAAY,GAAG,CAAC,CAAC,CAAC;QAClB,oBAAe,GAAG,CAAC,CAAC,CAAC;QACrB,YAAO,GAAG,CAAC,CAAC,CAAC;QAIrB,UAAU;QACV,OAAE,GAAG,CAAC,CAAC;QACP,YAAO,GAAG,CAAC,CAAC;QACZ,YAAO,GAAG,CAAC,CAAC;QACZ,aAAQ,GAAG,CAAC,CAAC;QAEb,MAAM;QACN,YAAO,GAAG,CAAC,CAAC;QACZ,WAAM,GAAG,CAAC,CAAC;QACX,aAAQ,GAAG,CAAC,CAAC;QACb,gBAAW,GAAG,CAAC,CAAC;QAChB,cAAS,GAAW,MAAM,CAAC,IAAI,CAAC;QAChC,UAAK,GAAG,CAAC,CAAC;QACV,YAAO,GAAW,MAAM,CAAC,IAAI,CAAC;QAC9B,cAAS,GAAG,KAAK,CAAC;QAGhB,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC;YAAE,MAAM,IAAI,qBAAqB,CAAC,8BAA8B,CAAC,CAAC;QACrF,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC;QAClB,IAAI,CAAC,YAAY,GAAG,WAAW,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;QACzC,IAAI,IAAI,CAAC,YAAY,GAAG,CAAC;YAAE,MAAM,IAAI,qBAAqB,CAAC,yBAAyB,CAAC,CAAC;QACtF,IAAI,CAAC,kBAAkB,GAAG,IAAI,CAAC,YAAY,CAAC;IAC9C,CAAC;IAED,sEAAsE;IACtE,MAAM,CAAC,QAAQ,CAAC,IAAgB,EAAE,OAAe;QAC/C,OAAO,IAAI,gBAAgB,CAAC,OAAO,KAAK,gBAAgB,CAAC,aAAa,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;IAChG,CAAC;IAED,+DAA+D;IAC/D,IAAI,SAAS;QACX,OAAO,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC;IAC3B,CAAC;IAED,IAAI,WAAW;QACb,OAAO,IAAI,CAAC,MAAM,CAAC;IACrB,CAAC;IAED,IAAI,WAAW;QACb,OAAO,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC;IAC5B,CAAC;IAED,0EAA0E;IAC1E,WAAW;QACT,IAAI,IAAI,CAAC,YAAY,EAAE,CAAC;YACtB,OAAO,IAAI,CAAC,OAAO,EAAE,EAAE,CAAC;gBACtB,OAAO;YACT,CAAC;QACH,CAAC;QACD,IAAI,IAAI,CAAC,kBAAkB,KAAK,CAAC,EAAE,CAAC;YAClC,IAAI,CAAC,YAAY,GAAG,KAAK,CAAC;YAC1B,OAAO,KAAK,CAAC;QACf,CAAC;QACD,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC;QACxB,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC;QAC5B,IAAI,CAAC,EAAE,GAAG,IAAI,CAAC,SAAS,EAAE,CAAC;QAC3B,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,EAAE,CAAC;YAAE,MAAM,IAAI,qBAAqB,CAAC,cAAc,IAAI,CAAC,EAAE,GAAG,CAAC,CAAC;QACtF,IAAI,CAAC,OAAO,GAAG,eAAe,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;QAC7C,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,SAAS,EAAE,CAAC;QAChC,IAAI,CAAC,SAAS,CAAC,kBAAkB,CAAC,IAAI,CAAC,OAAO,CAAC;YAAE,MAAM,IAAI,qBAAqB,CAAC,wBAAwB,IAAI,CAAC,OAAO,GAAG,CAAC,CAAC;QAC1H,MAAM,WAAW,GAAG,eAAe,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;QAClD,IAAI,WAAW,GAAG,IAAI;YAAE,MAAM,IAAI,qBAAqB,CAAC,mBAAmB,CAAC,CAAC;QAC7E,IAAI,CAAC,OAAO,CAAC,WAAW,GAAG,CAAC,CAAC,CAAC;QAC9B,MAAM,KAAK,GAAa,EAAE,CAAC;QAC3B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,WAAW,EAAE,CAAC,EAAE;YAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,EAAE,CAAW,CAAC,CAAC;QAC/E,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC;QACpB,IAAI,CAAC,QAAQ,GAAG,WAAW,CAAC,IAAI,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC;QAC9C,MAAM,CAAC,GAAG,IAAI,CAAC,CAAC;QAChB,IAAI,IAAI,CAAC,QAAQ,GAAG,CAAC;YAAE,MAAM,IAAI,qBAAqB,CAAC,qBAAqB,CAAC,CAAC;QAC9E,IAAI,IAAI,CAAC,QAAQ,CAAC,MAAM,GAAG,WAAW;YAAE,IAAI,CAAC,QAAQ,GAAG,IAAI,KAAK,CAAS,WAAW,CAAC,CAAC;QACvF,IAAI,CAAC,cAAc,GAAG,IAAI,CAAC,QAAQ,CAAC;QACpC,IAAI,CAAC,kBAAkB,EAAE,CAAC;QAC1B,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC;QACzB,OAAO,IAAI,CAAC;IACd,CAAC;IAED,oDAAoD;IACpD,OAAO;QACL,IAAI,CAAC,IAAI,CAAC,YAAY,IAAI,IAAI,CAAC,cAAc,KAAK,CAAC;YAAE,OAAO,KAAK,CAAC;QAClE,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC;QACxB,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC;QAC5B,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC;QACrB,IAAI,CAAC,SAAS,GAAG,KAAK,CAAC;QACvB,IAAI,CAAC,OAAO,GAAG,CAAC,CAAC;QACjB,IAAI,CAAC,OAAO,GAAG,MAAM,CAAC,IAAI,CAAC;QAE3B,QAAQ,IAAI,CAAC,OAAO,EAAE,CAAC;YACrB,KAAK,iBAAiB,CAAC,IAAI;gBACzB,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;gBACjB,IAAI,CAAC,SAAS,GAAG,MAAM,CAAC,GAAG,CAAC;gBAC5B,IAAI,CAAC,UAAU,GAAG,EAAE,CAAC;gBACrB,MAAM,CAAC,GAAG,IAAI,EAAE,CAAC;gBACjB,MAAM;YACR,KAAK,iBAAiB,CAAC,KAAK,CAAC;YAC7B,KAAK,iBAAiB,CAAC,KAAK;gBAC1B,IAAI,CAAC,SAAS,GAAG,MAAM,CAAC,GAAG,CAAC;gBAC5B,cAAc,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;gBAC7B,IAAI,CAAC,UAAU,GAAG,MAAM,CAAC,GAAG,GAAG,IAAI,CAAC,SAAS,CAAC;gBAC9C,MAAM;YACR,OAAO,CAAC,CAAC,CAAC;gBACR,MAAM,MAAM,GAAG,eAAe,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;gBAC7C,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;gBACrB,IAAI,CAAC,SAAS,GAAG,MAAM,CAAC,GAAG,CAAC;gBAC5B,IAAI,CAAC,UAAU,GAAG,MAAM,CAAC;gBACzB,MAAM,CAAC,GAAG,IAAI,MAAM,CAAC;gBACrB,MAAM;YACR,CAAC;QACH,CAAC;QAED,QAAQ,IAAI,CAAC,EAAE,EAAE,CAAC;YAChB,KAAK,aAAa,CAAC,MAAM,CAAC;YAC1B,KAAK,aAAa,CAAC,QAAQ;gBACzB,IAAI,CAAC,WAAW,GAAG,MAAM,CAAC,GAAG,CAAC;gBAC9B,IAAI,CAAC,OAAO,GAAG,UAAU,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;gBACxC,IAAI,CAAC,WAAW,EAAE,CAAC;gBACnB,MAAM;YACR,KAAK,aAAa,CAAC,SAAS,CAAC;YAC7B,KAAK,aAAa,CAAC,OAAO;gBACxB,IAAI,CAAC,WAAW,GAAG,MAAM,CAAC,GAAG,CAAC;gBAC9B,IAAI,CAAC,OAAO,GAAG,UAAU,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;gBACxC,MAAM;YACR,KAAK,aAAa,CAAC,WAAW;gBAC5B,IAAI,CAAC,WAAW,GAAG,MAAM,CAAC,GAAG,CAAC;gBAC9B,IAAI,CAAC,OAAO,GAAG,UAAU,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;gBACxC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;gBAChB,IAAI,CAAC,OAAO,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC;gBAC/C,MAAM,CAAC,GAAG,IAAI,CAAC,CAAC;gBAChB,MAAM;YACR,KAAK,aAAa,CAAC,IAAI;gBACrB,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,SAAS,EAAE,CAAC;gBAC/B,IAAI,IAAI,CAAC,MAAM,KAAK,YAAY,CAAC,MAAM,IAAI,IAAI,CAAC,MAAM,KAAK,YAAY,CAAC,MAAM;oBAAE,MAAM,IAAI,qBAAqB,CAAC,mBAAmB,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC;gBACnJ,IAAI,CAAC,WAAW,GAAG,CAAC,CAAC,CAAC;gBACtB,IAAI,CAAC,YAAY,GAAG,MAAM,CAAC,GAAG,CAAC;gBAC/B,IAAI,CAAC,QAAQ,GAAG,UAAU,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;gBACzC,IAAI,CAAC,eAAe,GAAG,MAAM,CAAC,GAAG,CAAC;gBAClC,IAAI,CAAC,WAAW,GAAG,UAAU,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;gBAC5C,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;gBAChB,IAAI,CAAC,SAAS,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC;gBACjD,MAAM,CAAC,GAAG,IAAI,CAAC,CAAC;gBAChB,IAAI,CAAC,OAAO,GAAG,MAAM,CAAC,GAAG,CAAC;gBAC1B,IAAI,CAAC,KAAK,GAAG,gBAAgB,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;gBAC5C,IAAI,IAAI,CAAC,MAAM,KAAK,YAAY,CAAC,MAAM;oBAAE,IAAI,CAAC,WAAW,EAAE,CAAC;gBAC5D,MAAM;QACV,CAAC;QACD,IAAI,CAAC,cAAc,EAAE,CAAC;QACtB,OAAO,IAAI,CAAC;IACd,CAAC;IAED,iFAAiF;IACjF,IAAI,WAAW;QACb,OAAO,IAAI,CAAC,WAAW,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,cAAc,CAAC,IAAI,CAAC,KAAK,EAAE,EAAE,GAAG,EAAE,IAAI,CAAC,WAAW,EAAE,CAAC,CAAC;IACpG,CAAC;IAED,0CAA0C;IAC1C,IAAI,YAAY;QACd,OAAO,cAAc,CAAC,IAAI,CAAC,KAAK,EAAE,EAAE,GAAG,EAAE,IAAI,CAAC,YAAY,EAAE,CAAC,CAAC;IAChE,CAAC;IAED,wCAAwC;IACxC,IAAI,eAAe;QACjB,OAAO,cAAc,CAAC,IAAI,CAAC,KAAK,EAAE,EAAE,GAAG,EAAE,IAAI,CAAC,eAAe,EAAE,CAAC,CAAC;IACnE,CAAC;IAED,4CAA4C;IAC5C,IAAI,OAAO;QACT,OAAO,cAAc,CAAC,IAAI,CAAC,KAAK,EAAE,EAAE,GAAG,EAAE,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC;IAC3D,CAAC;IAED,uEAAuE;IAEvE,0CAA0C;IAC1C,IAAI,GAAG;QACL,IAAI,IAAI,CAAC,QAAQ,KAAK,IAAI,EAAE,CAAC;YAC3B,QAAQ,IAAI,CAAC,OAAO,EAAE,CAAC;gBACrB,KAAK,iBAAiB,CAAC,IAAI;oBACzB,IAAI,CAAC,QAAQ,GAAG,aAAa,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC;oBAC1D,MAAM;gBACR,KAAK,iBAAiB,CAAC,KAAK,CAAC;gBAC7B,KAAK,iBAAiB,CAAC,KAAK;oBAC1B,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,QAAQ,EAAE,CAAC;oBACzC,MAAM;gBACR;oBACE,IAAI,CAAC,QAAQ,GAAG,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC;oBAClG,MAAM;YACV,CAAC;QACH,CAAC;QACD,OAAO,IAAI,CAAC,QAAQ,CAAC;IACvB,CAAC;IAED,uBAAuB;IACvB,IAAI,QAAQ;QACV,IAAI,IAAI,CAAC,OAAO,KAAK,iBAAiB,CAAC,KAAK,IAAI,IAAI,CAAC,OAAO,KAAK,iBAAiB,CAAC,KAAK;YAAE,MAAM,IAAI,KAAK,CAAC,eAAe,IAAI,CAAC,OAAO,GAAG,CAAC,CAAC;QAC1I,OAAO,cAAc,CAAC,IAAI,CAAC,KAAK,EAAE,EAAE,GAAG,EAAE,IAAI,CAAC,SAAS,EAAE,CAAC,CAAC;IAC7D,CAAC;IAED,mCAAmC;IACnC,IAAI,OAAO;QACT,IAAI,IAAI,CAAC,OAAO,KAAK,iBAAiB,CAAC,MAAM;YAAE,MAAM,IAAI,KAAK,CAAC,eAAe,IAAI,CAAC,OAAO,GAAG,CAAC,CAAC;QAC/F,OAAO,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,UAAU,CAAC,CAAC;IAC/E,CAAC;IAED,0EAA0E;IAE1E,MAAM,CAAC,MAAc;QACnB,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC;QAC3B,OAAQ,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAY,GAAG,CAAC,CAAC;IAC/C,CAAC;IAED,UAAU,CAAC,MAAc;QACvB,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,iBAAiB,CAAC,OAAO,CAAC,CAAC,KAAK,CAAC,CAAC;IAC3E,CAAC;IAED,QAAQ,CAAC,MAAc;QACrB,MAAM,KAAK,GAAG,gBAAgB,CAAC,IAAI,CAAC,KAAK,EAAE,EAAE,GAAG,EAAE,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,iBAAiB,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QACnG,IAAI,KAAK,GAAG,CAAC,UAAU,IAAI,KAAK,GAAG,UAAU;YAAE,MAAM,IAAI,qBAAqB,CAAC,8BAA8B,CAAC,CAAC;QAC/G,OAAO,KAAK,CAAC;IACf,CAAC;IAED,6BAA6B;IAC7B,QAAQ,CAAC,MAAc;QACrB,OAAO,cAAc,CAAC,IAAI,CAAC,KAAK,EAAE,EAAE,GAAG,EAAE,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,iBAAiB,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IAC5F,CAAC;IAED,SAAS,CAAC,MAAc;QACtB,MAAM,EAAE,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,iBAAiB,CAAC,MAAM,CAAC,CAAC;QAC1D,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE;YAAE,YAAY,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,GAAG,CAAC,CAAW,CAAC;QAC3E,OAAO,WAAW,CAAC,UAAU,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC;IACzC,CAAC;IAED,UAAU,CAAC,MAAc;QACvB,MAAM,EAAE,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,iBAAiB,CAAC,OAAO,CAAC,CAAC;QAC3D,MAAM,KAAK,GAAG,WAAW,CAAC,IAAI,CAAC,KAAK,EAAE,EAAE,GAAG,EAAE,CAAC,CAAC;QAC/C,0FAA0F;QAC1F,IAAI,CAAC,KAAK,GAAG,UAAU,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC,GAAG,IAAI,CAAC,GAAG,EAAE;YAAE,MAAM,IAAI,qBAAqB,CAAC,wBAAwB,CAAC,CAAC;QACzH,OAAO;YACL,EAAE,EAAE,WAAW,CAAC,IAAI,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC;YACrC,GAAG,EAAE,WAAW,CAAC,IAAI,CAAC,KAAK,EAAE,EAAE,GAAG,CAAC,CAAC,KAAK,CAAC;YAC1C,EAAE,EAAE,WAAW,CAAC,IAAI,CAAC,KAAK,EAAE,EAAE,GAAG,CAAC,CAAC,KAAK,CAAC;YACzC,KAAK,EAAE,CAAC,KAAK,IAAI,EAAE,CAAC,GAAG,IAAI;YAC3B,QAAQ,EAAE,KAAK,GAAG,CAAC;SACpB,CAAC;IACJ,CAAC;IAED,SAAS,CAAC,MAAc;QACtB,OAAO,UAAU,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC;IAC1C,CAAC;IAED,OAAO,CAAC,MAAc;QACpB,OAAO,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,iBAAiB,CAAC,MAAM,CAAC,CAAC,CAAC;IAC9E,CAAC;IAED,qCAAqC;IACrC,OAAO,CAAC,MAAc;QACpB,OAAO,aAAa,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,iBAAiB,CAAC,IAAI,CAAC,CAAC,CAAC;IACjF,CAAC;IAED,WAAW,CAAC,MAAc;QACxB,MAAM,EAAE,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,iBAAiB,CAAC,QAAQ,CAAC,CAAC;QAC5D,MAAM,KAAK,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;QAC5C,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,GAAG,CAAC,CAAW,CAAC;QAC1C,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,KAAK,CAAC,OAAO,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,IAAI,GAAG,CAAC;YAAE,MAAM,IAAI,qBAAqB,CAAC,yBAAyB,CAAC,CAAC;QAC3I,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;IACzB,CAAC;IAED,iBAAiB,CAAC,MAAc;QAC9B,MAAM,EAAE,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,iBAAiB,CAAC,cAAc,CAAC,CAAC;QAClE,MAAM,QAAQ,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;QAC/C,MAAM,GAAG,GAAI,IAAI,CAAC,KAAK,CAAC,EAAE,GAAG,CAAC,CAAY,GAAG,CAAE,IAAI,CAAC,KAAK,CAAC,EAAE,GAAG,CAAC,CAAY,IAAI,CAAC,CAAC,CAAC;QACnF,MAAM,OAAO,GAAG,GAAG,IAAI,MAAM,CAAC,CAAC,CAAC,GAAG,GAAG,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC;QACpD,MAAM,KAAK,GAAG,QAAQ,CAAC,GAAG,CAAC,MAAM,CAAC,UAAU,CAAC,OAAO,GAAG,SAAS,CAAC,CAAC,CAAC;QACnE,IACE,OAAO,GAAG,CAAC,GAAG;YACd,OAAO,GAAG,GAAG;YACb,QAAQ,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC;YACjC,QAAQ,CAAC,OAAO,CAAC,SAAS,CAAC,GAAG,CAAC;YAC/B,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC;YAC9B,KAAK,CAAC,OAAO,CAAC,SAAS,CAAC,GAAG,CAAC,EAC5B,CAAC;YACD,MAAM,IAAI,qBAAqB,CAAC,+BAA+B,CAAC,CAAC;QACnE,CAAC;QACD,OAAO,EAAE,QAAQ,EAAE,aAAa,EAAE,OAAO,EAAE,CAAC;IAC9C,CAAC;IAED,kCAAkC;IAClC,WAAW,CAAC,MAAc;QACxB,OAAO,cAAc,CAAC,IAAI,CAAC,KAAK,EAAE,EAAE,GAAG,EAAE,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,iBAAiB,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;IAC/F,CAAC;IAED,8EAA8E;IAC9E,QAAQ,CAAC,MAAc;QACrB,OAAO,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,iBAAiB,CAAC,KAAK,CAAC,CAAC,CAAC;IAC7E,CAAC;IAED,6EAA6E;IAErE,WAAW;QACjB,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC;QACxB,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC;QAC5B,MAAM,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC;QACjC,MAAM,WAAW,GAAG,CAAC,KAAK,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC;QACrC,IAAI,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC;QAC1B,MAAM,MAAM,GAAG,MAAM,CAAC,GAAG,CAAC;QAC1B,MAAM,CAAC,GAAG,IAAI,WAAW,CAAC;QAC1B,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC;QACtB,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC;QAC9B,KAAK,IAAI,MAAM,GAAG,CAAC,EAAE,MAAM,GAAG,KAAK,EAAE,MAAM,EAAE,EAAE,CAAC;YAC9C,IAAI,CAAE,IAAI,CAAC,MAAM,GAAG,CAAC,MAAM,IAAI,CAAC,CAAC,CAAY,GAAG,CAAC,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC;gBAC3E,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;gBACrB,SAAS;YACX,CAAC;YACD,OAAO,CAAC,MAAM,CAAC,GAAG,MAAM,CAAC,GAAG,CAAC;YAC7B,QAAQ,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC;gBAC5B,KAAK,iBAAiB,CAAC,OAAO;oBAC5B,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;oBAChB,MAAM,CAAC,GAAG,IAAI,CAAC,CAAC;oBAChB,MAAM;gBACR,KAAK,iBAAiB,CAAC,KAAK,CAAC;gBAC7B,KAAK,iBAAiB,CAAC,KAAK,CAAC;gBAC7B,KAAK,iBAAiB,CAAC,QAAQ;oBAC7B,cAAc,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;oBAC7B,MAAM;gBACR,KAAK,iBAAiB,CAAC,MAAM;oBAC3B,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;oBAChB,MAAM,CAAC,GAAG,IAAI,CAAC,CAAC;oBAChB,MAAM;gBACR,KAAK,iBAAiB,CAAC,OAAO,CAAC;gBAC/B,KAAK,iBAAiB,CAAC,IAAI;oBACzB,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;oBACjB,MAAM,CAAC,GAAG,IAAI,EAAE,CAAC;oBACjB,MAAM;gBACR,KAAK,iBAAiB,CAAC,QAAQ;oBAC7B,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;oBAChB,MAAM,CAAC,GAAG,IAAI,CAAC,CAAC;oBAChB,MAAM;gBACR,KAAK,iBAAiB,CAAC,cAAc;oBACnC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;oBACjB,MAAM,CAAC,GAAG,IAAI,EAAE,CAAC;oBACjB,MAAM;gBACR,KAAK,iBAAiB,CAAC,MAAM,CAAC;gBAC9B,KAAK,iBAAiB,CAAC,KAAK,CAAC,CAAC,CAAC;oBAC7B,MAAM,MAAM,GAAG,eAAe,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;oBAC7C,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;oBACrB,MAAM,CAAC,GAAG,IAAI,MAAM,CAAC;oBACrB,MAAM;gBACR,CAAC;gBACD;oBACE,MAAM,IAAI,qBAAqB,CAAC,uBAAuB,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YACnF,CAAC;QACH,CAAC;IACH,CAAC;IAEO,OAAO,CAAC,MAAc,EAAE,QAAgB;QAC9C,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC;QAC3B,IAAI,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,KAAK,QAAQ;YAAE,MAAM,IAAI,KAAK,CAAC,UAAU,MAAM,OAAO,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,SAAS,QAAQ,GAAG,CAAC,CAAC;QACtH,MAAM,MAAM,GAAG,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAW,CAAC;QAC/C,IAAI,MAAM,GAAG,CAAC;YAAE,MAAM,IAAI,KAAK,CAAC,UAAU,MAAM,WAAW,CAAC,CAAC;QAC7D,OAAO,MAAM,CAAC;IAChB,CAAC;IAEO,aAAa,CAAC,MAAc;QAClC,IAAI,CAAC,IAAI,CAAC,SAAS;YAAE,MAAM,IAAI,KAAK,CAAC,2CAA2C,CAAC,CAAC;QAClF,IAAI,CAAC,CAAC,MAAM,IAAI,CAAC,IAAI,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC;YAAE,MAAM,IAAI,UAAU,CAAC,UAAU,MAAM,mBAAmB,CAAC,CAAC;IAC/G,CAAC;IAEO,eAAe,CAAC,QAAgB;QACtC,MAAM,MAAM,GAAG,EAAE,GAAG,EAAE,QAAQ,EAAE,CAAC;QACjC,MAAM,MAAM,GAAG,eAAe,CAAC,IAAI,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;QACnD,OAAO,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,GAAG,EAAE,MAAM,CAAC,GAAG,GAAG,MAAM,CAAC,CAAC;IAC9D,CAAC;IAEO,SAAS;QACf,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;QAChB,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,CAAW,CAAC;IAClD,CAAC;IAEO,OAAO,CAAC,KAAa;QAC3B,IAAI,KAAK,GAAG,CAAC,IAAI,IAAI,CAAC,OAAO,CAAC,GAAG,GAAG,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM;YAAE,MAAM,IAAI,qBAAqB,CAAC,yBAAyB,CAAC,CAAC;IAC5H,CAAC;CACF;AAED,+BAA+B;AAC/B,MAAM,SAAS,GAAG,MAAM,CAAC,KAAK,CAAC,qBAAqB,CAAC,CAAC;AAEtD,MAAM,aAAa,GAAG,IAAI,WAAW,CAAC,CAAC,CAAC,CAAC;AACzC,MAAM,WAAW,GAAG,IAAI,QAAQ,CAAC,aAAa,CAAC,CAAC;AAChD,MAAM,YAAY,GAAG,IAAI,UAAU,CAAC,aAAa,CAAC,CAAC","sourcesContent":["// Twin of G9SyncData.Protocol/RowBatch/G9CRowBatchReader.cs: reads a G9RowBatch frame in either body layout. Forward\n// only; values are decoded from the body on demand.\nimport { G9ESyncColumnType } from '../../abstractions/enums.js';\nimport { readGuidBytes } from '../../abstractions/guid.js';\nimport { G9SyncKey } from '../../abstractions/key.js';\nimport { G9Long } from '../../abstractions/long.js';\nimport type { DecimalParts } from '../../internal/dotnetFormat.js';\nimport { utf8Decode } from '../../internal/utf8.js';\nimport { toRows } from './columnLayout.js';\nimport {\n type Cursor,\n G9ECompression,\n G9EPushRowOp,\n G9ERowBatchOp,\n G9RowBatchFormat,\n G9RowBatchFormatError,\n isRowBatchOp,\n readInt32LE,\n readVarint,\n readVarintInt32,\n readVarintLong,\n readZigZagLong,\n readZigZagNumber,\n} from './format.js';\nimport type { G9DateTimeOffsetValue, G9DateTimeValue } from './writer.js';\n\n/**\n * Decompresses a Brotli frame body. Returns exactly `expectedLength` bytes or throws. Node: `nodeBrotliDecompressor()`\n * (`@g9tm/syncdata/node`); Lynx: the native module of `@g9tm/syncdata-lynx`; anywhere: `jsBrotliDecompressor()`\n * (`@g9tm/syncdata/brotli-js`, pure JavaScript, slower).\n */\nexport interface G9FrameDecompressor {\n decompress(compressed: Uint8Array, expectedLength: number): Uint8Array | Promise<Uint8Array>;\n}\n\n/** The header of a frame, read without decoding the body. */\nexport interface G9FrameHeader {\n version: number;\n compression: number;\n bodyLength: number;\n}\n\n/** Validates a frame's header (magic, version, compression, body length, budget). */\nexport function readFrameHeader(frame: Uint8Array, maxBodyBytes: number = G9RowBatchFormat.MaxDecodedBytes): G9FrameHeader {\n if (!(maxBodyBytes > 0)) throw new RangeError('maxBodyBytes must be positive.');\n if (frame.length < G9RowBatchFormat.HeaderSize || frame[0] !== 0x47 || frame[1] !== 0x39 || frame[2] !== 0x52 || frame[3] !== 0x42) {\n throw new G9RowBatchFormatError('Not a G9RowBatch frame.');\n }\n const version = frame[4] as number;\n if (version !== G9RowBatchFormat.Version && version !== G9RowBatchFormat.ColumnVersion) {\n throw new G9RowBatchFormatError(`Unsupported G9RowBatch version ${version}.`);\n }\n const compression = frame[5] as number;\n const bodyLength = readInt32LE(frame, 6);\n if (bodyLength < 4 || bodyLength > G9RowBatchFormat.MaxDecodedBytes) throw new G9RowBatchFormatError('Invalid body length.');\n if (bodyLength > maxBodyBytes) {\n throw new G9RowBatchFormatError(`The frame declares a ${bodyLength}-byte body; this reader accepts at most ${maxBodyBytes} bytes.`);\n }\n if (compression !== G9ECompression.None && compression !== G9ECompression.Brotli) {\n throw new G9RowBatchFormatError(`Unknown compression ${compression}.`);\n }\n if (compression === G9ECompression.None && frame.length - G9RowBatchFormat.HeaderSize !== bodyLength) {\n throw new G9RowBatchFormatError('Body length mismatch.');\n }\n return { version, compression, bodyLength };\n}\n\nlet defaultDecompressor: G9FrameDecompressor | null = null;\n\n/**\n * Sets the Brotli decoder used wherever none is passed explicitly (the store, the engine's reconciliation). Call it\n * once at start-up: `useNodeBrotli()` (`@g9tm/syncdata/node`), `useLynxBrotli()` (`@g9tm/syncdata-lynx`) or\n * `setDefaultFrameDecompressor(jsBrotliDecompressor())` (`@g9tm/syncdata/brotli-js`).\n */\nexport function setDefaultFrameDecompressor(decompressor: G9FrameDecompressor | null): void {\n defaultDecompressor = decompressor;\n}\n\n/** The decoder set with {@link setDefaultFrameDecompressor}, or null. */\nexport function getDefaultFrameDecompressor(): G9FrameDecompressor | null {\n return defaultDecompressor;\n}\n\n/** Options of {@link openRowBatch}. */\nexport interface G9OpenRowBatchOptions {\n /** Brotli decoder for compressed frames (every frame the server sends over 128 bytes); the default decoder when omitted. */\n decompressor?: G9FrameDecompressor | null;\n /** The largest decoded body this caller allocates for (ADR-0051). */\n maxBodyBytes?: number;\n}\n\n/**\n * Validates, decompresses when needed, and opens a frame. Async because a Lynx decompressor crosses the native bridge;\n * an uncompressed frame resolves without waiting on anything.\n */\nexport async function openRowBatch(frame: Uint8Array, options?: G9OpenRowBatchOptions): Promise<G9RowBatchReader> {\n const header = readFrameHeader(frame, options?.maxBodyBytes);\n if (header.compression === G9ECompression.None) return G9RowBatchReader.fromBody(frame.subarray(G9RowBatchFormat.HeaderSize), header.version);\n const decompressor = options?.decompressor ?? defaultDecompressor;\n if (!decompressor) {\n throw new G9RowBatchFormatError('The frame is Brotli-compressed and no decompressor is configured (see G9FrameDecompressor).');\n }\n let body: Uint8Array;\n try {\n body = await decompressor.decompress(frame.subarray(G9RowBatchFormat.HeaderSize), header.bodyLength);\n } catch (error) {\n throw new G9RowBatchFormatError(`Brotli body could not be decompressed: ${error instanceof Error ? error.message : String(error)}`);\n }\n if (!body || body.length !== header.bodyLength) throw new G9RowBatchFormatError('Brotli body could not be decompressed.');\n return G9RowBatchReader.fromBody(body, header.version);\n}\n\n/** Opens an uncompressed frame synchronously (throws for a compressed one). */\nexport function openRowBatchSync(frame: Uint8Array, maxBodyBytes?: number): G9RowBatchReader {\n const header = readFrameHeader(frame, maxBodyBytes);\n if (header.compression !== G9ECompression.None) throw new G9RowBatchFormatError('The frame is compressed; use openRowBatch.');\n return G9RowBatchReader.fromBody(frame.subarray(G9RowBatchFormat.HeaderSize), header.version);\n}\n\n/** Reads the sections and rows of one G9RowBatch body. */\nexport class G9RowBatchReader {\n private readonly _body: Uint8Array;\n private readonly _cursor: Cursor = { pos: 4 };\n private _sectionsRemaining: number;\n private _sectionOpen = false;\n private _rowsRemaining = 0;\n private _types: number[] = [];\n private _offsets: number[] = [];\n private _keyStart = 0;\n private _keyLength = 0;\n private _keyText: string | null = null;\n private _versionPos = -1;\n private _sequencePos = -1;\n private _baseVersionPos = -1;\n private _hlcPos = -1;\n\n readonly sectionCount: number;\n\n // section\n op = 0;\n tableId = 0;\n keyType = 0;\n rowCount = 0;\n\n // row\n version = 0;\n pushOp = 0;\n sequence = 0;\n baseVersion = 0;\n dirtyMask: G9Long = G9Long.ZERO;\n hlcMs = 0;\n rowHash: G9Long = G9Long.ZERO;\n hasValues = false;\n\n private constructor(body: Uint8Array) {\n if (body.length < 4) throw new G9RowBatchFormatError('Row batch body is too short.');\n this._body = body;\n this.sectionCount = readInt32LE(body, 0);\n if (this.sectionCount < 0) throw new G9RowBatchFormatError('Negative section count.');\n this._sectionsRemaining = this.sectionCount;\n }\n\n /** Opens an already decompressed body of the given layout version. */\n static fromBody(body: Uint8Array, version: number): G9RowBatchReader {\n return new G9RowBatchReader(version === G9RowBatchFormat.ColumnVersion ? toRows(body) : body);\n }\n\n /** The decoded size of this frame's body (row-wise layout). */\n get bodyBytes(): number {\n return this._body.length;\n }\n\n get columnTypes(): readonly number[] {\n return this._types;\n }\n\n get columnCount(): number {\n return this._types.length;\n }\n\n /** Moves to the next section, skipping unread rows of the current one. */\n nextSection(): boolean {\n if (this._sectionOpen) {\n while (this.readRow()) {\n // skip\n }\n }\n if (this._sectionsRemaining === 0) {\n this._sectionOpen = false;\n return false;\n }\n const body = this._body;\n const cursor = this._cursor;\n this.op = this._readByte();\n if (!isRowBatchOp(this.op)) throw new G9RowBatchFormatError(`Unknown op ${this.op}.`);\n this.tableId = readVarintInt32(body, cursor);\n this.keyType = this._readByte();\n if (!G9SyncKey.isSupportedKeyType(this.keyType)) throw new G9RowBatchFormatError(`Unsupported key type ${this.keyType}.`);\n const columnCount = readVarintInt32(body, cursor);\n if (columnCount > 1024) throw new G9RowBatchFormatError('Too many columns.');\n this._ensure(columnCount + 4);\n const types: number[] = [];\n for (let i = 0; i < columnCount; i++) types.push(body[cursor.pos++] as number);\n this._types = types;\n this.rowCount = readInt32LE(body, cursor.pos);\n cursor.pos += 4;\n if (this.rowCount < 0) throw new G9RowBatchFormatError('Negative row count.');\n if (this._offsets.length < columnCount) this._offsets = new Array<number>(columnCount);\n this._rowsRemaining = this.rowCount;\n this._sectionsRemaining--;\n this._sectionOpen = true;\n return true;\n }\n\n /** Moves to the next row of the current section. */\n readRow(): boolean {\n if (!this._sectionOpen || this._rowsRemaining === 0) return false;\n const body = this._body;\n const cursor = this._cursor;\n this._keyText = null;\n this.hasValues = false;\n this.version = 0;\n this.rowHash = G9Long.ZERO;\n\n switch (this.keyType) {\n case G9ESyncColumnType.Guid:\n this._ensure(16);\n this._keyStart = cursor.pos;\n this._keyLength = 16;\n cursor.pos += 16;\n break;\n case G9ESyncColumnType.Int32:\n case G9ESyncColumnType.Int64:\n this._keyStart = cursor.pos;\n readVarintLong(body, cursor);\n this._keyLength = cursor.pos - this._keyStart;\n break;\n default: {\n const length = readVarintInt32(body, cursor);\n this._ensure(length);\n this._keyStart = cursor.pos;\n this._keyLength = length;\n cursor.pos += length;\n break;\n }\n }\n\n switch (this.op) {\n case G9ERowBatchOp.Upsert:\n case G9ERowBatchOp.Backfill:\n this._versionPos = cursor.pos;\n this.version = readVarint(body, cursor);\n this._readValues();\n break;\n case G9ERowBatchOp.Tombstone:\n case G9ERowBatchOp.MoveOut:\n this._versionPos = cursor.pos;\n this.version = readVarint(body, cursor);\n break;\n case G9ERowBatchOp.KeyVersions:\n this._versionPos = cursor.pos;\n this.version = readVarint(body, cursor);\n this._ensure(8);\n this.rowHash = G9Long.readLE(body, cursor.pos);\n cursor.pos += 8;\n break;\n case G9ERowBatchOp.Push:\n this.pushOp = this._readByte();\n if (this.pushOp !== G9EPushRowOp.Upsert && this.pushOp !== G9EPushRowOp.Delete) throw new G9RowBatchFormatError(`Unknown push op ${this.pushOp}.`);\n this._versionPos = -1;\n this._sequencePos = cursor.pos;\n this.sequence = readVarint(body, cursor);\n this._baseVersionPos = cursor.pos;\n this.baseVersion = readVarint(body, cursor);\n this._ensure(8);\n this.dirtyMask = G9Long.readLE(body, cursor.pos);\n cursor.pos += 8;\n this._hlcPos = cursor.pos;\n this.hlcMs = readZigZagNumber(body, cursor);\n if (this.pushOp === G9EPushRowOp.Upsert) this._readValues();\n break;\n }\n this._rowsRemaining--;\n return true;\n }\n\n /** The row's version, exact (the {@link version} number is exact below 2^53). */\n get versionLong(): G9Long {\n return this._versionPos < 0 ? G9Long.ZERO : readVarintLong(this._body, { pos: this._versionPos });\n }\n\n /** A push row's local sequence, exact. */\n get sequenceLong(): G9Long {\n return readVarintLong(this._body, { pos: this._sequencePos });\n }\n\n /** A push row's base version, exact. */\n get baseVersionLong(): G9Long {\n return readVarintLong(this._body, { pos: this._baseVersionPos });\n }\n\n /** A push row's HLC milliseconds, exact. */\n get hlcLong(): G9Long {\n return readZigZagLong(this._body, { pos: this._hlcPos });\n }\n\n // ---------------------------------------------------------------- key\n\n /** Canonical key text (see G9SyncKey). */\n get key(): string {\n if (this._keyText === null) {\n switch (this.keyType) {\n case G9ESyncColumnType.Guid:\n this._keyText = readGuidBytes(this._body, this._keyStart);\n break;\n case G9ESyncColumnType.Int32:\n case G9ESyncColumnType.Int64:\n this._keyText = this.keyInt64.toString();\n break;\n default:\n this._keyText = utf8Decode(this._body.subarray(this._keyStart, this._keyStart + this._keyLength));\n break;\n }\n }\n return this._keyText;\n }\n\n /** The integer key. */\n get keyInt64(): G9Long {\n if (this.keyType !== G9ESyncColumnType.Int32 && this.keyType !== G9ESyncColumnType.Int64) throw new Error(`Key type is ${this.keyType}.`);\n return readZigZagLong(this._body, { pos: this._keyStart });\n }\n\n /** UTF-8 bytes of a string key. */\n get keyUtf8(): Uint8Array {\n if (this.keyType !== G9ESyncColumnType.String) throw new Error(`Key type is ${this.keyType}.`);\n return this._body.subarray(this._keyStart, this._keyStart + this._keyLength);\n }\n\n // ---------------------------------------------------------------- values\n\n isNull(column: number): boolean {\n this._ensureValues(column);\n return (this._offsets[column] as number) < 0;\n }\n\n getBoolean(column: number): boolean {\n return this._body[this._offset(column, G9ESyncColumnType.Boolean)] !== 0;\n }\n\n getInt32(column: number): number {\n const value = readZigZagNumber(this._body, { pos: this._offset(column, G9ESyncColumnType.Int32) });\n if (value < -2147483648 || value > 2147483647) throw new G9RowBatchFormatError('Int32 value is out of range.');\n return value;\n }\n\n /** An Int64 value, exact. */\n getInt64(column: number): G9Long {\n return readZigZagLong(this._body, { pos: this._offset(column, G9ESyncColumnType.Int64) });\n }\n\n getDouble(column: number): number {\n const at = this._offset(column, G9ESyncColumnType.Double);\n for (let i = 0; i < 8; i++) DOUBLE_BYTES[i] = this._body[at + i] as number;\n return DOUBLE_VIEW.getFloat64(0, true);\n }\n\n getDecimal(column: number): DecimalParts {\n const at = this._offset(column, G9ESyncColumnType.Decimal);\n const flags = readInt32LE(this._body, at + 12);\n // decimal.GetBits: bits 0-15 and 24-30 of the flags are zero and the scale is at most 28.\n if ((flags & 0x7f00ffff) !== 0 || ((flags >> 16) & 0xff) > 28) throw new G9RowBatchFormatError('Invalid decimal value.');\n return {\n lo: readInt32LE(this._body, at) >>> 0,\n mid: readInt32LE(this._body, at + 4) >>> 0,\n hi: readInt32LE(this._body, at + 8) >>> 0,\n scale: (flags >> 16) & 0xff,\n negative: flags < 0,\n };\n }\n\n getString(column: number): string {\n return utf8Decode(this.getUtf8(column));\n }\n\n getUtf8(column: number): Uint8Array {\n return this._lengthPrefixed(this._offset(column, G9ESyncColumnType.String));\n }\n\n /** A GUID in canonical text form. */\n getGuid(column: number): string {\n return readGuidBytes(this._body, this._offset(column, G9ESyncColumnType.Guid));\n }\n\n getDateTime(column: number): G9DateTimeValue {\n const at = this._offset(column, G9ESyncColumnType.DateTime);\n const ticks = G9Long.readLE(this._body, at);\n const kind = this._body[at + 8] as number;\n if (ticks.compare(G9Long.ZERO) < 0 || ticks.compare(MAX_TICKS) > 0 || kind > 2) throw new G9RowBatchFormatError('Invalid DateTime value.');\n return { ticks, kind };\n }\n\n getDateTimeOffset(column: number): G9DateTimeOffsetValue {\n const at = this._offset(column, G9ESyncColumnType.DateTimeOffset);\n const utcTicks = G9Long.readLE(this._body, at);\n const raw = (this._body[at + 8] as number) | ((this._body[at + 9] as number) << 8);\n const minutes = raw >= 0x8000 ? raw - 0x10000 : raw;\n const local = utcTicks.add(G9Long.fromNumber(minutes * 600000000));\n if (\n minutes < -840 ||\n minutes > 840 ||\n utcTicks.compare(G9Long.ZERO) < 0 ||\n utcTicks.compare(MAX_TICKS) > 0 ||\n local.compare(G9Long.ZERO) < 0 ||\n local.compare(MAX_TICKS) > 0\n ) {\n throw new G9RowBatchFormatError('Invalid DateTimeOffset value.');\n }\n return { utcTicks, offsetMinutes: minutes };\n }\n\n /** A TimeSpan as ticks, exact. */\n getTimeSpan(column: number): G9Long {\n return readZigZagLong(this._body, { pos: this._offset(column, G9ESyncColumnType.TimeSpan) });\n }\n\n /** The bytes of a Bytes column (a view into the body; copy it to keep it). */\n getBytes(column: number): Uint8Array {\n return this._lengthPrefixed(this._offset(column, G9ESyncColumnType.Bytes));\n }\n\n // ---------------------------------------------------------------- internals\n\n private _readValues(): void {\n const body = this._body;\n const cursor = this._cursor;\n const count = this._types.length;\n const bitmapBytes = (count + 7) >> 3;\n this._ensure(bitmapBytes);\n const bitmap = cursor.pos;\n cursor.pos += bitmapBytes;\n this.hasValues = true;\n const offsets = this._offsets;\n for (let column = 0; column < count; column++) {\n if (((body[bitmap + (column >> 3)] as number) & (1 << (column & 7))) !== 0) {\n offsets[column] = -1;\n continue;\n }\n offsets[column] = cursor.pos;\n switch (this._types[column]) {\n case G9ESyncColumnType.Boolean:\n this._ensure(1);\n cursor.pos += 1;\n break;\n case G9ESyncColumnType.Int32:\n case G9ESyncColumnType.Int64:\n case G9ESyncColumnType.TimeSpan:\n readVarintLong(body, cursor);\n break;\n case G9ESyncColumnType.Double:\n this._ensure(8);\n cursor.pos += 8;\n break;\n case G9ESyncColumnType.Decimal:\n case G9ESyncColumnType.Guid:\n this._ensure(16);\n cursor.pos += 16;\n break;\n case G9ESyncColumnType.DateTime:\n this._ensure(9);\n cursor.pos += 9;\n break;\n case G9ESyncColumnType.DateTimeOffset:\n this._ensure(10);\n cursor.pos += 10;\n break;\n case G9ESyncColumnType.String:\n case G9ESyncColumnType.Bytes: {\n const length = readVarintInt32(body, cursor);\n this._ensure(length);\n cursor.pos += length;\n break;\n }\n default:\n throw new G9RowBatchFormatError(`Unknown column type ${this._types[column]}.`);\n }\n }\n }\n\n private _offset(column: number, expected: number): number {\n this._ensureValues(column);\n if (this._types[column] !== expected) throw new Error(`Column ${column} is ${this._types[column]}, not ${expected}.`);\n const offset = this._offsets[column] as number;\n if (offset < 0) throw new Error(`Column ${column} is NULL.`);\n return offset;\n }\n\n private _ensureValues(column: number): void {\n if (!this.hasValues) throw new Error('The current row carries no column values.');\n if (!(column >= 0 && column < this._types.length)) throw new RangeError(`Column ${column} is out of range.`);\n }\n\n private _lengthPrefixed(position: number): Uint8Array {\n const cursor = { pos: position };\n const length = readVarintInt32(this._body, cursor);\n return this._body.subarray(cursor.pos, cursor.pos + length);\n }\n\n private _readByte(): number {\n this._ensure(1);\n return this._body[this._cursor.pos++] as number;\n }\n\n private _ensure(count: number): void {\n if (count < 0 || this._cursor.pos + count > this._body.length) throw new G9RowBatchFormatError('Row batch is truncated.');\n }\n}\n\n/** DateTime.MaxValue.Ticks. */\nconst MAX_TICKS = G9Long.parse('3155378975999999999');\n\nconst DOUBLE_BUFFER = new ArrayBuffer(8);\nconst DOUBLE_VIEW = new DataView(DOUBLE_BUFFER);\nconst DOUBLE_BYTES = new Uint8Array(DOUBLE_BUFFER);\n"]}
|