xitdb 0.12.0 → 0.14.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 +120 -118
- package/dist/core-buffered-file.d.ts +23 -25
- package/dist/core-buffered-file.js +182 -0
- package/dist/core-file.d.ts +8 -10
- package/dist/core-file.js +105 -0
- package/dist/core-memory.d.ts +15 -15
- package/dist/core-memory.js +152 -0
- package/dist/core.d.ts +14 -14
- package/dist/core.js +1 -0
- package/dist/database.d.ts +204 -80
- package/dist/database.js +3047 -0
- package/dist/exceptions.d.ts +4 -0
- package/dist/exceptions.js +62 -0
- package/dist/hasher.d.ts +2 -1
- package/dist/hasher.js +49 -0
- package/dist/index.d.ts +30 -26
- package/dist/index.js +35 -3986
- package/dist/read-array-list.d.ts +8 -8
- package/dist/read-array-list.js +35 -0
- package/dist/read-counted-hash-map.d.ts +3 -3
- package/dist/read-counted-hash-map.js +19 -0
- package/dist/read-counted-hash-set.d.ts +3 -3
- package/dist/read-counted-hash-set.js +19 -0
- package/dist/read-cursor.d.ts +29 -23
- package/dist/read-cursor.js +577 -0
- package/dist/read-hash-map.d.ts +22 -22
- package/dist/read-hash-map.js +65 -0
- package/dist/read-hash-set.d.ts +13 -13
- package/dist/read-hash-set.js +47 -0
- package/dist/read-linked-array-list.d.ts +8 -8
- package/dist/read-linked-array-list.js +35 -0
- package/dist/read-sorted-map.d.ts +21 -0
- package/dist/read-sorted-map.js +73 -0
- package/dist/read-sorted-set.d.ts +19 -0
- package/dist/read-sorted-set.js +65 -0
- package/dist/slot-pointer.d.ts +1 -1
- package/dist/slot-pointer.js +11 -0
- package/dist/slot.d.ts +2 -2
- package/dist/slot.js +41 -0
- package/dist/slotted.d.ts +1 -1
- package/dist/slotted.js +1 -0
- package/dist/tag.d.ts +3 -1
- package/dist/tag.js +25 -0
- package/dist/write-array-list.d.ts +13 -14
- package/dist/write-array-list.js +42 -0
- package/dist/write-counted-hash-map.d.ts +4 -5
- package/dist/write-counted-hash-map.js +18 -0
- package/dist/write-counted-hash-set.d.ts +4 -5
- package/dist/write-counted-hash-set.js +18 -0
- package/dist/write-cursor.d.ts +15 -15
- package/dist/write-cursor.js +124 -0
- package/dist/write-hash-map.d.ts +22 -23
- package/dist/write-hash-map.js +90 -0
- package/dist/write-hash-set.d.ts +16 -17
- package/dist/write-hash-set.js +59 -0
- package/dist/write-linked-array-list.d.ts +16 -17
- package/dist/write-linked-array-list.js +52 -0
- package/dist/write-sorted-map.d.ts +12 -0
- package/dist/write-sorted-map.js +37 -0
- package/dist/write-sorted-set.d.ts +10 -0
- package/dist/write-sorted-set.js +29 -0
- package/dist/writeable-data.js +68 -0
- package/package.json +6 -6
package/dist/index.js
CHANGED
|
@@ -1,3986 +1,35 @@
|
|
|
1
|
-
//
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
};
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
Tag2[Tag2["COUNTED_HASH_SET"] = 13] = "COUNTED_HASH_SET";
|
|
37
|
-
})(Tag ||= {});
|
|
38
|
-
function tagValueOf(n) {
|
|
39
|
-
if (n < 0 || n > 13) {
|
|
40
|
-
throw new Error(`Invalid tag value: ${n}`);
|
|
41
|
-
}
|
|
42
|
-
return n;
|
|
43
|
-
}
|
|
44
|
-
// src/slot.ts
|
|
45
|
-
class Slot {
|
|
46
|
-
static LENGTH = 9;
|
|
47
|
-
value;
|
|
48
|
-
tag;
|
|
49
|
-
full;
|
|
50
|
-
constructor(value = 0n, tag = 0 /* NONE */, full = false) {
|
|
51
|
-
this.value = typeof value === "bigint" ? value : BigInt(value);
|
|
52
|
-
this.tag = tag;
|
|
53
|
-
this.full = full;
|
|
54
|
-
}
|
|
55
|
-
withTag(tag) {
|
|
56
|
-
return new Slot(this.value, tag, this.full);
|
|
57
|
-
}
|
|
58
|
-
withFull(full) {
|
|
59
|
-
return new Slot(this.value, this.tag, full);
|
|
60
|
-
}
|
|
61
|
-
empty() {
|
|
62
|
-
return this.tag === 0 /* NONE */ && !this.full;
|
|
63
|
-
}
|
|
64
|
-
toBytes() {
|
|
65
|
-
const buffer = new ArrayBuffer(Slot.LENGTH);
|
|
66
|
-
const view = new DataView(buffer);
|
|
67
|
-
let tagInt = this.full ? 128 : 0;
|
|
68
|
-
tagInt = tagInt | this.tag;
|
|
69
|
-
view.setUint8(0, tagInt);
|
|
70
|
-
view.setBigInt64(1, this.value, false);
|
|
71
|
-
return new Uint8Array(buffer);
|
|
72
|
-
}
|
|
73
|
-
static fromBytes(bytes) {
|
|
74
|
-
const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
|
|
75
|
-
const tagByte = view.getUint8(0);
|
|
76
|
-
const full = (tagByte & 128) !== 0;
|
|
77
|
-
const tag = tagValueOf(tagByte & 127);
|
|
78
|
-
const value = view.getBigInt64(1, false);
|
|
79
|
-
return new Slot(value, tag, full);
|
|
80
|
-
}
|
|
81
|
-
equals(other) {
|
|
82
|
-
return this.value === other.value && this.tag === other.tag && this.full === other.full;
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
// src/slot-pointer.ts
|
|
86
|
-
class SlotPointer {
|
|
87
|
-
position;
|
|
88
|
-
slot;
|
|
89
|
-
constructor(position, slot) {
|
|
90
|
-
this.position = position;
|
|
91
|
-
this.slot = slot;
|
|
92
|
-
}
|
|
93
|
-
withSlot(slot) {
|
|
94
|
-
return new SlotPointer(this.position, slot);
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
// src/exceptions.ts
|
|
98
|
-
class DatabaseException extends Error {
|
|
99
|
-
constructor(message) {
|
|
100
|
-
super(message);
|
|
101
|
-
this.name = this.constructor.name;
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
class NotImplementedException extends DatabaseException {
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
class UnreachableException extends DatabaseException {
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
class InvalidDatabaseException extends DatabaseException {
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
class InvalidVersionException extends DatabaseException {
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
class InvalidHashSizeException extends DatabaseException {
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
class KeyNotFoundException extends DatabaseException {
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
class WriteNotAllowedException extends DatabaseException {
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
class UnexpectedTagException extends DatabaseException {
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
class CursorNotWriteableException extends DatabaseException {
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
class ExpectedTxStartException extends DatabaseException {
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
class KeyOffsetExceededException extends DatabaseException {
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
class PathPartMustBeAtEndException extends DatabaseException {
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
class StreamTooLongException extends DatabaseException {
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
class EndOfStreamException extends DatabaseException {
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
class InvalidOffsetException extends DatabaseException {
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
class InvalidTopLevelTypeException extends DatabaseException {
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
class ExpectedUnsignedLongException extends DatabaseException {
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
class NoAvailableSlotsException extends DatabaseException {
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
class MustSetNewSlotsToFullException extends DatabaseException {
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
class EmptySlotException extends DatabaseException {
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
class ExpectedRootNodeException extends DatabaseException {
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
class InvalidFormatTagSizeException extends DatabaseException {
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
class UnexpectedWriterPositionException extends DatabaseException {
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
class MaxShiftExceededException extends DatabaseException {
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
class Uint64OverflowException extends DatabaseException {
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
class Int64OverflowException extends DatabaseException {
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
// src/writeable-data.ts
|
|
184
|
-
var UINT64_MAX = 2n ** 64n - 1n;
|
|
185
|
-
var INT64_MIN = -(2n ** 63n);
|
|
186
|
-
var INT64_MAX = 2n ** 63n - 1n;
|
|
187
|
-
|
|
188
|
-
class Uint {
|
|
189
|
-
value;
|
|
190
|
-
constructor(value) {
|
|
191
|
-
const bigintValue = BigInt(value);
|
|
192
|
-
if (bigintValue < 0n || bigintValue > UINT64_MAX) {
|
|
193
|
-
throw new Uint64OverflowException;
|
|
194
|
-
}
|
|
195
|
-
this.value = bigintValue;
|
|
196
|
-
}
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
class Int {
|
|
200
|
-
value;
|
|
201
|
-
constructor(value) {
|
|
202
|
-
const bigintValue = BigInt(value);
|
|
203
|
-
if (bigintValue < INT64_MIN || bigintValue > INT64_MAX) {
|
|
204
|
-
throw new Int64OverflowException;
|
|
205
|
-
}
|
|
206
|
-
this.value = bigintValue;
|
|
207
|
-
}
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
class Float {
|
|
211
|
-
value;
|
|
212
|
-
constructor(value) {
|
|
213
|
-
this.value = value;
|
|
214
|
-
}
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
class Bytes {
|
|
218
|
-
value;
|
|
219
|
-
formatTag;
|
|
220
|
-
constructor(value, formatTag) {
|
|
221
|
-
if (typeof value === "string") {
|
|
222
|
-
this.value = new TextEncoder().encode(value);
|
|
223
|
-
} else {
|
|
224
|
-
this.value = value;
|
|
225
|
-
}
|
|
226
|
-
if (formatTag === undefined || formatTag === null) {
|
|
227
|
-
this.formatTag = null;
|
|
228
|
-
} else if (typeof formatTag === "string") {
|
|
229
|
-
const encoded = new TextEncoder().encode(formatTag);
|
|
230
|
-
if (encoded.length !== 2) {
|
|
231
|
-
throw new InvalidFormatTagSizeException;
|
|
232
|
-
}
|
|
233
|
-
this.formatTag = encoded;
|
|
234
|
-
} else {
|
|
235
|
-
if (formatTag.length !== 2) {
|
|
236
|
-
throw new InvalidFormatTagSizeException;
|
|
237
|
-
}
|
|
238
|
-
this.formatTag = formatTag;
|
|
239
|
-
}
|
|
240
|
-
}
|
|
241
|
-
isShort() {
|
|
242
|
-
const totalSize = this.formatTag !== null ? 6 : 8;
|
|
243
|
-
if (this.value.length > totalSize)
|
|
244
|
-
return false;
|
|
245
|
-
for (const b of this.value) {
|
|
246
|
-
if (b === 0)
|
|
247
|
-
return false;
|
|
248
|
-
}
|
|
249
|
-
return true;
|
|
250
|
-
}
|
|
251
|
-
}
|
|
252
|
-
// src/core-memory.ts
|
|
253
|
-
class CoreMemory {
|
|
254
|
-
memory;
|
|
255
|
-
constructor() {
|
|
256
|
-
this.memory = new RandomAccessMemory;
|
|
257
|
-
}
|
|
258
|
-
reader() {
|
|
259
|
-
return this.memory;
|
|
260
|
-
}
|
|
261
|
-
writer() {
|
|
262
|
-
return this.memory;
|
|
263
|
-
}
|
|
264
|
-
async length() {
|
|
265
|
-
return this.memory.size();
|
|
266
|
-
}
|
|
267
|
-
async seek(pos) {
|
|
268
|
-
this.memory.seek(pos);
|
|
269
|
-
}
|
|
270
|
-
position() {
|
|
271
|
-
return this.memory.getPosition();
|
|
272
|
-
}
|
|
273
|
-
async setLength(len) {
|
|
274
|
-
this.memory.setLength(len);
|
|
275
|
-
}
|
|
276
|
-
async flush() {}
|
|
277
|
-
async sync() {}
|
|
278
|
-
}
|
|
279
|
-
|
|
280
|
-
class RandomAccessMemory {
|
|
281
|
-
buffer;
|
|
282
|
-
_position = 0;
|
|
283
|
-
_count = 0;
|
|
284
|
-
constructor(initialSize = 1024) {
|
|
285
|
-
this.buffer = new Uint8Array(initialSize);
|
|
286
|
-
}
|
|
287
|
-
ensureCapacity(minCapacity) {
|
|
288
|
-
if (minCapacity > this.buffer.length) {
|
|
289
|
-
let newCapacity = this.buffer.length * 2;
|
|
290
|
-
if (newCapacity < minCapacity) {
|
|
291
|
-
newCapacity = minCapacity;
|
|
292
|
-
}
|
|
293
|
-
const newBuffer = new Uint8Array(newCapacity);
|
|
294
|
-
newBuffer.set(this.buffer.subarray(0, this._count));
|
|
295
|
-
this.buffer = newBuffer;
|
|
296
|
-
}
|
|
297
|
-
}
|
|
298
|
-
size() {
|
|
299
|
-
return this._count;
|
|
300
|
-
}
|
|
301
|
-
seek(pos) {
|
|
302
|
-
if (pos > this._count) {
|
|
303
|
-
this._position = this._count;
|
|
304
|
-
} else {
|
|
305
|
-
this._position = pos;
|
|
306
|
-
}
|
|
307
|
-
}
|
|
308
|
-
getPosition() {
|
|
309
|
-
return this._position;
|
|
310
|
-
}
|
|
311
|
-
setLength(len) {
|
|
312
|
-
if (len === 0) {
|
|
313
|
-
this.reset();
|
|
314
|
-
} else {
|
|
315
|
-
if (len > this._count)
|
|
316
|
-
throw new Error("Cannot extend length");
|
|
317
|
-
this._count = len;
|
|
318
|
-
if (this._position > len) {
|
|
319
|
-
this._position = len;
|
|
320
|
-
}
|
|
321
|
-
}
|
|
322
|
-
}
|
|
323
|
-
reset() {
|
|
324
|
-
this._count = 0;
|
|
325
|
-
this._position = 0;
|
|
326
|
-
}
|
|
327
|
-
toByteArray() {
|
|
328
|
-
return this.buffer.slice(0, this._count);
|
|
329
|
-
}
|
|
330
|
-
async write(data) {
|
|
331
|
-
const pos = this._position;
|
|
332
|
-
if (pos < this._count) {
|
|
333
|
-
const bytesBeforeEnd = Math.min(data.length, this._count - pos);
|
|
334
|
-
for (let i = 0;i < bytesBeforeEnd; i++) {
|
|
335
|
-
this.buffer[pos + i] = data[i];
|
|
336
|
-
}
|
|
337
|
-
if (bytesBeforeEnd < data.length) {
|
|
338
|
-
const bytesAfterEnd = data.length - bytesBeforeEnd;
|
|
339
|
-
this.ensureCapacity(this._count + bytesAfterEnd);
|
|
340
|
-
this.buffer.set(data.subarray(bytesBeforeEnd), this._count);
|
|
341
|
-
this._count += bytesAfterEnd;
|
|
342
|
-
}
|
|
343
|
-
} else {
|
|
344
|
-
this.ensureCapacity(this._count + data.length);
|
|
345
|
-
this.buffer.set(data, this._count);
|
|
346
|
-
this._count += data.length;
|
|
347
|
-
}
|
|
348
|
-
this._position = pos + data.length;
|
|
349
|
-
}
|
|
350
|
-
async writeByte(v) {
|
|
351
|
-
await this.write(new Uint8Array([v & 255]));
|
|
352
|
-
}
|
|
353
|
-
async writeShort(v) {
|
|
354
|
-
const buffer = new ArrayBuffer(2);
|
|
355
|
-
const view = new DataView(buffer);
|
|
356
|
-
view.setInt16(0, v, false);
|
|
357
|
-
await this.write(new Uint8Array(buffer));
|
|
358
|
-
}
|
|
359
|
-
async writeLong(v) {
|
|
360
|
-
const buffer = new ArrayBuffer(8);
|
|
361
|
-
const view = new DataView(buffer);
|
|
362
|
-
view.setBigInt64(0, BigInt(v), false);
|
|
363
|
-
await this.write(new Uint8Array(buffer));
|
|
364
|
-
}
|
|
365
|
-
async readFully(b) {
|
|
366
|
-
const pos = this._position;
|
|
367
|
-
if (pos + b.length > this._count) {
|
|
368
|
-
throw new Error("End of stream");
|
|
369
|
-
}
|
|
370
|
-
b.set(this.buffer.subarray(pos, pos + b.length));
|
|
371
|
-
this._position = pos + b.length;
|
|
372
|
-
}
|
|
373
|
-
async readByte() {
|
|
374
|
-
const bytes = new Uint8Array(1);
|
|
375
|
-
await this.readFully(bytes);
|
|
376
|
-
return bytes[0];
|
|
377
|
-
}
|
|
378
|
-
async readShort() {
|
|
379
|
-
const bytes = new Uint8Array(2);
|
|
380
|
-
await this.readFully(bytes);
|
|
381
|
-
const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
|
|
382
|
-
return view.getInt16(0, false);
|
|
383
|
-
}
|
|
384
|
-
async readInt() {
|
|
385
|
-
const bytes = new Uint8Array(4);
|
|
386
|
-
await this.readFully(bytes);
|
|
387
|
-
const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
|
|
388
|
-
return view.getInt32(0, false);
|
|
389
|
-
}
|
|
390
|
-
async readLong() {
|
|
391
|
-
const bytes = new Uint8Array(8);
|
|
392
|
-
await this.readFully(bytes);
|
|
393
|
-
const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
|
|
394
|
-
return Number(view.getBigInt64(0, false));
|
|
395
|
-
}
|
|
396
|
-
}
|
|
397
|
-
// src/core-file.ts
|
|
398
|
-
import * as fs from "fs/promises";
|
|
399
|
-
|
|
400
|
-
class CoreFile {
|
|
401
|
-
filePath;
|
|
402
|
-
_position = 0;
|
|
403
|
-
fileHandle;
|
|
404
|
-
constructor(filePath, fileHandle) {
|
|
405
|
-
this.filePath = filePath;
|
|
406
|
-
this.fileHandle = fileHandle;
|
|
407
|
-
}
|
|
408
|
-
static async create(filePath) {
|
|
409
|
-
try {
|
|
410
|
-
await fs.access(filePath);
|
|
411
|
-
} catch {
|
|
412
|
-
await fs.writeFile(filePath, new Uint8Array(0));
|
|
413
|
-
}
|
|
414
|
-
const fileHandle = await fs.open(filePath, "r+");
|
|
415
|
-
return new CoreFile(filePath, fileHandle);
|
|
416
|
-
}
|
|
417
|
-
reader() {
|
|
418
|
-
return new FileDataReader(this);
|
|
419
|
-
}
|
|
420
|
-
writer() {
|
|
421
|
-
return new FileDataWriter(this);
|
|
422
|
-
}
|
|
423
|
-
async length() {
|
|
424
|
-
const stats = await this.fileHandle.stat();
|
|
425
|
-
return stats.size;
|
|
426
|
-
}
|
|
427
|
-
async seek(pos) {
|
|
428
|
-
this._position = pos;
|
|
429
|
-
}
|
|
430
|
-
position() {
|
|
431
|
-
return this._position;
|
|
432
|
-
}
|
|
433
|
-
async setLength(len) {
|
|
434
|
-
await this.fileHandle.truncate(len);
|
|
435
|
-
}
|
|
436
|
-
async flush() {}
|
|
437
|
-
async sync() {
|
|
438
|
-
await this.fileHandle.sync();
|
|
439
|
-
}
|
|
440
|
-
[Symbol.dispose]() {
|
|
441
|
-
import("fs").then((fs2) => {
|
|
442
|
-
fs2.closeSync(this.fileHandle.fd);
|
|
443
|
-
});
|
|
444
|
-
}
|
|
445
|
-
}
|
|
446
|
-
|
|
447
|
-
class FileDataReader {
|
|
448
|
-
core;
|
|
449
|
-
constructor(core) {
|
|
450
|
-
this.core = core;
|
|
451
|
-
}
|
|
452
|
-
async readFully(b) {
|
|
453
|
-
const position = this.core.position();
|
|
454
|
-
await this.core.fileHandle.readv([b], position);
|
|
455
|
-
this.core.seek(position + b.length);
|
|
456
|
-
}
|
|
457
|
-
async readByte() {
|
|
458
|
-
const bytes = new Uint8Array(1);
|
|
459
|
-
await this.readFully(bytes);
|
|
460
|
-
return bytes[0];
|
|
461
|
-
}
|
|
462
|
-
async readShort() {
|
|
463
|
-
const bytes = new Uint8Array(2);
|
|
464
|
-
await this.readFully(bytes);
|
|
465
|
-
const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
|
|
466
|
-
return view.getInt16(0, false);
|
|
467
|
-
}
|
|
468
|
-
async readInt() {
|
|
469
|
-
const bytes = new Uint8Array(4);
|
|
470
|
-
await this.readFully(bytes);
|
|
471
|
-
const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
|
|
472
|
-
return view.getInt32(0, false);
|
|
473
|
-
}
|
|
474
|
-
async readLong() {
|
|
475
|
-
const bytes = new Uint8Array(8);
|
|
476
|
-
await this.readFully(bytes);
|
|
477
|
-
const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
|
|
478
|
-
return Number(view.getBigInt64(0, false));
|
|
479
|
-
}
|
|
480
|
-
}
|
|
481
|
-
|
|
482
|
-
class FileDataWriter {
|
|
483
|
-
core;
|
|
484
|
-
constructor(core) {
|
|
485
|
-
this.core = core;
|
|
486
|
-
}
|
|
487
|
-
async write(buffer) {
|
|
488
|
-
const position = this.core.position();
|
|
489
|
-
await this.core.fileHandle.writev([buffer], position);
|
|
490
|
-
this.core.seek(position + buffer.length);
|
|
491
|
-
}
|
|
492
|
-
async writeByte(v) {
|
|
493
|
-
await this.write(new Uint8Array([v & 255]));
|
|
494
|
-
}
|
|
495
|
-
async writeShort(v) {
|
|
496
|
-
const buffer = new ArrayBuffer(2);
|
|
497
|
-
const view = new DataView(buffer);
|
|
498
|
-
view.setInt16(0, v, false);
|
|
499
|
-
await this.write(new Uint8Array(buffer));
|
|
500
|
-
}
|
|
501
|
-
async writeLong(v) {
|
|
502
|
-
const buffer = new ArrayBuffer(8);
|
|
503
|
-
const view = new DataView(buffer);
|
|
504
|
-
view.setBigInt64(0, BigInt(v), false);
|
|
505
|
-
await this.write(new Uint8Array(buffer));
|
|
506
|
-
}
|
|
507
|
-
}
|
|
508
|
-
// src/core-buffered-file.ts
|
|
509
|
-
class CoreBufferedFile {
|
|
510
|
-
file;
|
|
511
|
-
constructor(file) {
|
|
512
|
-
this.file = file;
|
|
513
|
-
}
|
|
514
|
-
static async create(filePath, bufferSize) {
|
|
515
|
-
const file = await RandomAccessBufferedFile.create(filePath, bufferSize);
|
|
516
|
-
return new CoreBufferedFile(file);
|
|
517
|
-
}
|
|
518
|
-
reader() {
|
|
519
|
-
return this.file;
|
|
520
|
-
}
|
|
521
|
-
writer() {
|
|
522
|
-
return this.file;
|
|
523
|
-
}
|
|
524
|
-
async length() {
|
|
525
|
-
return await this.file.length();
|
|
526
|
-
}
|
|
527
|
-
async seek(pos) {
|
|
528
|
-
await this.file.seek(pos);
|
|
529
|
-
}
|
|
530
|
-
position() {
|
|
531
|
-
return this.file.position();
|
|
532
|
-
}
|
|
533
|
-
async setLength(len) {
|
|
534
|
-
await this.file.setLength(len);
|
|
535
|
-
}
|
|
536
|
-
async flush() {
|
|
537
|
-
await this.file.flush();
|
|
538
|
-
}
|
|
539
|
-
async sync() {
|
|
540
|
-
await this.file.sync();
|
|
541
|
-
}
|
|
542
|
-
[Symbol.dispose]() {
|
|
543
|
-
this.file.file[Symbol.dispose]();
|
|
544
|
-
}
|
|
545
|
-
}
|
|
546
|
-
var DEFAULT_BUFFER_SIZE = 8 * 1024 * 1024;
|
|
547
|
-
|
|
548
|
-
class RandomAccessBufferedFile {
|
|
549
|
-
file;
|
|
550
|
-
memory;
|
|
551
|
-
bufferSize;
|
|
552
|
-
filePos;
|
|
553
|
-
memoryPos;
|
|
554
|
-
constructor(file, bufferSize) {
|
|
555
|
-
this.file = file;
|
|
556
|
-
this.memory = new CoreMemory;
|
|
557
|
-
this.bufferSize = bufferSize;
|
|
558
|
-
this.filePos = 0;
|
|
559
|
-
this.memoryPos = 0;
|
|
560
|
-
}
|
|
561
|
-
static async create(filePath, bufferSize = DEFAULT_BUFFER_SIZE) {
|
|
562
|
-
const file = await CoreFile.create(filePath);
|
|
563
|
-
return new RandomAccessBufferedFile(file, bufferSize);
|
|
564
|
-
}
|
|
565
|
-
async seek(pos) {
|
|
566
|
-
if (pos > this.memoryPos + await this.memory.length()) {
|
|
567
|
-
await this.flush();
|
|
568
|
-
}
|
|
569
|
-
this.filePos = pos;
|
|
570
|
-
if (await this.memory.length() === 0) {
|
|
571
|
-
this.memoryPos = pos;
|
|
572
|
-
}
|
|
573
|
-
}
|
|
574
|
-
async length() {
|
|
575
|
-
return Math.max(this.memoryPos + await this.memory.length(), await this.file.length());
|
|
576
|
-
}
|
|
577
|
-
position() {
|
|
578
|
-
return this.filePos;
|
|
579
|
-
}
|
|
580
|
-
async setLength(len) {
|
|
581
|
-
await this.flush();
|
|
582
|
-
await this.file.setLength(len);
|
|
583
|
-
this.filePos = Math.min(len, this.filePos);
|
|
584
|
-
}
|
|
585
|
-
async flush() {
|
|
586
|
-
if (await this.memory.length() > 0) {
|
|
587
|
-
await this.file.seek(this.memoryPos);
|
|
588
|
-
await this.file.writer().write(this.memory.memory.toByteArray());
|
|
589
|
-
this.memoryPos = 0;
|
|
590
|
-
this.memory.memory.reset();
|
|
591
|
-
}
|
|
592
|
-
}
|
|
593
|
-
async sync() {
|
|
594
|
-
await this.flush();
|
|
595
|
-
await this.file.sync();
|
|
596
|
-
}
|
|
597
|
-
async write(buffer) {
|
|
598
|
-
if (await this.memory.length() + buffer.length > this.bufferSize) {
|
|
599
|
-
await this.flush();
|
|
600
|
-
}
|
|
601
|
-
if (this.filePos >= this.memoryPos && this.filePos <= this.memoryPos + await this.memory.length()) {
|
|
602
|
-
this.memory.seek(this.filePos - this.memoryPos);
|
|
603
|
-
await this.memory.memory.write(buffer);
|
|
604
|
-
} else {
|
|
605
|
-
await this.file.seek(this.filePos);
|
|
606
|
-
await this.file.writer().write(buffer);
|
|
607
|
-
}
|
|
608
|
-
this.filePos += buffer.length;
|
|
609
|
-
}
|
|
610
|
-
async writeByte(v) {
|
|
611
|
-
await this.write(new Uint8Array([v & 255]));
|
|
612
|
-
}
|
|
613
|
-
async writeShort(v) {
|
|
614
|
-
const buffer = new ArrayBuffer(2);
|
|
615
|
-
const view = new DataView(buffer);
|
|
616
|
-
view.setInt16(0, v & 65535, false);
|
|
617
|
-
await this.write(new Uint8Array(buffer));
|
|
618
|
-
}
|
|
619
|
-
async writeLong(v) {
|
|
620
|
-
const buffer = new ArrayBuffer(8);
|
|
621
|
-
const view = new DataView(buffer);
|
|
622
|
-
view.setBigInt64(0, BigInt(v), false);
|
|
623
|
-
await this.write(new Uint8Array(buffer));
|
|
624
|
-
}
|
|
625
|
-
async readFully(buffer) {
|
|
626
|
-
let pos = 0;
|
|
627
|
-
if (this.filePos < this.memoryPos) {
|
|
628
|
-
const sizeBeforeMem = Math.min(this.memoryPos - this.filePos, buffer.length);
|
|
629
|
-
const tempBuffer = new Uint8Array(sizeBeforeMem);
|
|
630
|
-
await this.file.seek(this.filePos);
|
|
631
|
-
await this.file.reader().readFully(tempBuffer);
|
|
632
|
-
buffer.set(tempBuffer, pos);
|
|
633
|
-
pos += sizeBeforeMem;
|
|
634
|
-
this.filePos += sizeBeforeMem;
|
|
635
|
-
}
|
|
636
|
-
if (pos === buffer.length)
|
|
637
|
-
return;
|
|
638
|
-
if (this.filePos >= this.memoryPos && this.filePos < this.memoryPos + await this.memory.length()) {
|
|
639
|
-
const memPos = this.filePos - this.memoryPos;
|
|
640
|
-
const sizeInMem = Math.min(await this.memory.length() - memPos, buffer.length - pos);
|
|
641
|
-
this.memory.seek(memPos);
|
|
642
|
-
const memBuffer = new Uint8Array(sizeInMem);
|
|
643
|
-
await this.memory.memory.readFully(memBuffer);
|
|
644
|
-
buffer.set(memBuffer, pos);
|
|
645
|
-
pos += sizeInMem;
|
|
646
|
-
this.filePos += sizeInMem;
|
|
647
|
-
}
|
|
648
|
-
if (pos === buffer.length)
|
|
649
|
-
return;
|
|
650
|
-
if (this.filePos >= this.memoryPos + await this.memory.length()) {
|
|
651
|
-
const sizeAfterMem = buffer.length - pos;
|
|
652
|
-
const tempBuffer = new Uint8Array(sizeAfterMem);
|
|
653
|
-
await this.file.seek(this.filePos);
|
|
654
|
-
await this.file.reader().readFully(tempBuffer);
|
|
655
|
-
buffer.set(tempBuffer, pos);
|
|
656
|
-
pos += sizeAfterMem;
|
|
657
|
-
this.filePos += sizeAfterMem;
|
|
658
|
-
}
|
|
659
|
-
}
|
|
660
|
-
async readByte() {
|
|
661
|
-
const bytes = new Uint8Array(1);
|
|
662
|
-
await this.readFully(bytes);
|
|
663
|
-
return bytes[0];
|
|
664
|
-
}
|
|
665
|
-
async readShort() {
|
|
666
|
-
const bytes = new Uint8Array(2);
|
|
667
|
-
await this.readFully(bytes);
|
|
668
|
-
const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
|
|
669
|
-
return view.getInt16(0, false);
|
|
670
|
-
}
|
|
671
|
-
async readInt() {
|
|
672
|
-
const bytes = new Uint8Array(4);
|
|
673
|
-
await this.readFully(bytes);
|
|
674
|
-
const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
|
|
675
|
-
return view.getInt32(0, false);
|
|
676
|
-
}
|
|
677
|
-
async readLong() {
|
|
678
|
-
const bytes = new Uint8Array(8);
|
|
679
|
-
await this.readFully(bytes);
|
|
680
|
-
const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
|
|
681
|
-
return Number(view.getBigInt64(0, false));
|
|
682
|
-
}
|
|
683
|
-
}
|
|
684
|
-
// src/hasher.ts
|
|
685
|
-
class Hasher {
|
|
686
|
-
algorithm;
|
|
687
|
-
id;
|
|
688
|
-
digestLength;
|
|
689
|
-
constructor(algorithm, id = 0) {
|
|
690
|
-
this.algorithm = algorithm;
|
|
691
|
-
this.id = id;
|
|
692
|
-
switch (algorithm) {
|
|
693
|
-
case "SHA-1":
|
|
694
|
-
this.digestLength = 20;
|
|
695
|
-
break;
|
|
696
|
-
case "SHA-256":
|
|
697
|
-
this.digestLength = 32;
|
|
698
|
-
break;
|
|
699
|
-
case "SHA-384":
|
|
700
|
-
this.digestLength = 48;
|
|
701
|
-
break;
|
|
702
|
-
case "SHA-512":
|
|
703
|
-
this.digestLength = 64;
|
|
704
|
-
break;
|
|
705
|
-
default:
|
|
706
|
-
throw new Error(`Unsupported hash algorithm: ${algorithm}`);
|
|
707
|
-
}
|
|
708
|
-
}
|
|
709
|
-
async digest(data) {
|
|
710
|
-
const buffer = new ArrayBuffer(data.length);
|
|
711
|
-
const view = new Uint8Array(buffer);
|
|
712
|
-
view.set(data);
|
|
713
|
-
const hashBuffer = await crypto.subtle.digest(this.algorithm, buffer);
|
|
714
|
-
return new Uint8Array(hashBuffer);
|
|
715
|
-
}
|
|
716
|
-
static stringToId(hashIdName) {
|
|
717
|
-
const bytes = new TextEncoder().encode(hashIdName);
|
|
718
|
-
if (bytes.length !== 4) {
|
|
719
|
-
throw new Error("Name must be exactly four bytes long");
|
|
720
|
-
}
|
|
721
|
-
const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
|
|
722
|
-
return view.getInt32(0, false);
|
|
723
|
-
}
|
|
724
|
-
static idToString(id) {
|
|
725
|
-
const buffer = new ArrayBuffer(4);
|
|
726
|
-
const view = new DataView(buffer);
|
|
727
|
-
view.setInt32(0, id, false);
|
|
728
|
-
return new TextDecoder().decode(new Uint8Array(buffer));
|
|
729
|
-
}
|
|
730
|
-
}
|
|
731
|
-
// src/read-cursor.ts
|
|
732
|
-
class KeyValuePairCursor {
|
|
733
|
-
valueCursor;
|
|
734
|
-
keyCursor;
|
|
735
|
-
hash;
|
|
736
|
-
constructor(valueCursor, keyCursor, hash) {
|
|
737
|
-
this.valueCursor = valueCursor;
|
|
738
|
-
this.keyCursor = keyCursor;
|
|
739
|
-
this.hash = hash;
|
|
740
|
-
}
|
|
741
|
-
}
|
|
742
|
-
|
|
743
|
-
class ReadCursor {
|
|
744
|
-
slotPtr;
|
|
745
|
-
db;
|
|
746
|
-
constructor(slotPtr, db) {
|
|
747
|
-
this.slotPtr = slotPtr;
|
|
748
|
-
this.db = db;
|
|
749
|
-
}
|
|
750
|
-
slot() {
|
|
751
|
-
return this.slotPtr.slot;
|
|
752
|
-
}
|
|
753
|
-
async readPath(path) {
|
|
754
|
-
try {
|
|
755
|
-
const slotPtr = await this.db.readSlotPointer(0 /* READ_ONLY */, path, 0, this.slotPtr);
|
|
756
|
-
return new ReadCursor(slotPtr, this.db);
|
|
757
|
-
} catch (e) {
|
|
758
|
-
if (e instanceof KeyNotFoundException) {
|
|
759
|
-
return null;
|
|
760
|
-
}
|
|
761
|
-
throw e;
|
|
762
|
-
}
|
|
763
|
-
}
|
|
764
|
-
async readPathSlot(path) {
|
|
765
|
-
try {
|
|
766
|
-
const slotPtr = await this.db.readSlotPointer(0 /* READ_ONLY */, path, 0, this.slotPtr);
|
|
767
|
-
if (!slotPtr.slot.empty()) {
|
|
768
|
-
return slotPtr.slot;
|
|
769
|
-
} else {
|
|
770
|
-
return null;
|
|
771
|
-
}
|
|
772
|
-
} catch (e) {
|
|
773
|
-
if (e instanceof KeyNotFoundException) {
|
|
774
|
-
return null;
|
|
775
|
-
}
|
|
776
|
-
throw e;
|
|
777
|
-
}
|
|
778
|
-
}
|
|
779
|
-
readUint() {
|
|
780
|
-
if (this.slotPtr.slot.tag !== 8 /* UINT */) {
|
|
781
|
-
throw new UnexpectedTagException;
|
|
782
|
-
}
|
|
783
|
-
if (this.slotPtr.slot.value < 0n)
|
|
784
|
-
throw new ExpectedUnsignedLongException;
|
|
785
|
-
return Number(this.slotPtr.slot.value);
|
|
786
|
-
}
|
|
787
|
-
readInt() {
|
|
788
|
-
if (this.slotPtr.slot.tag !== 9 /* INT */) {
|
|
789
|
-
throw new UnexpectedTagException;
|
|
790
|
-
}
|
|
791
|
-
return Number(this.slotPtr.slot.value);
|
|
792
|
-
}
|
|
793
|
-
readFloat() {
|
|
794
|
-
if (this.slotPtr.slot.tag !== 10 /* FLOAT */) {
|
|
795
|
-
throw new UnexpectedTagException;
|
|
796
|
-
}
|
|
797
|
-
const buffer = new ArrayBuffer(8);
|
|
798
|
-
const view = new DataView(buffer);
|
|
799
|
-
view.setBigInt64(0, this.slotPtr.slot.value, false);
|
|
800
|
-
return view.getFloat64(0, false);
|
|
801
|
-
}
|
|
802
|
-
async readBytes(maxSizeMaybe = null) {
|
|
803
|
-
const bytesObj = await this.readBytesObject(maxSizeMaybe);
|
|
804
|
-
return bytesObj.value;
|
|
805
|
-
}
|
|
806
|
-
async readBytesObject(maxSizeMaybe = null) {
|
|
807
|
-
const reader = this.db.core.reader();
|
|
808
|
-
switch (this.slotPtr.slot.tag) {
|
|
809
|
-
case 0 /* NONE */:
|
|
810
|
-
return new Bytes(new Uint8Array(0));
|
|
811
|
-
case 6 /* BYTES */: {
|
|
812
|
-
await this.db.core.seek(Number(this.slotPtr.slot.value));
|
|
813
|
-
const valueSize = await reader.readLong();
|
|
814
|
-
if (maxSizeMaybe !== null && valueSize > maxSizeMaybe) {
|
|
815
|
-
throw new StreamTooLongException;
|
|
816
|
-
}
|
|
817
|
-
const startPosition = this.db.core.position();
|
|
818
|
-
const value = new Uint8Array(valueSize);
|
|
819
|
-
await reader.readFully(value);
|
|
820
|
-
let formatTag = null;
|
|
821
|
-
if (this.slotPtr.slot.full) {
|
|
822
|
-
await this.db.core.seek(startPosition + valueSize);
|
|
823
|
-
formatTag = new Uint8Array(2);
|
|
824
|
-
await reader.readFully(formatTag);
|
|
825
|
-
}
|
|
826
|
-
return new Bytes(value, formatTag);
|
|
827
|
-
}
|
|
828
|
-
case 7 /* SHORT_BYTES */: {
|
|
829
|
-
const buffer = new ArrayBuffer(8);
|
|
830
|
-
const view = new DataView(buffer);
|
|
831
|
-
view.setBigInt64(0, this.slotPtr.slot.value, false);
|
|
832
|
-
const bytes = new Uint8Array(buffer);
|
|
833
|
-
const totalSize = this.slotPtr.slot.full ? bytes.length - 2 : bytes.length;
|
|
834
|
-
let valueSize = 0;
|
|
835
|
-
for (const b of bytes) {
|
|
836
|
-
if (b === 0 || valueSize === totalSize)
|
|
837
|
-
break;
|
|
838
|
-
valueSize += 1;
|
|
839
|
-
}
|
|
840
|
-
if (maxSizeMaybe !== null && valueSize > maxSizeMaybe) {
|
|
841
|
-
throw new StreamTooLongException;
|
|
842
|
-
}
|
|
843
|
-
let formatTag = null;
|
|
844
|
-
if (this.slotPtr.slot.full) {
|
|
845
|
-
formatTag = bytes.slice(totalSize, bytes.length);
|
|
846
|
-
}
|
|
847
|
-
return new Bytes(bytes.slice(0, valueSize), formatTag);
|
|
848
|
-
}
|
|
849
|
-
default:
|
|
850
|
-
throw new UnexpectedTagException;
|
|
851
|
-
}
|
|
852
|
-
}
|
|
853
|
-
async readKeyValuePair() {
|
|
854
|
-
const reader = this.db.core.reader();
|
|
855
|
-
if (this.slotPtr.slot.tag !== 5 /* KV_PAIR */) {
|
|
856
|
-
throw new UnexpectedTagException;
|
|
857
|
-
}
|
|
858
|
-
await this.db.core.seek(Number(this.slotPtr.slot.value));
|
|
859
|
-
const kvPairBytes = new Uint8Array(KeyValuePair.length(this.db.header.hashSize));
|
|
860
|
-
await reader.readFully(kvPairBytes);
|
|
861
|
-
const kvPair = KeyValuePair.fromBytes(kvPairBytes, this.db.header.hashSize);
|
|
862
|
-
const hashPos = Number(this.slotPtr.slot.value);
|
|
863
|
-
const keySlotPos = hashPos + this.db.header.hashSize;
|
|
864
|
-
const valueSlotPos = keySlotPos + Slot.LENGTH;
|
|
865
|
-
return new KeyValuePairCursor(new ReadCursor(new SlotPointer(valueSlotPos, kvPair.valueSlot), this.db), new ReadCursor(new SlotPointer(keySlotPos, kvPair.keySlot), this.db), kvPair.hash);
|
|
866
|
-
}
|
|
867
|
-
async reader() {
|
|
868
|
-
const reader = this.db.core.reader();
|
|
869
|
-
switch (this.slotPtr.slot.tag) {
|
|
870
|
-
case 6 /* BYTES */: {
|
|
871
|
-
await this.db.core.seek(Number(this.slotPtr.slot.value));
|
|
872
|
-
const size = await reader.readLong();
|
|
873
|
-
const startPosition = this.db.core.position();
|
|
874
|
-
return new Reader(this, size, startPosition, 0);
|
|
875
|
-
}
|
|
876
|
-
case 7 /* SHORT_BYTES */: {
|
|
877
|
-
const buffer = new ArrayBuffer(8);
|
|
878
|
-
const view = new DataView(buffer);
|
|
879
|
-
view.setBigInt64(0, this.slotPtr.slot.value, false);
|
|
880
|
-
const bytes = new Uint8Array(buffer);
|
|
881
|
-
const totalSize = this.slotPtr.slot.full ? bytes.length - 2 : bytes.length;
|
|
882
|
-
let valueSize = 0;
|
|
883
|
-
for (const b of bytes) {
|
|
884
|
-
if (b === 0 || valueSize === totalSize)
|
|
885
|
-
break;
|
|
886
|
-
valueSize += 1;
|
|
887
|
-
}
|
|
888
|
-
const startPosition = this.slotPtr.position + 1;
|
|
889
|
-
return new Reader(this, valueSize, startPosition, 0);
|
|
890
|
-
}
|
|
891
|
-
default:
|
|
892
|
-
throw new UnexpectedTagException;
|
|
893
|
-
}
|
|
894
|
-
}
|
|
895
|
-
async count() {
|
|
896
|
-
const reader = this.db.core.reader();
|
|
897
|
-
switch (this.slotPtr.slot.tag) {
|
|
898
|
-
case 0 /* NONE */:
|
|
899
|
-
return 0;
|
|
900
|
-
case 2 /* ARRAY_LIST */: {
|
|
901
|
-
await this.db.core.seek(Number(this.slotPtr.slot.value));
|
|
902
|
-
const headerBytes = new Uint8Array(ArrayListHeader.LENGTH);
|
|
903
|
-
await reader.readFully(headerBytes);
|
|
904
|
-
const header = ArrayListHeader.fromBytes(headerBytes);
|
|
905
|
-
return header.size;
|
|
906
|
-
}
|
|
907
|
-
case 3 /* LINKED_ARRAY_LIST */: {
|
|
908
|
-
await this.db.core.seek(Number(this.slotPtr.slot.value));
|
|
909
|
-
const headerBytes = new Uint8Array(LinkedArrayListHeader.LENGTH);
|
|
910
|
-
await reader.readFully(headerBytes);
|
|
911
|
-
const header = LinkedArrayListHeader.fromBytes(headerBytes);
|
|
912
|
-
return header.size;
|
|
913
|
-
}
|
|
914
|
-
case 6 /* BYTES */: {
|
|
915
|
-
await this.db.core.seek(Number(this.slotPtr.slot.value));
|
|
916
|
-
return reader.readLong();
|
|
917
|
-
}
|
|
918
|
-
case 7 /* SHORT_BYTES */: {
|
|
919
|
-
const buffer = new ArrayBuffer(8);
|
|
920
|
-
const view = new DataView(buffer);
|
|
921
|
-
view.setBigInt64(0, this.slotPtr.slot.value, false);
|
|
922
|
-
const bytes = new Uint8Array(buffer);
|
|
923
|
-
const totalSize = this.slotPtr.slot.full ? bytes.length - 2 : bytes.length;
|
|
924
|
-
let size = 0;
|
|
925
|
-
for (const b of bytes) {
|
|
926
|
-
if (b === 0 || size === totalSize)
|
|
927
|
-
break;
|
|
928
|
-
size += 1;
|
|
929
|
-
}
|
|
930
|
-
return size;
|
|
931
|
-
}
|
|
932
|
-
case 12 /* COUNTED_HASH_MAP */:
|
|
933
|
-
case 13 /* COUNTED_HASH_SET */: {
|
|
934
|
-
await this.db.core.seek(Number(this.slotPtr.slot.value));
|
|
935
|
-
return reader.readLong();
|
|
936
|
-
}
|
|
937
|
-
default:
|
|
938
|
-
throw new UnexpectedTagException;
|
|
939
|
-
}
|
|
940
|
-
}
|
|
941
|
-
async* [Symbol.asyncIterator]() {
|
|
942
|
-
const iterator = await this.iterator();
|
|
943
|
-
while (await iterator.hasNext()) {
|
|
944
|
-
const next = await iterator.next();
|
|
945
|
-
if (next !== null) {
|
|
946
|
-
yield next;
|
|
947
|
-
}
|
|
948
|
-
}
|
|
949
|
-
}
|
|
950
|
-
async iterator() {
|
|
951
|
-
const iterator = new CursorIterator(this);
|
|
952
|
-
await iterator.init();
|
|
953
|
-
return iterator;
|
|
954
|
-
}
|
|
955
|
-
}
|
|
956
|
-
|
|
957
|
-
class Reader {
|
|
958
|
-
parent;
|
|
959
|
-
size;
|
|
960
|
-
startPosition;
|
|
961
|
-
relativePosition;
|
|
962
|
-
constructor(parent, size, startPosition, relativePosition) {
|
|
963
|
-
this.parent = parent;
|
|
964
|
-
this.size = size;
|
|
965
|
-
this.startPosition = startPosition;
|
|
966
|
-
this.relativePosition = relativePosition;
|
|
967
|
-
}
|
|
968
|
-
async read(buffer) {
|
|
969
|
-
if (this.size < this.relativePosition)
|
|
970
|
-
throw new EndOfStreamException;
|
|
971
|
-
await this.parent.db.core.seek(this.startPosition + this.relativePosition);
|
|
972
|
-
const readSize = Math.min(buffer.length, this.size - this.relativePosition);
|
|
973
|
-
if (readSize === 0)
|
|
974
|
-
return -1;
|
|
975
|
-
const reader = this.parent.db.core.reader();
|
|
976
|
-
const tempBuffer = new Uint8Array(readSize);
|
|
977
|
-
await reader.readFully(tempBuffer);
|
|
978
|
-
buffer.set(tempBuffer);
|
|
979
|
-
this.relativePosition += readSize;
|
|
980
|
-
return readSize;
|
|
981
|
-
}
|
|
982
|
-
async readFully(buffer) {
|
|
983
|
-
if (this.size < this.relativePosition || this.size - this.relativePosition < buffer.length) {
|
|
984
|
-
throw new EndOfStreamException;
|
|
985
|
-
}
|
|
986
|
-
await this.parent.db.core.seek(this.startPosition + this.relativePosition);
|
|
987
|
-
const reader = this.parent.db.core.reader();
|
|
988
|
-
await reader.readFully(buffer);
|
|
989
|
-
this.relativePosition += buffer.length;
|
|
990
|
-
}
|
|
991
|
-
async readByte() {
|
|
992
|
-
const bytes = new Uint8Array(1);
|
|
993
|
-
await this.readFully(bytes);
|
|
994
|
-
return bytes[0];
|
|
995
|
-
}
|
|
996
|
-
async readShort() {
|
|
997
|
-
const readSize = 2;
|
|
998
|
-
const bytes = new Uint8Array(readSize);
|
|
999
|
-
await this.readFully(bytes);
|
|
1000
|
-
const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
|
|
1001
|
-
return view.getInt16(0, false);
|
|
1002
|
-
}
|
|
1003
|
-
async readInt() {
|
|
1004
|
-
const readSize = 4;
|
|
1005
|
-
const bytes = new Uint8Array(readSize);
|
|
1006
|
-
await this.readFully(bytes);
|
|
1007
|
-
const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
|
|
1008
|
-
return view.getInt32(0, false);
|
|
1009
|
-
}
|
|
1010
|
-
async readLong() {
|
|
1011
|
-
const readSize = 8;
|
|
1012
|
-
const bytes = new Uint8Array(readSize);
|
|
1013
|
-
await this.readFully(bytes);
|
|
1014
|
-
const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
|
|
1015
|
-
return Number(view.getBigInt64(0, false));
|
|
1016
|
-
}
|
|
1017
|
-
seek(position) {
|
|
1018
|
-
if (position > this.size) {
|
|
1019
|
-
throw new InvalidOffsetException;
|
|
1020
|
-
}
|
|
1021
|
-
this.relativePosition = position;
|
|
1022
|
-
}
|
|
1023
|
-
}
|
|
1024
|
-
|
|
1025
|
-
class IteratorLevel {
|
|
1026
|
-
position;
|
|
1027
|
-
block;
|
|
1028
|
-
index;
|
|
1029
|
-
constructor(position, block, index) {
|
|
1030
|
-
this.position = position;
|
|
1031
|
-
this.block = block;
|
|
1032
|
-
this.index = index;
|
|
1033
|
-
}
|
|
1034
|
-
}
|
|
1035
|
-
|
|
1036
|
-
class CursorIterator {
|
|
1037
|
-
cursor;
|
|
1038
|
-
size = 0;
|
|
1039
|
-
index = 0;
|
|
1040
|
-
stack = [];
|
|
1041
|
-
nextCursorMaybe = null;
|
|
1042
|
-
constructor(cursor) {
|
|
1043
|
-
this.cursor = cursor;
|
|
1044
|
-
}
|
|
1045
|
-
async init() {
|
|
1046
|
-
switch (this.cursor.slotPtr.slot.tag) {
|
|
1047
|
-
case 0 /* NONE */:
|
|
1048
|
-
this.size = 0;
|
|
1049
|
-
this.index = 0;
|
|
1050
|
-
this.stack = [];
|
|
1051
|
-
break;
|
|
1052
|
-
case 2 /* ARRAY_LIST */: {
|
|
1053
|
-
const position = Number(this.cursor.slotPtr.slot.value);
|
|
1054
|
-
await this.cursor.db.core.seek(position);
|
|
1055
|
-
const reader = this.cursor.db.core.reader();
|
|
1056
|
-
const headerBytes = new Uint8Array(ArrayListHeader.LENGTH);
|
|
1057
|
-
await reader.readFully(headerBytes);
|
|
1058
|
-
const header = ArrayListHeader.fromBytes(headerBytes);
|
|
1059
|
-
this.size = await this.cursor.count();
|
|
1060
|
-
this.index = 0;
|
|
1061
|
-
this.stack = await this.initStack(this.cursor, header.ptr, INDEX_BLOCK_SIZE);
|
|
1062
|
-
break;
|
|
1063
|
-
}
|
|
1064
|
-
case 3 /* LINKED_ARRAY_LIST */: {
|
|
1065
|
-
const position = Number(this.cursor.slotPtr.slot.value);
|
|
1066
|
-
await this.cursor.db.core.seek(position);
|
|
1067
|
-
const reader = this.cursor.db.core.reader();
|
|
1068
|
-
const headerBytes = new Uint8Array(LinkedArrayListHeader.LENGTH);
|
|
1069
|
-
await reader.readFully(headerBytes);
|
|
1070
|
-
const header = LinkedArrayListHeader.fromBytes(headerBytes);
|
|
1071
|
-
this.size = await this.cursor.count();
|
|
1072
|
-
this.index = 0;
|
|
1073
|
-
this.stack = await this.initStack(this.cursor, header.ptr, LINKED_ARRAY_LIST_INDEX_BLOCK_SIZE);
|
|
1074
|
-
break;
|
|
1075
|
-
}
|
|
1076
|
-
case 4 /* HASH_MAP */:
|
|
1077
|
-
case 11 /* HASH_SET */:
|
|
1078
|
-
this.size = 0;
|
|
1079
|
-
this.index = 0;
|
|
1080
|
-
this.stack = await this.initStack(this.cursor, Number(this.cursor.slotPtr.slot.value), INDEX_BLOCK_SIZE);
|
|
1081
|
-
break;
|
|
1082
|
-
case 12 /* COUNTED_HASH_MAP */:
|
|
1083
|
-
case 13 /* COUNTED_HASH_SET */:
|
|
1084
|
-
this.size = 0;
|
|
1085
|
-
this.index = 0;
|
|
1086
|
-
this.stack = await this.initStack(this.cursor, Number(this.cursor.slotPtr.slot.value) + 8, INDEX_BLOCK_SIZE);
|
|
1087
|
-
break;
|
|
1088
|
-
default:
|
|
1089
|
-
throw new UnexpectedTagException;
|
|
1090
|
-
}
|
|
1091
|
-
}
|
|
1092
|
-
async initStack(cursor, position, blockSize) {
|
|
1093
|
-
await cursor.db.core.seek(position);
|
|
1094
|
-
const reader = cursor.db.core.reader();
|
|
1095
|
-
const indexBlockBytes = new Uint8Array(blockSize);
|
|
1096
|
-
await reader.readFully(indexBlockBytes);
|
|
1097
|
-
const indexBlock = new Array(SLOT_COUNT);
|
|
1098
|
-
const slotSize = blockSize / SLOT_COUNT;
|
|
1099
|
-
for (let i = 0;i < SLOT_COUNT; i++) {
|
|
1100
|
-
const slotBytes = indexBlockBytes.slice(i * slotSize, i * slotSize + Slot.LENGTH);
|
|
1101
|
-
indexBlock[i] = Slot.fromBytes(slotBytes);
|
|
1102
|
-
}
|
|
1103
|
-
return [new IteratorLevel(position, indexBlock, 0)];
|
|
1104
|
-
}
|
|
1105
|
-
async hasNext() {
|
|
1106
|
-
switch (this.cursor.slotPtr.slot.tag) {
|
|
1107
|
-
case 0 /* NONE */:
|
|
1108
|
-
return false;
|
|
1109
|
-
case 2 /* ARRAY_LIST */:
|
|
1110
|
-
return this.index < this.size;
|
|
1111
|
-
case 3 /* LINKED_ARRAY_LIST */:
|
|
1112
|
-
return this.index < this.size;
|
|
1113
|
-
case 4 /* HASH_MAP */:
|
|
1114
|
-
case 11 /* HASH_SET */:
|
|
1115
|
-
case 12 /* COUNTED_HASH_MAP */:
|
|
1116
|
-
case 13 /* COUNTED_HASH_SET */:
|
|
1117
|
-
if (this.nextCursorMaybe === null) {
|
|
1118
|
-
this.nextCursorMaybe = await this.nextInternal(INDEX_BLOCK_SIZE);
|
|
1119
|
-
}
|
|
1120
|
-
return this.nextCursorMaybe !== null;
|
|
1121
|
-
default:
|
|
1122
|
-
return false;
|
|
1123
|
-
}
|
|
1124
|
-
}
|
|
1125
|
-
async next() {
|
|
1126
|
-
switch (this.cursor.slotPtr.slot.tag) {
|
|
1127
|
-
case 0 /* NONE */:
|
|
1128
|
-
return null;
|
|
1129
|
-
case 2 /* ARRAY_LIST */:
|
|
1130
|
-
if (!await this.hasNext())
|
|
1131
|
-
return null;
|
|
1132
|
-
this.index += 1;
|
|
1133
|
-
return this.nextInternal(INDEX_BLOCK_SIZE);
|
|
1134
|
-
case 3 /* LINKED_ARRAY_LIST */:
|
|
1135
|
-
if (!await this.hasNext())
|
|
1136
|
-
return null;
|
|
1137
|
-
this.index += 1;
|
|
1138
|
-
return this.nextInternal(LINKED_ARRAY_LIST_INDEX_BLOCK_SIZE);
|
|
1139
|
-
case 4 /* HASH_MAP */:
|
|
1140
|
-
case 11 /* HASH_SET */:
|
|
1141
|
-
case 12 /* COUNTED_HASH_MAP */:
|
|
1142
|
-
case 13 /* COUNTED_HASH_SET */:
|
|
1143
|
-
if (this.nextCursorMaybe !== null) {
|
|
1144
|
-
const nextCursor = this.nextCursorMaybe;
|
|
1145
|
-
this.nextCursorMaybe = null;
|
|
1146
|
-
return nextCursor;
|
|
1147
|
-
} else {
|
|
1148
|
-
return this.nextInternal(INDEX_BLOCK_SIZE);
|
|
1149
|
-
}
|
|
1150
|
-
default:
|
|
1151
|
-
throw new UnexpectedTagException;
|
|
1152
|
-
}
|
|
1153
|
-
}
|
|
1154
|
-
async nextInternal(blockSize) {
|
|
1155
|
-
while (this.stack.length > 0) {
|
|
1156
|
-
const level = this.stack[this.stack.length - 1];
|
|
1157
|
-
if (level.index === level.block.length) {
|
|
1158
|
-
this.stack.pop();
|
|
1159
|
-
if (this.stack.length > 0) {
|
|
1160
|
-
this.stack[this.stack.length - 1].index += 1;
|
|
1161
|
-
}
|
|
1162
|
-
continue;
|
|
1163
|
-
} else {
|
|
1164
|
-
const nextSlot = level.block[level.index];
|
|
1165
|
-
if (nextSlot.tag === 1 /* INDEX */) {
|
|
1166
|
-
const nextPos = Number(nextSlot.value);
|
|
1167
|
-
await this.cursor.db.core.seek(nextPos);
|
|
1168
|
-
const reader = this.cursor.db.core.reader();
|
|
1169
|
-
const indexBlockBytes = new Uint8Array(blockSize);
|
|
1170
|
-
await reader.readFully(indexBlockBytes);
|
|
1171
|
-
const indexBlock = new Array(SLOT_COUNT);
|
|
1172
|
-
const slotSize = blockSize / SLOT_COUNT;
|
|
1173
|
-
for (let i = 0;i < SLOT_COUNT; i++) {
|
|
1174
|
-
const slotBytes = indexBlockBytes.slice(i * slotSize, i * slotSize + Slot.LENGTH);
|
|
1175
|
-
indexBlock[i] = Slot.fromBytes(slotBytes);
|
|
1176
|
-
}
|
|
1177
|
-
this.stack.push(new IteratorLevel(nextPos, indexBlock, 0));
|
|
1178
|
-
continue;
|
|
1179
|
-
} else {
|
|
1180
|
-
this.stack[this.stack.length - 1].index += 1;
|
|
1181
|
-
if (!nextSlot.empty()) {
|
|
1182
|
-
const position = level.position + level.index * Slot.LENGTH;
|
|
1183
|
-
return new ReadCursor(new SlotPointer(position, nextSlot), this.cursor.db);
|
|
1184
|
-
} else {
|
|
1185
|
-
continue;
|
|
1186
|
-
}
|
|
1187
|
-
}
|
|
1188
|
-
}
|
|
1189
|
-
}
|
|
1190
|
-
return null;
|
|
1191
|
-
}
|
|
1192
|
-
}
|
|
1193
|
-
|
|
1194
|
-
// src/write-cursor.ts
|
|
1195
|
-
class WriteKeyValuePairCursor extends KeyValuePairCursor {
|
|
1196
|
-
valueCursor;
|
|
1197
|
-
keyCursor;
|
|
1198
|
-
constructor(valueCursor, keyCursor, hash) {
|
|
1199
|
-
super(valueCursor, keyCursor, hash);
|
|
1200
|
-
this.valueCursor = valueCursor;
|
|
1201
|
-
this.keyCursor = keyCursor;
|
|
1202
|
-
}
|
|
1203
|
-
}
|
|
1204
|
-
|
|
1205
|
-
class WriteCursor extends ReadCursor {
|
|
1206
|
-
constructor(slotPtr, db) {
|
|
1207
|
-
super(slotPtr, db);
|
|
1208
|
-
}
|
|
1209
|
-
async writePath(path) {
|
|
1210
|
-
const slotPtr = await this.db.readSlotPointer(1 /* READ_WRITE */, path, 0, this.slotPtr);
|
|
1211
|
-
if (this.db.txStart === null) {
|
|
1212
|
-
await this.db.core.sync();
|
|
1213
|
-
}
|
|
1214
|
-
return new WriteCursor(slotPtr, this.db);
|
|
1215
|
-
}
|
|
1216
|
-
async write(data) {
|
|
1217
|
-
const cursor = await this.writePath([new WriteData(data)]);
|
|
1218
|
-
this.slotPtr = cursor.slotPtr;
|
|
1219
|
-
}
|
|
1220
|
-
async writeIfEmpty(data) {
|
|
1221
|
-
if (this.slotPtr.slot.empty()) {
|
|
1222
|
-
await this.write(data);
|
|
1223
|
-
}
|
|
1224
|
-
}
|
|
1225
|
-
async readKeyValuePair() {
|
|
1226
|
-
const kvPairCursor = await super.readKeyValuePair();
|
|
1227
|
-
return new WriteKeyValuePairCursor(new WriteCursor(kvPairCursor.valueCursor.slotPtr, this.db), new WriteCursor(kvPairCursor.keyCursor.slotPtr, this.db), kvPairCursor.hash);
|
|
1228
|
-
}
|
|
1229
|
-
async writer() {
|
|
1230
|
-
const writer = this.db.core.writer();
|
|
1231
|
-
const ptrPos = await this.db.core.length();
|
|
1232
|
-
await this.db.core.seek(ptrPos);
|
|
1233
|
-
await writer.writeLong(0);
|
|
1234
|
-
const startPosition = await this.db.core.length();
|
|
1235
|
-
return new Writer(this, 0, new Slot(ptrPos, 6 /* BYTES */), startPosition, 0);
|
|
1236
|
-
}
|
|
1237
|
-
async* [Symbol.asyncIterator]() {
|
|
1238
|
-
const iterator = await this.iterator();
|
|
1239
|
-
while (await iterator.hasNext()) {
|
|
1240
|
-
const next = await iterator.next();
|
|
1241
|
-
if (next !== null) {
|
|
1242
|
-
yield next;
|
|
1243
|
-
}
|
|
1244
|
-
}
|
|
1245
|
-
}
|
|
1246
|
-
async iterator() {
|
|
1247
|
-
const iterator = new WriteCursorIterator(this);
|
|
1248
|
-
await iterator.init();
|
|
1249
|
-
return iterator;
|
|
1250
|
-
}
|
|
1251
|
-
}
|
|
1252
|
-
|
|
1253
|
-
class Writer {
|
|
1254
|
-
parent;
|
|
1255
|
-
size;
|
|
1256
|
-
slot;
|
|
1257
|
-
startPosition;
|
|
1258
|
-
relativePosition;
|
|
1259
|
-
formatTag = null;
|
|
1260
|
-
constructor(parent, size, slot, startPosition, relativePosition) {
|
|
1261
|
-
this.parent = parent;
|
|
1262
|
-
this.size = size;
|
|
1263
|
-
this.slot = slot;
|
|
1264
|
-
this.startPosition = startPosition;
|
|
1265
|
-
this.relativePosition = relativePosition;
|
|
1266
|
-
}
|
|
1267
|
-
async write(buffer) {
|
|
1268
|
-
if (this.size < this.relativePosition)
|
|
1269
|
-
throw new EndOfStreamException;
|
|
1270
|
-
await this.parent.db.core.seek(this.startPosition + this.relativePosition);
|
|
1271
|
-
const writer = this.parent.db.core.writer();
|
|
1272
|
-
await writer.write(buffer);
|
|
1273
|
-
this.relativePosition += buffer.length;
|
|
1274
|
-
if (this.relativePosition > this.size) {
|
|
1275
|
-
this.size = this.relativePosition;
|
|
1276
|
-
}
|
|
1277
|
-
}
|
|
1278
|
-
async finish() {
|
|
1279
|
-
const writer = this.parent.db.core.writer();
|
|
1280
|
-
if (this.formatTag !== null) {
|
|
1281
|
-
this.slot = this.slot.withFull(true);
|
|
1282
|
-
const formatTagPos = await this.parent.db.core.length();
|
|
1283
|
-
await this.parent.db.core.seek(formatTagPos);
|
|
1284
|
-
if (this.startPosition + this.size !== formatTagPos)
|
|
1285
|
-
throw new UnexpectedWriterPositionException;
|
|
1286
|
-
await writer.write(this.formatTag);
|
|
1287
|
-
}
|
|
1288
|
-
await this.parent.db.core.seek(Number(this.slot.value));
|
|
1289
|
-
await writer.writeLong(this.size);
|
|
1290
|
-
if (this.parent.slotPtr.position === null)
|
|
1291
|
-
throw new CursorNotWriteableException;
|
|
1292
|
-
const position = this.parent.slotPtr.position;
|
|
1293
|
-
await this.parent.db.core.seek(position);
|
|
1294
|
-
await writer.write(this.slot.toBytes());
|
|
1295
|
-
this.parent.slotPtr = this.parent.slotPtr.withSlot(this.slot);
|
|
1296
|
-
}
|
|
1297
|
-
seek(position) {
|
|
1298
|
-
if (position <= this.size) {
|
|
1299
|
-
this.relativePosition = position;
|
|
1300
|
-
}
|
|
1301
|
-
}
|
|
1302
|
-
}
|
|
1303
|
-
|
|
1304
|
-
class WriteCursorIterator extends CursorIterator {
|
|
1305
|
-
constructor(cursor) {
|
|
1306
|
-
super(cursor);
|
|
1307
|
-
}
|
|
1308
|
-
async next() {
|
|
1309
|
-
const readCursor = await super.next();
|
|
1310
|
-
if (readCursor !== null) {
|
|
1311
|
-
return new WriteCursor(readCursor.slotPtr, readCursor.db);
|
|
1312
|
-
} else {
|
|
1313
|
-
return null;
|
|
1314
|
-
}
|
|
1315
|
-
}
|
|
1316
|
-
}
|
|
1317
|
-
|
|
1318
|
-
// src/database.ts
|
|
1319
|
-
var VERSION = 0;
|
|
1320
|
-
var MAGIC_NUMBER = new Uint8Array([120, 105, 116]);
|
|
1321
|
-
var BIT_COUNT = 4;
|
|
1322
|
-
var SLOT_COUNT = 1 << BIT_COUNT;
|
|
1323
|
-
var MASK = BigInt(SLOT_COUNT - 1);
|
|
1324
|
-
var INDEX_BLOCK_SIZE = Slot.LENGTH * SLOT_COUNT;
|
|
1325
|
-
var LINKED_ARRAY_LIST_SLOT_LENGTH = 8 + Slot.LENGTH;
|
|
1326
|
-
var LINKED_ARRAY_LIST_INDEX_BLOCK_SIZE = LINKED_ARRAY_LIST_SLOT_LENGTH * SLOT_COUNT;
|
|
1327
|
-
var MAX_BRANCH_LENGTH = 16;
|
|
1328
|
-
var WriteMode;
|
|
1329
|
-
((WriteMode2) => {
|
|
1330
|
-
WriteMode2[WriteMode2["READ_ONLY"] = 0] = "READ_ONLY";
|
|
1331
|
-
WriteMode2[WriteMode2["READ_WRITE"] = 1] = "READ_WRITE";
|
|
1332
|
-
})(WriteMode ||= {});
|
|
1333
|
-
|
|
1334
|
-
class Header {
|
|
1335
|
-
hashId;
|
|
1336
|
-
hashSize;
|
|
1337
|
-
version;
|
|
1338
|
-
tag;
|
|
1339
|
-
magicNumber;
|
|
1340
|
-
static LENGTH = 12;
|
|
1341
|
-
constructor(hashId, hashSize, version, tag, magicNumber) {
|
|
1342
|
-
this.hashId = hashId;
|
|
1343
|
-
this.hashSize = hashSize;
|
|
1344
|
-
this.version = version;
|
|
1345
|
-
this.tag = tag;
|
|
1346
|
-
this.magicNumber = magicNumber;
|
|
1347
|
-
}
|
|
1348
|
-
toBytes() {
|
|
1349
|
-
const buffer = new ArrayBuffer(Header.LENGTH);
|
|
1350
|
-
const view = new DataView(buffer);
|
|
1351
|
-
const arr = new Uint8Array(buffer);
|
|
1352
|
-
arr.set(this.magicNumber, 0);
|
|
1353
|
-
view.setUint8(3, this.tag);
|
|
1354
|
-
view.setInt16(4, this.version, false);
|
|
1355
|
-
view.setInt16(6, this.hashSize, false);
|
|
1356
|
-
view.setInt32(8, this.hashId, false);
|
|
1357
|
-
return arr;
|
|
1358
|
-
}
|
|
1359
|
-
static async read(core) {
|
|
1360
|
-
const reader = core.reader();
|
|
1361
|
-
const magicNumber = new Uint8Array(3);
|
|
1362
|
-
await reader.readFully(magicNumber);
|
|
1363
|
-
const tagByte = await reader.readByte();
|
|
1364
|
-
const tag = tagValueOf(tagByte & 127);
|
|
1365
|
-
const version = await reader.readShort();
|
|
1366
|
-
const hashSize = await reader.readShort();
|
|
1367
|
-
const hashId = await reader.readInt();
|
|
1368
|
-
return new Header(hashId, hashSize, version, tag, magicNumber);
|
|
1369
|
-
}
|
|
1370
|
-
async write(core) {
|
|
1371
|
-
const writer = core.writer();
|
|
1372
|
-
await writer.write(this.toBytes());
|
|
1373
|
-
}
|
|
1374
|
-
validate() {
|
|
1375
|
-
if (!arraysEqual(this.magicNumber, MAGIC_NUMBER)) {
|
|
1376
|
-
throw new InvalidDatabaseException;
|
|
1377
|
-
}
|
|
1378
|
-
if (this.version > VERSION) {
|
|
1379
|
-
throw new InvalidVersionException;
|
|
1380
|
-
}
|
|
1381
|
-
}
|
|
1382
|
-
withTag(tag) {
|
|
1383
|
-
return new Header(this.hashId, this.hashSize, this.version, tag, this.magicNumber);
|
|
1384
|
-
}
|
|
1385
|
-
}
|
|
1386
|
-
|
|
1387
|
-
class ArrayListHeader {
|
|
1388
|
-
ptr;
|
|
1389
|
-
size;
|
|
1390
|
-
static LENGTH = 16;
|
|
1391
|
-
constructor(ptr, size) {
|
|
1392
|
-
this.ptr = ptr;
|
|
1393
|
-
this.size = size;
|
|
1394
|
-
}
|
|
1395
|
-
toBytes() {
|
|
1396
|
-
const buffer = new ArrayBuffer(ArrayListHeader.LENGTH);
|
|
1397
|
-
const view = new DataView(buffer);
|
|
1398
|
-
view.setBigInt64(0, BigInt(this.size), false);
|
|
1399
|
-
view.setBigInt64(8, BigInt(this.ptr), false);
|
|
1400
|
-
return new Uint8Array(buffer);
|
|
1401
|
-
}
|
|
1402
|
-
static fromBytes(bytes) {
|
|
1403
|
-
const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
|
|
1404
|
-
const size = Number(view.getBigInt64(0, false));
|
|
1405
|
-
checkLong(size);
|
|
1406
|
-
const ptr = Number(view.getBigInt64(8, false));
|
|
1407
|
-
checkLong(ptr);
|
|
1408
|
-
return new ArrayListHeader(ptr, size);
|
|
1409
|
-
}
|
|
1410
|
-
withPtr(ptr) {
|
|
1411
|
-
return new ArrayListHeader(ptr, this.size);
|
|
1412
|
-
}
|
|
1413
|
-
}
|
|
1414
|
-
|
|
1415
|
-
class TopLevelArrayListHeader {
|
|
1416
|
-
fileSize;
|
|
1417
|
-
parent;
|
|
1418
|
-
static LENGTH = 8 + ArrayListHeader.LENGTH;
|
|
1419
|
-
constructor(fileSize, parent) {
|
|
1420
|
-
this.fileSize = fileSize;
|
|
1421
|
-
this.parent = parent;
|
|
1422
|
-
}
|
|
1423
|
-
toBytes() {
|
|
1424
|
-
const buffer = new ArrayBuffer(TopLevelArrayListHeader.LENGTH);
|
|
1425
|
-
const view = new DataView(buffer);
|
|
1426
|
-
const arr = new Uint8Array(buffer);
|
|
1427
|
-
arr.set(this.parent.toBytes(), 0);
|
|
1428
|
-
view.setBigInt64(ArrayListHeader.LENGTH, BigInt(this.fileSize), false);
|
|
1429
|
-
return arr;
|
|
1430
|
-
}
|
|
1431
|
-
}
|
|
1432
|
-
|
|
1433
|
-
class LinkedArrayListHeader {
|
|
1434
|
-
shift;
|
|
1435
|
-
ptr;
|
|
1436
|
-
size;
|
|
1437
|
-
static LENGTH = 17;
|
|
1438
|
-
constructor(shift, ptr, size) {
|
|
1439
|
-
this.shift = shift;
|
|
1440
|
-
this.ptr = ptr;
|
|
1441
|
-
this.size = size;
|
|
1442
|
-
}
|
|
1443
|
-
toBytes() {
|
|
1444
|
-
const buffer = new ArrayBuffer(LinkedArrayListHeader.LENGTH);
|
|
1445
|
-
const view = new DataView(buffer);
|
|
1446
|
-
view.setBigInt64(0, BigInt(this.size), false);
|
|
1447
|
-
view.setBigInt64(8, BigInt(this.ptr), false);
|
|
1448
|
-
view.setUint8(16, this.shift & 63);
|
|
1449
|
-
return new Uint8Array(buffer);
|
|
1450
|
-
}
|
|
1451
|
-
static fromBytes(bytes) {
|
|
1452
|
-
const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
|
|
1453
|
-
const size = Number(view.getBigInt64(0, false));
|
|
1454
|
-
checkLong(size);
|
|
1455
|
-
const ptr = Number(view.getBigInt64(8, false));
|
|
1456
|
-
checkLong(ptr);
|
|
1457
|
-
const shift = view.getUint8(16) & 63;
|
|
1458
|
-
return new LinkedArrayListHeader(shift, ptr, size);
|
|
1459
|
-
}
|
|
1460
|
-
withPtr(ptr) {
|
|
1461
|
-
return new LinkedArrayListHeader(this.shift, ptr, this.size);
|
|
1462
|
-
}
|
|
1463
|
-
}
|
|
1464
|
-
|
|
1465
|
-
class KeyValuePair {
|
|
1466
|
-
valueSlot;
|
|
1467
|
-
keySlot;
|
|
1468
|
-
hash;
|
|
1469
|
-
constructor(valueSlot, keySlot, hash) {
|
|
1470
|
-
this.valueSlot = valueSlot;
|
|
1471
|
-
this.keySlot = keySlot;
|
|
1472
|
-
this.hash = hash;
|
|
1473
|
-
}
|
|
1474
|
-
static length(hashSize) {
|
|
1475
|
-
return hashSize + Slot.LENGTH * 2;
|
|
1476
|
-
}
|
|
1477
|
-
toBytes() {
|
|
1478
|
-
const buffer = new Uint8Array(KeyValuePair.length(this.hash.length));
|
|
1479
|
-
buffer.set(this.hash, 0);
|
|
1480
|
-
buffer.set(this.keySlot.toBytes(), this.hash.length);
|
|
1481
|
-
buffer.set(this.valueSlot.toBytes(), this.hash.length + Slot.LENGTH);
|
|
1482
|
-
return buffer;
|
|
1483
|
-
}
|
|
1484
|
-
static fromBytes(bytes, hashSize) {
|
|
1485
|
-
const hash = bytes.slice(0, hashSize);
|
|
1486
|
-
const keySlotBytes = bytes.slice(hashSize, hashSize + Slot.LENGTH);
|
|
1487
|
-
const keySlot = Slot.fromBytes(keySlotBytes);
|
|
1488
|
-
const valueSlotBytes = bytes.slice(hashSize + Slot.LENGTH, hashSize + Slot.LENGTH * 2);
|
|
1489
|
-
const valueSlot = Slot.fromBytes(valueSlotBytes);
|
|
1490
|
-
return new KeyValuePair(valueSlot, keySlot, hash);
|
|
1491
|
-
}
|
|
1492
|
-
}
|
|
1493
|
-
|
|
1494
|
-
class LinkedArrayListSlot2 {
|
|
1495
|
-
size;
|
|
1496
|
-
slot;
|
|
1497
|
-
static LENGTH = 8 + Slot.LENGTH;
|
|
1498
|
-
constructor(size, slot) {
|
|
1499
|
-
this.size = size;
|
|
1500
|
-
this.slot = slot;
|
|
1501
|
-
}
|
|
1502
|
-
withSize(size) {
|
|
1503
|
-
return new LinkedArrayListSlot2(size, this.slot);
|
|
1504
|
-
}
|
|
1505
|
-
toBytes() {
|
|
1506
|
-
const buffer = new ArrayBuffer(LinkedArrayListSlot2.LENGTH);
|
|
1507
|
-
const view = new DataView(buffer);
|
|
1508
|
-
const arr = new Uint8Array(buffer);
|
|
1509
|
-
arr.set(this.slot.toBytes(), 0);
|
|
1510
|
-
view.setBigInt64(Slot.LENGTH, BigInt(this.size), false);
|
|
1511
|
-
return arr;
|
|
1512
|
-
}
|
|
1513
|
-
static fromBytes(bytes) {
|
|
1514
|
-
const slotBytes = bytes.slice(0, Slot.LENGTH);
|
|
1515
|
-
const slot = Slot.fromBytes(slotBytes);
|
|
1516
|
-
const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
|
|
1517
|
-
const size = Number(view.getBigInt64(Slot.LENGTH, false));
|
|
1518
|
-
checkLong(size);
|
|
1519
|
-
return new LinkedArrayListSlot2(size, slot);
|
|
1520
|
-
}
|
|
1521
|
-
}
|
|
1522
|
-
|
|
1523
|
-
class LinkedArrayListSlotPointer {
|
|
1524
|
-
slotPtr;
|
|
1525
|
-
leafCount;
|
|
1526
|
-
constructor(slotPtr, leafCount) {
|
|
1527
|
-
this.slotPtr = slotPtr;
|
|
1528
|
-
this.leafCount = leafCount;
|
|
1529
|
-
}
|
|
1530
|
-
withSlotPointer(slotPtr) {
|
|
1531
|
-
return new LinkedArrayListSlotPointer(slotPtr, this.leafCount);
|
|
1532
|
-
}
|
|
1533
|
-
}
|
|
1534
|
-
|
|
1535
|
-
class LinkedArrayListBlockInfo {
|
|
1536
|
-
block;
|
|
1537
|
-
i;
|
|
1538
|
-
parentSlot;
|
|
1539
|
-
constructor(block, i, parentSlot) {
|
|
1540
|
-
this.block = block;
|
|
1541
|
-
this.i = i;
|
|
1542
|
-
this.parentSlot = parentSlot;
|
|
1543
|
-
}
|
|
1544
|
-
}
|
|
1545
|
-
|
|
1546
|
-
class HashMapGetKVPair {
|
|
1547
|
-
hash;
|
|
1548
|
-
kind = "kv_pair";
|
|
1549
|
-
constructor(hash) {
|
|
1550
|
-
this.hash = hash;
|
|
1551
|
-
}
|
|
1552
|
-
}
|
|
1553
|
-
|
|
1554
|
-
class HashMapGetKey {
|
|
1555
|
-
hash;
|
|
1556
|
-
kind = "key";
|
|
1557
|
-
constructor(hash) {
|
|
1558
|
-
this.hash = hash;
|
|
1559
|
-
}
|
|
1560
|
-
}
|
|
1561
|
-
|
|
1562
|
-
class HashMapGetValue {
|
|
1563
|
-
hash;
|
|
1564
|
-
kind = "value";
|
|
1565
|
-
constructor(hash) {
|
|
1566
|
-
this.hash = hash;
|
|
1567
|
-
}
|
|
1568
|
-
}
|
|
1569
|
-
|
|
1570
|
-
class ArrayListInit {
|
|
1571
|
-
kind = "ArrayListInit";
|
|
1572
|
-
async readSlotPointer(db, isTopLevel, writeMode, path, pathI, slotPtr) {
|
|
1573
|
-
if (writeMode === 0 /* READ_ONLY */)
|
|
1574
|
-
throw new WriteNotAllowedException;
|
|
1575
|
-
if (isTopLevel) {
|
|
1576
|
-
const writer = db.core.writer();
|
|
1577
|
-
if (db.header.tag === 0 /* NONE */) {
|
|
1578
|
-
await db.core.seek(Header.LENGTH);
|
|
1579
|
-
const arrayListPtr = Header.LENGTH + TopLevelArrayListHeader.LENGTH;
|
|
1580
|
-
await writer.write(new TopLevelArrayListHeader(0, new ArrayListHeader(arrayListPtr, 0)).toBytes());
|
|
1581
|
-
await writer.write(new Uint8Array(INDEX_BLOCK_SIZE));
|
|
1582
|
-
await db.core.seek(0);
|
|
1583
|
-
db.header = db.header.withTag(2 /* ARRAY_LIST */);
|
|
1584
|
-
await writer.write(db.header.toBytes());
|
|
1585
|
-
}
|
|
1586
|
-
const nextSlotPtr = slotPtr.withSlot(slotPtr.slot.withTag(2 /* ARRAY_LIST */));
|
|
1587
|
-
return db.readSlotPointer(writeMode, path, pathI + 1, nextSlotPtr);
|
|
1588
|
-
}
|
|
1589
|
-
if (slotPtr.position === null)
|
|
1590
|
-
throw new CursorNotWriteableException;
|
|
1591
|
-
const position = slotPtr.position;
|
|
1592
|
-
switch (slotPtr.slot.tag) {
|
|
1593
|
-
case 0 /* NONE */: {
|
|
1594
|
-
const writer = db.core.writer();
|
|
1595
|
-
let arrayListStart = await db.core.length();
|
|
1596
|
-
await db.core.seek(arrayListStart);
|
|
1597
|
-
const arrayListPtr = arrayListStart + ArrayListHeader.LENGTH;
|
|
1598
|
-
await writer.write(new ArrayListHeader(arrayListPtr, 0).toBytes());
|
|
1599
|
-
await writer.write(new Uint8Array(INDEX_BLOCK_SIZE));
|
|
1600
|
-
const nextSlotPtr = new SlotPointer(position, new Slot(arrayListStart, 2 /* ARRAY_LIST */));
|
|
1601
|
-
await db.core.seek(position);
|
|
1602
|
-
await writer.write(nextSlotPtr.slot.toBytes());
|
|
1603
|
-
return db.readSlotPointer(writeMode, path, pathI + 1, nextSlotPtr);
|
|
1604
|
-
}
|
|
1605
|
-
case 2 /* ARRAY_LIST */: {
|
|
1606
|
-
const reader = db.core.reader();
|
|
1607
|
-
const writer = db.core.writer();
|
|
1608
|
-
let arrayListStart = Number(slotPtr.slot.value);
|
|
1609
|
-
if (db.txStart !== null) {
|
|
1610
|
-
if (arrayListStart < db.txStart) {
|
|
1611
|
-
await db.core.seek(arrayListStart);
|
|
1612
|
-
const headerBytes = new Uint8Array(ArrayListHeader.LENGTH);
|
|
1613
|
-
await reader.readFully(headerBytes);
|
|
1614
|
-
const header = ArrayListHeader.fromBytes(headerBytes);
|
|
1615
|
-
await db.core.seek(header.ptr);
|
|
1616
|
-
const arrayListIndexBlock = new Uint8Array(INDEX_BLOCK_SIZE);
|
|
1617
|
-
await reader.readFully(arrayListIndexBlock);
|
|
1618
|
-
arrayListStart = await db.core.length();
|
|
1619
|
-
await db.core.seek(arrayListStart);
|
|
1620
|
-
const nextArrayListPtr = arrayListStart + ArrayListHeader.LENGTH;
|
|
1621
|
-
const newHeader = header.withPtr(nextArrayListPtr);
|
|
1622
|
-
await writer.write(newHeader.toBytes());
|
|
1623
|
-
await writer.write(arrayListIndexBlock);
|
|
1624
|
-
}
|
|
1625
|
-
} else if (db.header.tag === 2 /* ARRAY_LIST */) {
|
|
1626
|
-
throw new ExpectedTxStartException;
|
|
1627
|
-
}
|
|
1628
|
-
const nextSlotPtr = new SlotPointer(position, new Slot(arrayListStart, 2 /* ARRAY_LIST */));
|
|
1629
|
-
await db.core.seek(position);
|
|
1630
|
-
await writer.write(nextSlotPtr.slot.toBytes());
|
|
1631
|
-
return db.readSlotPointer(writeMode, path, pathI + 1, nextSlotPtr);
|
|
1632
|
-
}
|
|
1633
|
-
default:
|
|
1634
|
-
throw new UnexpectedTagException;
|
|
1635
|
-
}
|
|
1636
|
-
}
|
|
1637
|
-
}
|
|
1638
|
-
|
|
1639
|
-
class ArrayListGet2 {
|
|
1640
|
-
index;
|
|
1641
|
-
kind = "ArrayListGet";
|
|
1642
|
-
constructor(index) {
|
|
1643
|
-
this.index = index;
|
|
1644
|
-
}
|
|
1645
|
-
async readSlotPointer(db, isTopLevel, writeMode, path, pathI, slotPtr) {
|
|
1646
|
-
const tag = isTopLevel ? db.header.tag : slotPtr.slot.tag;
|
|
1647
|
-
switch (tag) {
|
|
1648
|
-
case 0 /* NONE */:
|
|
1649
|
-
throw new KeyNotFoundException;
|
|
1650
|
-
case 2 /* ARRAY_LIST */:
|
|
1651
|
-
break;
|
|
1652
|
-
default:
|
|
1653
|
-
throw new UnexpectedTagException;
|
|
1654
|
-
}
|
|
1655
|
-
const nextArrayListStart = Number(slotPtr.slot.value);
|
|
1656
|
-
let index = this.index;
|
|
1657
|
-
await db.core.seek(nextArrayListStart);
|
|
1658
|
-
const reader = db.core.reader();
|
|
1659
|
-
const headerBytes = new Uint8Array(ArrayListHeader.LENGTH);
|
|
1660
|
-
await reader.readFully(headerBytes);
|
|
1661
|
-
const header = ArrayListHeader.fromBytes(headerBytes);
|
|
1662
|
-
if (index >= header.size || index < -header.size) {
|
|
1663
|
-
throw new KeyNotFoundException;
|
|
1664
|
-
}
|
|
1665
|
-
const key = index < 0 ? header.size - Math.abs(index) : index;
|
|
1666
|
-
const lastKey = header.size - 1;
|
|
1667
|
-
const shift = lastKey < SLOT_COUNT ? 0 : Math.floor(Math.log(lastKey) / Math.log(SLOT_COUNT));
|
|
1668
|
-
const finalSlotPtr = await db.readArrayListSlot(header.ptr, key, shift, writeMode, isTopLevel);
|
|
1669
|
-
return db.readSlotPointer(writeMode, path, pathI + 1, finalSlotPtr);
|
|
1670
|
-
}
|
|
1671
|
-
}
|
|
1672
|
-
|
|
1673
|
-
class ArrayListAppend {
|
|
1674
|
-
kind = "ArrayListAppend";
|
|
1675
|
-
async readSlotPointer(db, isTopLevel, writeMode, path, pathI, slotPtr) {
|
|
1676
|
-
if (writeMode === 0 /* READ_ONLY */)
|
|
1677
|
-
throw new WriteNotAllowedException;
|
|
1678
|
-
const tag = isTopLevel ? db.header.tag : slotPtr.slot.tag;
|
|
1679
|
-
if (tag !== 2 /* ARRAY_LIST */)
|
|
1680
|
-
throw new UnexpectedTagException;
|
|
1681
|
-
const reader = db.core.reader();
|
|
1682
|
-
const nextArrayListStart = Number(slotPtr.slot.value);
|
|
1683
|
-
await db.core.seek(nextArrayListStart);
|
|
1684
|
-
const headerBytes = new Uint8Array(ArrayListHeader.LENGTH);
|
|
1685
|
-
await reader.readFully(headerBytes);
|
|
1686
|
-
const origHeader = ArrayListHeader.fromBytes(headerBytes);
|
|
1687
|
-
const appendResult = await db.readArrayListSlotAppend(origHeader, writeMode, isTopLevel);
|
|
1688
|
-
const finalSlotPtr = await db.readSlotPointer(writeMode, path, pathI + 1, appendResult.slotPtr);
|
|
1689
|
-
const writer = db.core.writer();
|
|
1690
|
-
if (isTopLevel) {
|
|
1691
|
-
await db.core.flush();
|
|
1692
|
-
const fileSize = await db.core.length();
|
|
1693
|
-
const header = new TopLevelArrayListHeader(fileSize, appendResult.header);
|
|
1694
|
-
await db.core.seek(nextArrayListStart);
|
|
1695
|
-
await writer.write(header.toBytes());
|
|
1696
|
-
} else {
|
|
1697
|
-
await db.core.seek(nextArrayListStart);
|
|
1698
|
-
await writer.write(appendResult.header.toBytes());
|
|
1699
|
-
}
|
|
1700
|
-
return finalSlotPtr;
|
|
1701
|
-
}
|
|
1702
|
-
}
|
|
1703
|
-
|
|
1704
|
-
class ArrayListSlice {
|
|
1705
|
-
size;
|
|
1706
|
-
kind = "ArrayListSlice";
|
|
1707
|
-
constructor(size) {
|
|
1708
|
-
this.size = size;
|
|
1709
|
-
}
|
|
1710
|
-
async readSlotPointer(db, isTopLevel, writeMode, path, pathI, slotPtr) {
|
|
1711
|
-
if (writeMode === 0 /* READ_ONLY */)
|
|
1712
|
-
throw new WriteNotAllowedException;
|
|
1713
|
-
if (slotPtr.slot.tag !== 2 /* ARRAY_LIST */)
|
|
1714
|
-
throw new UnexpectedTagException;
|
|
1715
|
-
const reader = db.core.reader();
|
|
1716
|
-
const nextArrayListStart = Number(slotPtr.slot.value);
|
|
1717
|
-
await db.core.seek(nextArrayListStart);
|
|
1718
|
-
const headerBytes = new Uint8Array(ArrayListHeader.LENGTH);
|
|
1719
|
-
await reader.readFully(headerBytes);
|
|
1720
|
-
const origHeader = ArrayListHeader.fromBytes(headerBytes);
|
|
1721
|
-
const sliceHeader = await db.readArrayListSlice(origHeader, this.size);
|
|
1722
|
-
const finalSlotPtr = await db.readSlotPointer(writeMode, path, pathI + 1, slotPtr);
|
|
1723
|
-
const writer = db.core.writer();
|
|
1724
|
-
await db.core.seek(nextArrayListStart);
|
|
1725
|
-
await writer.write(sliceHeader.toBytes());
|
|
1726
|
-
return finalSlotPtr;
|
|
1727
|
-
}
|
|
1728
|
-
}
|
|
1729
|
-
|
|
1730
|
-
class LinkedArrayListInit {
|
|
1731
|
-
kind = "LinkedArrayListInit";
|
|
1732
|
-
async readSlotPointer(db, isTopLevel, writeMode, path, pathI, slotPtr) {
|
|
1733
|
-
if (writeMode === 0 /* READ_ONLY */)
|
|
1734
|
-
throw new WriteNotAllowedException;
|
|
1735
|
-
if (isTopLevel)
|
|
1736
|
-
throw new InvalidTopLevelTypeException;
|
|
1737
|
-
if (slotPtr.position === null)
|
|
1738
|
-
throw new CursorNotWriteableException;
|
|
1739
|
-
const position = slotPtr.position;
|
|
1740
|
-
switch (slotPtr.slot.tag) {
|
|
1741
|
-
case 0 /* NONE */: {
|
|
1742
|
-
const writer = db.core.writer();
|
|
1743
|
-
const arrayListStart = await db.core.length();
|
|
1744
|
-
await db.core.seek(arrayListStart);
|
|
1745
|
-
const arrayListPtr = arrayListStart + LinkedArrayListHeader.LENGTH;
|
|
1746
|
-
await writer.write(new LinkedArrayListHeader(0, arrayListPtr, 0).toBytes());
|
|
1747
|
-
await writer.write(new Uint8Array(LINKED_ARRAY_LIST_INDEX_BLOCK_SIZE));
|
|
1748
|
-
const nextSlotPtr = new SlotPointer(position, new Slot(arrayListStart, 3 /* LINKED_ARRAY_LIST */));
|
|
1749
|
-
await db.core.seek(position);
|
|
1750
|
-
await writer.write(nextSlotPtr.slot.toBytes());
|
|
1751
|
-
return db.readSlotPointer(writeMode, path, pathI + 1, nextSlotPtr);
|
|
1752
|
-
}
|
|
1753
|
-
case 3 /* LINKED_ARRAY_LIST */: {
|
|
1754
|
-
const reader = db.core.reader();
|
|
1755
|
-
const writer = db.core.writer();
|
|
1756
|
-
let arrayListStart = Number(slotPtr.slot.value);
|
|
1757
|
-
if (db.txStart !== null) {
|
|
1758
|
-
if (arrayListStart < db.txStart) {
|
|
1759
|
-
await db.core.seek(arrayListStart);
|
|
1760
|
-
const headerBytes = new Uint8Array(LinkedArrayListHeader.LENGTH);
|
|
1761
|
-
await reader.readFully(headerBytes);
|
|
1762
|
-
const header = LinkedArrayListHeader.fromBytes(headerBytes);
|
|
1763
|
-
await db.core.seek(header.ptr);
|
|
1764
|
-
const arrayListIndexBlock = new Uint8Array(LINKED_ARRAY_LIST_INDEX_BLOCK_SIZE);
|
|
1765
|
-
await reader.readFully(arrayListIndexBlock);
|
|
1766
|
-
arrayListStart = await db.core.length();
|
|
1767
|
-
await db.core.seek(arrayListStart);
|
|
1768
|
-
const nextArrayListPtr = arrayListStart + LinkedArrayListHeader.LENGTH;
|
|
1769
|
-
const newHeader = header.withPtr(nextArrayListPtr);
|
|
1770
|
-
await writer.write(newHeader.toBytes());
|
|
1771
|
-
await writer.write(arrayListIndexBlock);
|
|
1772
|
-
}
|
|
1773
|
-
} else if (db.header.tag === 2 /* ARRAY_LIST */) {
|
|
1774
|
-
throw new ExpectedTxStartException;
|
|
1775
|
-
}
|
|
1776
|
-
const nextSlotPtr = new SlotPointer(position, new Slot(arrayListStart, 3 /* LINKED_ARRAY_LIST */));
|
|
1777
|
-
await db.core.seek(position);
|
|
1778
|
-
await writer.write(nextSlotPtr.slot.toBytes());
|
|
1779
|
-
return db.readSlotPointer(writeMode, path, pathI + 1, nextSlotPtr);
|
|
1780
|
-
}
|
|
1781
|
-
default:
|
|
1782
|
-
throw new UnexpectedTagException;
|
|
1783
|
-
}
|
|
1784
|
-
}
|
|
1785
|
-
}
|
|
1786
|
-
|
|
1787
|
-
class LinkedArrayListGet {
|
|
1788
|
-
index;
|
|
1789
|
-
kind = "LinkedArrayListGet";
|
|
1790
|
-
constructor(index) {
|
|
1791
|
-
this.index = index;
|
|
1792
|
-
}
|
|
1793
|
-
async readSlotPointer(db, isTopLevel, writeMode, path, pathI, slotPtr) {
|
|
1794
|
-
switch (slotPtr.slot.tag) {
|
|
1795
|
-
case 0 /* NONE */:
|
|
1796
|
-
throw new KeyNotFoundException;
|
|
1797
|
-
case 3 /* LINKED_ARRAY_LIST */:
|
|
1798
|
-
break;
|
|
1799
|
-
default:
|
|
1800
|
-
throw new UnexpectedTagException;
|
|
1801
|
-
}
|
|
1802
|
-
let index = this.index;
|
|
1803
|
-
await db.core.seek(Number(slotPtr.slot.value));
|
|
1804
|
-
const reader = db.core.reader();
|
|
1805
|
-
const headerBytes = new Uint8Array(LinkedArrayListHeader.LENGTH);
|
|
1806
|
-
await reader.readFully(headerBytes);
|
|
1807
|
-
const header = LinkedArrayListHeader.fromBytes(headerBytes);
|
|
1808
|
-
if (index >= header.size || index < -header.size) {
|
|
1809
|
-
throw new KeyNotFoundException;
|
|
1810
|
-
}
|
|
1811
|
-
const key = index < 0 ? header.size - Math.abs(index) : index;
|
|
1812
|
-
const finalSlotPtr = await db.readLinkedArrayListSlot(header.ptr, key, header.shift, writeMode, isTopLevel);
|
|
1813
|
-
return db.readSlotPointer(writeMode, path, pathI + 1, finalSlotPtr.slotPtr);
|
|
1814
|
-
}
|
|
1815
|
-
}
|
|
1816
|
-
|
|
1817
|
-
class LinkedArrayListAppend {
|
|
1818
|
-
kind = "LinkedArrayListAppend";
|
|
1819
|
-
async readSlotPointer(db, isTopLevel, writeMode, path, pathI, slotPtr) {
|
|
1820
|
-
if (writeMode === 0 /* READ_ONLY */)
|
|
1821
|
-
throw new WriteNotAllowedException;
|
|
1822
|
-
if (slotPtr.slot.tag !== 3 /* LINKED_ARRAY_LIST */)
|
|
1823
|
-
throw new UnexpectedTagException;
|
|
1824
|
-
const reader = db.core.reader();
|
|
1825
|
-
const nextArrayListStart = Number(slotPtr.slot.value);
|
|
1826
|
-
await db.core.seek(nextArrayListStart);
|
|
1827
|
-
const headerBytes = new Uint8Array(LinkedArrayListHeader.LENGTH);
|
|
1828
|
-
await reader.readFully(headerBytes);
|
|
1829
|
-
const origHeader = LinkedArrayListHeader.fromBytes(headerBytes);
|
|
1830
|
-
const appendResult = await db.readLinkedArrayListSlotAppend(origHeader, writeMode, isTopLevel);
|
|
1831
|
-
const finalSlotPtr = await db.readSlotPointer(writeMode, path, pathI + 1, appendResult.slotPtr.slotPtr);
|
|
1832
|
-
const writer = db.core.writer();
|
|
1833
|
-
await db.core.seek(nextArrayListStart);
|
|
1834
|
-
await writer.write(appendResult.header.toBytes());
|
|
1835
|
-
return finalSlotPtr;
|
|
1836
|
-
}
|
|
1837
|
-
}
|
|
1838
|
-
|
|
1839
|
-
class LinkedArrayListSlice {
|
|
1840
|
-
offset;
|
|
1841
|
-
size;
|
|
1842
|
-
kind = "LinkedArrayListSlice";
|
|
1843
|
-
constructor(offset, size) {
|
|
1844
|
-
this.offset = offset;
|
|
1845
|
-
this.size = size;
|
|
1846
|
-
}
|
|
1847
|
-
async readSlotPointer(db, isTopLevel, writeMode, path, pathI, slotPtr) {
|
|
1848
|
-
if (writeMode === 0 /* READ_ONLY */)
|
|
1849
|
-
throw new WriteNotAllowedException;
|
|
1850
|
-
if (slotPtr.slot.tag !== 3 /* LINKED_ARRAY_LIST */)
|
|
1851
|
-
throw new UnexpectedTagException;
|
|
1852
|
-
const reader = db.core.reader();
|
|
1853
|
-
const nextArrayListStart = Number(slotPtr.slot.value);
|
|
1854
|
-
await db.core.seek(nextArrayListStart);
|
|
1855
|
-
const headerBytes = new Uint8Array(LinkedArrayListHeader.LENGTH);
|
|
1856
|
-
await reader.readFully(headerBytes);
|
|
1857
|
-
const origHeader = LinkedArrayListHeader.fromBytes(headerBytes);
|
|
1858
|
-
const sliceHeader = await db.readLinkedArrayListSlice(origHeader, this.offset, this.size);
|
|
1859
|
-
const finalSlotPtr = await db.readSlotPointer(writeMode, path, pathI + 1, slotPtr);
|
|
1860
|
-
const writer = db.core.writer();
|
|
1861
|
-
await db.core.seek(nextArrayListStart);
|
|
1862
|
-
await writer.write(sliceHeader.toBytes());
|
|
1863
|
-
return finalSlotPtr;
|
|
1864
|
-
}
|
|
1865
|
-
}
|
|
1866
|
-
|
|
1867
|
-
class LinkedArrayListConcat {
|
|
1868
|
-
list;
|
|
1869
|
-
kind = "LinkedArrayListConcat";
|
|
1870
|
-
constructor(list) {
|
|
1871
|
-
this.list = list;
|
|
1872
|
-
}
|
|
1873
|
-
async readSlotPointer(db, isTopLevel, writeMode, path, pathI, slotPtr) {
|
|
1874
|
-
if (writeMode === 0 /* READ_ONLY */)
|
|
1875
|
-
throw new WriteNotAllowedException;
|
|
1876
|
-
if (slotPtr.slot.tag !== 3 /* LINKED_ARRAY_LIST */)
|
|
1877
|
-
throw new UnexpectedTagException;
|
|
1878
|
-
if (this.list.tag !== 3 /* LINKED_ARRAY_LIST */)
|
|
1879
|
-
throw new UnexpectedTagException;
|
|
1880
|
-
const reader = db.core.reader();
|
|
1881
|
-
const nextArrayListStart = Number(slotPtr.slot.value);
|
|
1882
|
-
await db.core.seek(nextArrayListStart);
|
|
1883
|
-
const headerBytesA = new Uint8Array(LinkedArrayListHeader.LENGTH);
|
|
1884
|
-
await reader.readFully(headerBytesA);
|
|
1885
|
-
const headerA = LinkedArrayListHeader.fromBytes(headerBytesA);
|
|
1886
|
-
await db.core.seek(Number(this.list.value));
|
|
1887
|
-
const headerBytesB = new Uint8Array(LinkedArrayListHeader.LENGTH);
|
|
1888
|
-
await reader.readFully(headerBytesB);
|
|
1889
|
-
const headerB = LinkedArrayListHeader.fromBytes(headerBytesB);
|
|
1890
|
-
const concatHeader = await db.readLinkedArrayListConcat(headerA, headerB);
|
|
1891
|
-
const finalSlotPtr = await db.readSlotPointer(writeMode, path, pathI + 1, slotPtr);
|
|
1892
|
-
const writer = db.core.writer();
|
|
1893
|
-
await db.core.seek(nextArrayListStart);
|
|
1894
|
-
await writer.write(concatHeader.toBytes());
|
|
1895
|
-
return finalSlotPtr;
|
|
1896
|
-
}
|
|
1897
|
-
}
|
|
1898
|
-
|
|
1899
|
-
class LinkedArrayListInsert {
|
|
1900
|
-
index;
|
|
1901
|
-
kind = "LinkedArrayListInsert";
|
|
1902
|
-
constructor(index) {
|
|
1903
|
-
this.index = index;
|
|
1904
|
-
}
|
|
1905
|
-
async readSlotPointer(db, isTopLevel, writeMode, path, pathI, slotPtr) {
|
|
1906
|
-
if (writeMode === 0 /* READ_ONLY */)
|
|
1907
|
-
throw new WriteNotAllowedException;
|
|
1908
|
-
if (slotPtr.slot.tag !== 3 /* LINKED_ARRAY_LIST */)
|
|
1909
|
-
throw new UnexpectedTagException;
|
|
1910
|
-
const reader = db.core.reader();
|
|
1911
|
-
const nextArrayListStart = Number(slotPtr.slot.value);
|
|
1912
|
-
await db.core.seek(nextArrayListStart);
|
|
1913
|
-
const headerBytes = new Uint8Array(LinkedArrayListHeader.LENGTH);
|
|
1914
|
-
await reader.readFully(headerBytes);
|
|
1915
|
-
const origHeader = LinkedArrayListHeader.fromBytes(headerBytes);
|
|
1916
|
-
let index = this.index;
|
|
1917
|
-
if (index >= origHeader.size || index < -origHeader.size) {
|
|
1918
|
-
throw new KeyNotFoundException;
|
|
1919
|
-
}
|
|
1920
|
-
const key = index < 0 ? origHeader.size - Math.abs(index) : index;
|
|
1921
|
-
const headerA = await db.readLinkedArrayListSlice(origHeader, 0, key);
|
|
1922
|
-
const headerB = await db.readLinkedArrayListSlice(origHeader, key, origHeader.size - key);
|
|
1923
|
-
const appendResult = await db.readLinkedArrayListSlotAppend(headerA, writeMode, isTopLevel);
|
|
1924
|
-
const concatHeader = await db.readLinkedArrayListConcat(appendResult.header, headerB);
|
|
1925
|
-
const nextSlotPtr = await db.readLinkedArrayListSlot(concatHeader.ptr, key, concatHeader.shift, 0 /* READ_ONLY */, isTopLevel);
|
|
1926
|
-
const finalSlotPtr = await db.readSlotPointer(writeMode, path, pathI + 1, nextSlotPtr.slotPtr);
|
|
1927
|
-
const writer = db.core.writer();
|
|
1928
|
-
await db.core.seek(nextArrayListStart);
|
|
1929
|
-
await writer.write(concatHeader.toBytes());
|
|
1930
|
-
return finalSlotPtr;
|
|
1931
|
-
}
|
|
1932
|
-
}
|
|
1933
|
-
|
|
1934
|
-
class LinkedArrayListRemove {
|
|
1935
|
-
index;
|
|
1936
|
-
kind = "LinkedArrayListRemove";
|
|
1937
|
-
constructor(index) {
|
|
1938
|
-
this.index = index;
|
|
1939
|
-
}
|
|
1940
|
-
async readSlotPointer(db, isTopLevel, writeMode, path, pathI, slotPtr) {
|
|
1941
|
-
if (writeMode === 0 /* READ_ONLY */)
|
|
1942
|
-
throw new WriteNotAllowedException;
|
|
1943
|
-
if (slotPtr.slot.tag !== 3 /* LINKED_ARRAY_LIST */)
|
|
1944
|
-
throw new UnexpectedTagException;
|
|
1945
|
-
const reader = db.core.reader();
|
|
1946
|
-
const nextArrayListStart = Number(slotPtr.slot.value);
|
|
1947
|
-
await db.core.seek(nextArrayListStart);
|
|
1948
|
-
const headerBytes = new Uint8Array(LinkedArrayListHeader.LENGTH);
|
|
1949
|
-
await reader.readFully(headerBytes);
|
|
1950
|
-
const origHeader = LinkedArrayListHeader.fromBytes(headerBytes);
|
|
1951
|
-
let index = this.index;
|
|
1952
|
-
if (index >= origHeader.size || index < -origHeader.size) {
|
|
1953
|
-
throw new KeyNotFoundException;
|
|
1954
|
-
}
|
|
1955
|
-
const key = index < 0 ? origHeader.size - Math.abs(index) : index;
|
|
1956
|
-
const headerA = await db.readLinkedArrayListSlice(origHeader, 0, key);
|
|
1957
|
-
const headerB = await db.readLinkedArrayListSlice(origHeader, key + 1, origHeader.size - (key + 1));
|
|
1958
|
-
const concatHeader = await db.readLinkedArrayListConcat(headerA, headerB);
|
|
1959
|
-
const nextSlotPtr = new SlotPointer(concatHeader.ptr, new Slot(nextArrayListStart, 3 /* LINKED_ARRAY_LIST */));
|
|
1960
|
-
const finalSlotPtr = await db.readSlotPointer(writeMode, path, pathI + 1, nextSlotPtr);
|
|
1961
|
-
const writer = db.core.writer();
|
|
1962
|
-
await db.core.seek(nextArrayListStart);
|
|
1963
|
-
await writer.write(concatHeader.toBytes());
|
|
1964
|
-
return finalSlotPtr;
|
|
1965
|
-
}
|
|
1966
|
-
}
|
|
1967
|
-
|
|
1968
|
-
class HashMapInit {
|
|
1969
|
-
counted;
|
|
1970
|
-
set;
|
|
1971
|
-
kind = "HashMapInit";
|
|
1972
|
-
constructor(counted = false, set = false) {
|
|
1973
|
-
this.counted = counted;
|
|
1974
|
-
this.set = set;
|
|
1975
|
-
}
|
|
1976
|
-
async readSlotPointer(db, isTopLevel, writeMode, path, pathI, slotPtr) {
|
|
1977
|
-
if (writeMode === 0 /* READ_ONLY */)
|
|
1978
|
-
throw new WriteNotAllowedException;
|
|
1979
|
-
const tag = this.counted ? this.set ? 13 /* COUNTED_HASH_SET */ : 12 /* COUNTED_HASH_MAP */ : this.set ? 11 /* HASH_SET */ : 4 /* HASH_MAP */;
|
|
1980
|
-
if (isTopLevel) {
|
|
1981
|
-
const writer = db.core.writer();
|
|
1982
|
-
if (db.header.tag === 0 /* NONE */) {
|
|
1983
|
-
await db.core.seek(Header.LENGTH);
|
|
1984
|
-
if (this.counted) {
|
|
1985
|
-
await writer.writeLong(0);
|
|
1986
|
-
}
|
|
1987
|
-
await writer.write(new Uint8Array(INDEX_BLOCK_SIZE));
|
|
1988
|
-
await db.core.seek(0);
|
|
1989
|
-
db.header = db.header.withTag(tag);
|
|
1990
|
-
await writer.write(db.header.toBytes());
|
|
1991
|
-
}
|
|
1992
|
-
const nextSlotPtr = slotPtr.withSlot(slotPtr.slot.withTag(tag));
|
|
1993
|
-
return db.readSlotPointer(writeMode, path, pathI + 1, nextSlotPtr);
|
|
1994
|
-
}
|
|
1995
|
-
if (slotPtr.position === null)
|
|
1996
|
-
throw new CursorNotWriteableException;
|
|
1997
|
-
const position = slotPtr.position;
|
|
1998
|
-
switch (slotPtr.slot.tag) {
|
|
1999
|
-
case 0 /* NONE */: {
|
|
2000
|
-
const writer = db.core.writer();
|
|
2001
|
-
const mapStart = await db.core.length();
|
|
2002
|
-
await db.core.seek(mapStart);
|
|
2003
|
-
if (this.counted) {
|
|
2004
|
-
await writer.writeLong(0);
|
|
2005
|
-
}
|
|
2006
|
-
await writer.write(new Uint8Array(INDEX_BLOCK_SIZE));
|
|
2007
|
-
const nextSlotPtr = new SlotPointer(position, new Slot(mapStart, tag));
|
|
2008
|
-
await db.core.seek(position);
|
|
2009
|
-
await writer.write(nextSlotPtr.slot.toBytes());
|
|
2010
|
-
return db.readSlotPointer(writeMode, path, pathI + 1, nextSlotPtr);
|
|
2011
|
-
}
|
|
2012
|
-
case 4 /* HASH_MAP */:
|
|
2013
|
-
case 11 /* HASH_SET */:
|
|
2014
|
-
case 12 /* COUNTED_HASH_MAP */:
|
|
2015
|
-
case 13 /* COUNTED_HASH_SET */: {
|
|
2016
|
-
if (this.counted) {
|
|
2017
|
-
switch (slotPtr.slot.tag) {
|
|
2018
|
-
case 12 /* COUNTED_HASH_MAP */:
|
|
2019
|
-
case 13 /* COUNTED_HASH_SET */:
|
|
2020
|
-
break;
|
|
2021
|
-
default:
|
|
2022
|
-
throw new UnexpectedTagException;
|
|
2023
|
-
}
|
|
2024
|
-
} else {
|
|
2025
|
-
switch (slotPtr.slot.tag) {
|
|
2026
|
-
case 4 /* HASH_MAP */:
|
|
2027
|
-
case 11 /* HASH_SET */:
|
|
2028
|
-
break;
|
|
2029
|
-
default:
|
|
2030
|
-
throw new UnexpectedTagException;
|
|
2031
|
-
}
|
|
2032
|
-
}
|
|
2033
|
-
const reader = db.core.reader();
|
|
2034
|
-
const writer = db.core.writer();
|
|
2035
|
-
let mapStart = Number(slotPtr.slot.value);
|
|
2036
|
-
if (db.txStart !== null) {
|
|
2037
|
-
if (mapStart < db.txStart) {
|
|
2038
|
-
await db.core.seek(mapStart);
|
|
2039
|
-
let mapCountMaybe = null;
|
|
2040
|
-
if (this.counted) {
|
|
2041
|
-
mapCountMaybe = await reader.readLong();
|
|
2042
|
-
}
|
|
2043
|
-
const mapIndexBlock = new Uint8Array(INDEX_BLOCK_SIZE);
|
|
2044
|
-
await reader.readFully(mapIndexBlock);
|
|
2045
|
-
mapStart = await db.core.length();
|
|
2046
|
-
await db.core.seek(mapStart);
|
|
2047
|
-
if (mapCountMaybe !== null) {
|
|
2048
|
-
await writer.writeLong(mapCountMaybe);
|
|
2049
|
-
}
|
|
2050
|
-
await writer.write(mapIndexBlock);
|
|
2051
|
-
}
|
|
2052
|
-
} else if (db.header.tag === 2 /* ARRAY_LIST */) {
|
|
2053
|
-
throw new ExpectedTxStartException;
|
|
2054
|
-
}
|
|
2055
|
-
const nextSlotPtr = new SlotPointer(position, new Slot(mapStart, tag));
|
|
2056
|
-
await db.core.seek(position);
|
|
2057
|
-
await writer.write(nextSlotPtr.slot.toBytes());
|
|
2058
|
-
return db.readSlotPointer(writeMode, path, pathI + 1, nextSlotPtr);
|
|
2059
|
-
}
|
|
2060
|
-
default:
|
|
2061
|
-
throw new UnexpectedTagException;
|
|
2062
|
-
}
|
|
2063
|
-
}
|
|
2064
|
-
}
|
|
2065
|
-
|
|
2066
|
-
class HashMapGet {
|
|
2067
|
-
target;
|
|
2068
|
-
kind = "HashMapGet";
|
|
2069
|
-
constructor(target) {
|
|
2070
|
-
this.target = target;
|
|
2071
|
-
}
|
|
2072
|
-
async readSlotPointer(db, isTopLevel, writeMode, path, pathI, slotPtr) {
|
|
2073
|
-
let counted = false;
|
|
2074
|
-
switch (slotPtr.slot.tag) {
|
|
2075
|
-
case 0 /* NONE */:
|
|
2076
|
-
throw new KeyNotFoundException;
|
|
2077
|
-
case 4 /* HASH_MAP */:
|
|
2078
|
-
case 11 /* HASH_SET */:
|
|
2079
|
-
break;
|
|
2080
|
-
case 12 /* COUNTED_HASH_MAP */:
|
|
2081
|
-
case 13 /* COUNTED_HASH_SET */:
|
|
2082
|
-
counted = true;
|
|
2083
|
-
break;
|
|
2084
|
-
default:
|
|
2085
|
-
throw new UnexpectedTagException;
|
|
2086
|
-
}
|
|
2087
|
-
const indexPos = counted ? Number(slotPtr.slot.value) + 8 : Number(slotPtr.slot.value);
|
|
2088
|
-
const hash = db.checkHash(this.target);
|
|
2089
|
-
const res = await db.readMapSlot(indexPos, hash, 0, writeMode, isTopLevel, this.target);
|
|
2090
|
-
if (writeMode === 1 /* READ_WRITE */ && counted && res.isEmpty) {
|
|
2091
|
-
const reader = db.core.reader();
|
|
2092
|
-
const writer = db.core.writer();
|
|
2093
|
-
await db.core.seek(Number(slotPtr.slot.value));
|
|
2094
|
-
const mapCount = await reader.readLong();
|
|
2095
|
-
await db.core.seek(Number(slotPtr.slot.value));
|
|
2096
|
-
await writer.writeLong(mapCount + 1);
|
|
2097
|
-
}
|
|
2098
|
-
return db.readSlotPointer(writeMode, path, pathI + 1, res.slotPtr);
|
|
2099
|
-
}
|
|
2100
|
-
}
|
|
2101
|
-
|
|
2102
|
-
class HashMapRemove {
|
|
2103
|
-
hash;
|
|
2104
|
-
kind = "HashMapRemove";
|
|
2105
|
-
constructor(hash) {
|
|
2106
|
-
this.hash = hash;
|
|
2107
|
-
}
|
|
2108
|
-
async readSlotPointer(db, isTopLevel, writeMode, path, pathI, slotPtr) {
|
|
2109
|
-
if (writeMode === 0 /* READ_ONLY */)
|
|
2110
|
-
throw new WriteNotAllowedException;
|
|
2111
|
-
let counted = false;
|
|
2112
|
-
switch (slotPtr.slot.tag) {
|
|
2113
|
-
case 0 /* NONE */:
|
|
2114
|
-
throw new KeyNotFoundException;
|
|
2115
|
-
case 4 /* HASH_MAP */:
|
|
2116
|
-
case 11 /* HASH_SET */:
|
|
2117
|
-
break;
|
|
2118
|
-
case 12 /* COUNTED_HASH_MAP */:
|
|
2119
|
-
case 13 /* COUNTED_HASH_SET */:
|
|
2120
|
-
counted = true;
|
|
2121
|
-
break;
|
|
2122
|
-
default:
|
|
2123
|
-
throw new UnexpectedTagException;
|
|
2124
|
-
}
|
|
2125
|
-
const indexPos = counted ? Number(slotPtr.slot.value) + 8 : Number(slotPtr.slot.value);
|
|
2126
|
-
const hash = db.checkHashBytes(this.hash);
|
|
2127
|
-
let keyFound = true;
|
|
2128
|
-
try {
|
|
2129
|
-
await db.removeMapSlot(indexPos, hash, 0, isTopLevel);
|
|
2130
|
-
} catch (e) {
|
|
2131
|
-
if (e instanceof KeyNotFoundException) {
|
|
2132
|
-
keyFound = false;
|
|
2133
|
-
} else {
|
|
2134
|
-
throw e;
|
|
2135
|
-
}
|
|
2136
|
-
}
|
|
2137
|
-
if (writeMode === 1 /* READ_WRITE */ && counted && keyFound) {
|
|
2138
|
-
const reader = db.core.reader();
|
|
2139
|
-
const writer = db.core.writer();
|
|
2140
|
-
await db.core.seek(Number(slotPtr.slot.value));
|
|
2141
|
-
const mapCount = await reader.readLong();
|
|
2142
|
-
await db.core.seek(Number(slotPtr.slot.value));
|
|
2143
|
-
await writer.writeLong(mapCount - 1);
|
|
2144
|
-
}
|
|
2145
|
-
if (!keyFound)
|
|
2146
|
-
throw new KeyNotFoundException;
|
|
2147
|
-
return slotPtr;
|
|
2148
|
-
}
|
|
2149
|
-
}
|
|
2150
|
-
|
|
2151
|
-
class WriteData {
|
|
2152
|
-
data;
|
|
2153
|
-
kind = "WriteData";
|
|
2154
|
-
constructor(data) {
|
|
2155
|
-
this.data = data;
|
|
2156
|
-
}
|
|
2157
|
-
async readSlotPointer(db, isTopLevel, writeMode, path, pathI, slotPtr) {
|
|
2158
|
-
if (writeMode === 0 /* READ_ONLY */)
|
|
2159
|
-
throw new WriteNotAllowedException;
|
|
2160
|
-
if (slotPtr.position === null)
|
|
2161
|
-
throw new CursorNotWriteableException;
|
|
2162
|
-
const position = slotPtr.position;
|
|
2163
|
-
const writer = db.core.writer();
|
|
2164
|
-
const data = this.data;
|
|
2165
|
-
let slot;
|
|
2166
|
-
if (data === null) {
|
|
2167
|
-
slot = new Slot;
|
|
2168
|
-
} else if (data instanceof Slot) {
|
|
2169
|
-
slot = data;
|
|
2170
|
-
} else if (data instanceof Uint) {
|
|
2171
|
-
slot = new Slot(data.value, 8 /* UINT */);
|
|
2172
|
-
} else if (data instanceof Int) {
|
|
2173
|
-
slot = new Slot(data.value, 9 /* INT */);
|
|
2174
|
-
} else if (data instanceof Float) {
|
|
2175
|
-
const buffer = new ArrayBuffer(8);
|
|
2176
|
-
const view = new DataView(buffer);
|
|
2177
|
-
view.setFloat64(0, data.value, false);
|
|
2178
|
-
const longValue = view.getBigInt64(0, false);
|
|
2179
|
-
slot = new Slot(longValue, 10 /* FLOAT */);
|
|
2180
|
-
} else if (data instanceof Bytes) {
|
|
2181
|
-
if (data.isShort()) {
|
|
2182
|
-
const buffer = new Uint8Array(8);
|
|
2183
|
-
buffer.set(data.value, 0);
|
|
2184
|
-
if (data.formatTag !== null) {
|
|
2185
|
-
buffer.set(data.formatTag, 6);
|
|
2186
|
-
}
|
|
2187
|
-
const view = new DataView(buffer.buffer);
|
|
2188
|
-
const longValue = view.getBigInt64(0, false);
|
|
2189
|
-
slot = new Slot(longValue, 7 /* SHORT_BYTES */, data.formatTag !== null);
|
|
2190
|
-
} else {
|
|
2191
|
-
const nextCursor = new WriteCursor(slotPtr, db);
|
|
2192
|
-
const cursorWriter = await nextCursor.writer();
|
|
2193
|
-
cursorWriter.formatTag = data.formatTag;
|
|
2194
|
-
await cursorWriter.write(data.value);
|
|
2195
|
-
await cursorWriter.finish();
|
|
2196
|
-
slot = cursorWriter.slot;
|
|
2197
|
-
}
|
|
2198
|
-
} else {
|
|
2199
|
-
throw new Error("Unknown data type");
|
|
2200
|
-
}
|
|
2201
|
-
if (slot.tag === 0 /* NONE */) {
|
|
2202
|
-
slot = slot.withFull(true);
|
|
2203
|
-
}
|
|
2204
|
-
await db.core.seek(position);
|
|
2205
|
-
await writer.write(slot.toBytes());
|
|
2206
|
-
const nextSlotPtr = new SlotPointer(slotPtr.position, slot);
|
|
2207
|
-
return db.readSlotPointer(writeMode, path, pathI + 1, nextSlotPtr);
|
|
2208
|
-
}
|
|
2209
|
-
}
|
|
2210
|
-
|
|
2211
|
-
class Context {
|
|
2212
|
-
fn;
|
|
2213
|
-
kind = "Context";
|
|
2214
|
-
constructor(fn) {
|
|
2215
|
-
this.fn = fn;
|
|
2216
|
-
}
|
|
2217
|
-
async readSlotPointer(db, isTopLevel, writeMode, path, pathI, slotPtr) {
|
|
2218
|
-
if (writeMode === 0 /* READ_ONLY */)
|
|
2219
|
-
throw new WriteNotAllowedException;
|
|
2220
|
-
if (pathI !== path.length - 1)
|
|
2221
|
-
throw new PathPartMustBeAtEndException;
|
|
2222
|
-
const nextCursor = new WriteCursor(slotPtr, db);
|
|
2223
|
-
try {
|
|
2224
|
-
await this.fn(nextCursor);
|
|
2225
|
-
} catch (e) {
|
|
2226
|
-
try {
|
|
2227
|
-
await db.truncate();
|
|
2228
|
-
} catch (_) {}
|
|
2229
|
-
throw e;
|
|
2230
|
-
}
|
|
2231
|
-
return nextCursor.slotPtr;
|
|
2232
|
-
}
|
|
2233
|
-
}
|
|
2234
|
-
|
|
2235
|
-
class HashMapGetResult {
|
|
2236
|
-
slotPtr;
|
|
2237
|
-
isEmpty;
|
|
2238
|
-
constructor(slotPtr, isEmpty) {
|
|
2239
|
-
this.slotPtr = slotPtr;
|
|
2240
|
-
this.isEmpty = isEmpty;
|
|
2241
|
-
}
|
|
2242
|
-
}
|
|
2243
|
-
|
|
2244
|
-
class ArrayListAppendResult {
|
|
2245
|
-
header;
|
|
2246
|
-
slotPtr;
|
|
2247
|
-
constructor(header, slotPtr) {
|
|
2248
|
-
this.header = header;
|
|
2249
|
-
this.slotPtr = slotPtr;
|
|
2250
|
-
}
|
|
2251
|
-
}
|
|
2252
|
-
|
|
2253
|
-
class LinkedArrayListAppendResult {
|
|
2254
|
-
header;
|
|
2255
|
-
slotPtr;
|
|
2256
|
-
constructor(header, slotPtr) {
|
|
2257
|
-
this.header = header;
|
|
2258
|
-
this.slotPtr = slotPtr;
|
|
2259
|
-
}
|
|
2260
|
-
}
|
|
2261
|
-
function arraysEqual(a, b) {
|
|
2262
|
-
if (a.length !== b.length)
|
|
2263
|
-
return false;
|
|
2264
|
-
for (let i = 0;i < a.length; i++) {
|
|
2265
|
-
if (a[i] !== b[i])
|
|
2266
|
-
return false;
|
|
2267
|
-
}
|
|
2268
|
-
return true;
|
|
2269
|
-
}
|
|
2270
|
-
function checkLong(n) {
|
|
2271
|
-
if (n < 0) {
|
|
2272
|
-
throw new ExpectedUnsignedLongException;
|
|
2273
|
-
}
|
|
2274
|
-
return n;
|
|
2275
|
-
}
|
|
2276
|
-
function bigIntShiftRight(value, bits) {
|
|
2277
|
-
let result = 0n;
|
|
2278
|
-
for (let i = 0;i < value.length; i++) {
|
|
2279
|
-
result = result << 8n | BigInt(value[i]);
|
|
2280
|
-
}
|
|
2281
|
-
return result >> BigInt(bits);
|
|
2282
|
-
}
|
|
2283
|
-
|
|
2284
|
-
class Database3 {
|
|
2285
|
-
core;
|
|
2286
|
-
hasher;
|
|
2287
|
-
header;
|
|
2288
|
-
txStart = null;
|
|
2289
|
-
constructor(core, hasher) {
|
|
2290
|
-
this.core = core;
|
|
2291
|
-
this.hasher = hasher;
|
|
2292
|
-
}
|
|
2293
|
-
static async create(core, hasher) {
|
|
2294
|
-
const db = new Database3(core, hasher);
|
|
2295
|
-
await core.seek(0);
|
|
2296
|
-
if (await core.length() === 0) {
|
|
2297
|
-
db.header = new Header(hasher.id, hasher.digestLength, VERSION, 0 /* NONE */, MAGIC_NUMBER);
|
|
2298
|
-
await db.header.write(core);
|
|
2299
|
-
await core.flush();
|
|
2300
|
-
} else {
|
|
2301
|
-
db.header = await Header.read(core);
|
|
2302
|
-
db.header.validate();
|
|
2303
|
-
if (db.header.hashSize !== hasher.digestLength) {
|
|
2304
|
-
throw new InvalidHashSizeException;
|
|
2305
|
-
}
|
|
2306
|
-
await db.truncate();
|
|
2307
|
-
}
|
|
2308
|
-
return db;
|
|
2309
|
-
}
|
|
2310
|
-
rootCursor() {
|
|
2311
|
-
return new WriteCursor(new SlotPointer(null, new Slot(Header.LENGTH, this.header.tag)), this);
|
|
2312
|
-
}
|
|
2313
|
-
async freeze() {
|
|
2314
|
-
if (this.txStart !== null) {
|
|
2315
|
-
this.txStart = await this.core.length();
|
|
2316
|
-
} else {
|
|
2317
|
-
throw new ExpectedTxStartException;
|
|
2318
|
-
}
|
|
2319
|
-
}
|
|
2320
|
-
async compact(targetCore) {
|
|
2321
|
-
const offsetMap = new Map;
|
|
2322
|
-
const hasher = new Hasher(this.hasher.algorithm, this.header.hashId);
|
|
2323
|
-
const target = await Database3.create(targetCore, hasher);
|
|
2324
|
-
if (this.header.tag === 0 /* NONE */)
|
|
2325
|
-
return target;
|
|
2326
|
-
if (this.header.tag !== 2 /* ARRAY_LIST */)
|
|
2327
|
-
throw new UnexpectedTagException;
|
|
2328
|
-
await this.core.seek(Header.LENGTH);
|
|
2329
|
-
const sourceReader = this.core.reader();
|
|
2330
|
-
const headerBytes = new Uint8Array(ArrayListHeader.LENGTH);
|
|
2331
|
-
await sourceReader.readFully(headerBytes);
|
|
2332
|
-
const sourceHeader = ArrayListHeader.fromBytes(headerBytes);
|
|
2333
|
-
if (sourceHeader.size === 0)
|
|
2334
|
-
return target;
|
|
2335
|
-
const lastKey = sourceHeader.size - 1;
|
|
2336
|
-
const shift = lastKey < SLOT_COUNT ? 0 : Math.floor(Math.log(lastKey) / Math.log(SLOT_COUNT));
|
|
2337
|
-
const lastSlotPtr = await this.readArrayListSlot(sourceHeader.ptr, lastKey, shift, 0 /* READ_ONLY */, true);
|
|
2338
|
-
const momentSlot = lastSlotPtr.slot;
|
|
2339
|
-
const targetWriter = targetCore.writer();
|
|
2340
|
-
await targetCore.seek(Header.LENGTH);
|
|
2341
|
-
const targetArrayListPtr = Header.LENGTH + TopLevelArrayListHeader.LENGTH;
|
|
2342
|
-
await targetWriter.write(new TopLevelArrayListHeader(0, new ArrayListHeader(targetArrayListPtr, 1)).toBytes());
|
|
2343
|
-
await targetWriter.write(new Uint8Array(INDEX_BLOCK_SIZE));
|
|
2344
|
-
const remappedMoment = await remapSlot(this.core, targetCore, this.header.hashSize, offsetMap, momentSlot);
|
|
2345
|
-
await targetCore.seek(targetArrayListPtr);
|
|
2346
|
-
await targetWriter.write(remappedMoment.toBytes());
|
|
2347
|
-
target.header = target.header.withTag(2 /* ARRAY_LIST */);
|
|
2348
|
-
await targetCore.seek(0);
|
|
2349
|
-
await target.header.write(targetCore);
|
|
2350
|
-
await targetCore.flush();
|
|
2351
|
-
const fileSize = await targetCore.length();
|
|
2352
|
-
await targetCore.seek(Header.LENGTH + ArrayListHeader.LENGTH);
|
|
2353
|
-
await targetWriter.writeLong(fileSize);
|
|
2354
|
-
await targetCore.flush();
|
|
2355
|
-
return target;
|
|
2356
|
-
}
|
|
2357
|
-
async truncate() {
|
|
2358
|
-
if (this.header.tag !== 2 /* ARRAY_LIST */)
|
|
2359
|
-
return;
|
|
2360
|
-
const rootCursor = this.rootCursor();
|
|
2361
|
-
const listSize = await rootCursor.count();
|
|
2362
|
-
if (listSize === 0)
|
|
2363
|
-
return;
|
|
2364
|
-
await this.core.seek(Header.LENGTH + ArrayListHeader.LENGTH);
|
|
2365
|
-
const reader = this.core.reader();
|
|
2366
|
-
const headerFileSize = await reader.readLong();
|
|
2367
|
-
if (headerFileSize === 0)
|
|
2368
|
-
return;
|
|
2369
|
-
const fileSize = await this.core.length();
|
|
2370
|
-
if (fileSize === headerFileSize)
|
|
2371
|
-
return;
|
|
2372
|
-
try {
|
|
2373
|
-
await this.core.setLength(headerFileSize);
|
|
2374
|
-
} catch (_) {}
|
|
2375
|
-
}
|
|
2376
|
-
checkHashBytes(hash) {
|
|
2377
|
-
if (hash.length !== this.header.hashSize) {
|
|
2378
|
-
throw new InvalidHashSizeException;
|
|
2379
|
-
}
|
|
2380
|
-
return hash;
|
|
2381
|
-
}
|
|
2382
|
-
checkHash(target) {
|
|
2383
|
-
return this.checkHashBytes(target.hash);
|
|
2384
|
-
}
|
|
2385
|
-
async readSlotPointer(writeMode, path, pathI, slotPtr) {
|
|
2386
|
-
if (pathI === path.length) {
|
|
2387
|
-
if (writeMode === 0 /* READ_ONLY */ && slotPtr.slot.tag === 0 /* NONE */) {
|
|
2388
|
-
throw new KeyNotFoundException;
|
|
2389
|
-
}
|
|
2390
|
-
return slotPtr;
|
|
2391
|
-
}
|
|
2392
|
-
const part = path[pathI];
|
|
2393
|
-
const isTopLevel = slotPtr.slot.value === BigInt(Header.LENGTH);
|
|
2394
|
-
const isTxStart = isTopLevel && this.header.tag === 2 /* ARRAY_LIST */ && this.txStart === null;
|
|
2395
|
-
if (isTxStart) {
|
|
2396
|
-
this.txStart = await this.core.length();
|
|
2397
|
-
}
|
|
2398
|
-
try {
|
|
2399
|
-
return await part.readSlotPointer(this, isTopLevel, writeMode, path, pathI, slotPtr);
|
|
2400
|
-
} finally {
|
|
2401
|
-
if (isTxStart) {
|
|
2402
|
-
this.txStart = null;
|
|
2403
|
-
}
|
|
2404
|
-
}
|
|
2405
|
-
}
|
|
2406
|
-
async readMapSlot(indexPos, keyHash, keyOffset, writeMode, isTopLevel, target) {
|
|
2407
|
-
if (keyOffset > this.header.hashSize * 8 / BIT_COUNT) {
|
|
2408
|
-
throw new KeyOffsetExceededException;
|
|
2409
|
-
}
|
|
2410
|
-
const reader = this.core.reader();
|
|
2411
|
-
const writer = this.core.writer();
|
|
2412
|
-
const i = Number(bigIntShiftRight(keyHash, keyOffset * BIT_COUNT) & MASK);
|
|
2413
|
-
const slotPos = indexPos + Slot.LENGTH * i;
|
|
2414
|
-
await this.core.seek(slotPos);
|
|
2415
|
-
const slotBytes = new Uint8Array(Slot.LENGTH);
|
|
2416
|
-
await reader.readFully(slotBytes);
|
|
2417
|
-
const slot = Slot.fromBytes(slotBytes);
|
|
2418
|
-
const ptr = Number(slot.value);
|
|
2419
|
-
switch (slot.tag) {
|
|
2420
|
-
case 0 /* NONE */: {
|
|
2421
|
-
switch (writeMode) {
|
|
2422
|
-
case 0 /* READ_ONLY */:
|
|
2423
|
-
throw new KeyNotFoundException;
|
|
2424
|
-
case 1 /* READ_WRITE */: {
|
|
2425
|
-
const hashPos = await this.core.length();
|
|
2426
|
-
await this.core.seek(hashPos);
|
|
2427
|
-
const keySlotPos = hashPos + this.header.hashSize;
|
|
2428
|
-
const valueSlotPos = keySlotPos + Slot.LENGTH;
|
|
2429
|
-
const kvPair = new KeyValuePair(new Slot, new Slot, keyHash);
|
|
2430
|
-
await writer.write(kvPair.toBytes());
|
|
2431
|
-
const nextSlot = new Slot(hashPos, 5 /* KV_PAIR */);
|
|
2432
|
-
await this.core.seek(slotPos);
|
|
2433
|
-
await writer.write(nextSlot.toBytes());
|
|
2434
|
-
let nextSlotPtr;
|
|
2435
|
-
if (target.kind === "kv_pair") {
|
|
2436
|
-
nextSlotPtr = new SlotPointer(slotPos, nextSlot);
|
|
2437
|
-
} else if (target.kind === "key") {
|
|
2438
|
-
nextSlotPtr = new SlotPointer(keySlotPos, kvPair.keySlot);
|
|
2439
|
-
} else {
|
|
2440
|
-
nextSlotPtr = new SlotPointer(valueSlotPos, kvPair.valueSlot);
|
|
2441
|
-
}
|
|
2442
|
-
return new HashMapGetResult(nextSlotPtr, true);
|
|
2443
|
-
}
|
|
2444
|
-
default:
|
|
2445
|
-
throw new UnreachableException;
|
|
2446
|
-
}
|
|
2447
|
-
}
|
|
2448
|
-
case 1 /* INDEX */: {
|
|
2449
|
-
let nextPtr = ptr;
|
|
2450
|
-
if (writeMode === 1 /* READ_WRITE */ && !isTopLevel) {
|
|
2451
|
-
if (this.txStart !== null) {
|
|
2452
|
-
if (nextPtr < this.txStart) {
|
|
2453
|
-
await this.core.seek(ptr);
|
|
2454
|
-
const indexBlock = new Uint8Array(INDEX_BLOCK_SIZE);
|
|
2455
|
-
await reader.readFully(indexBlock);
|
|
2456
|
-
nextPtr = await this.core.length();
|
|
2457
|
-
await this.core.seek(nextPtr);
|
|
2458
|
-
await writer.write(indexBlock);
|
|
2459
|
-
await this.core.seek(slotPos);
|
|
2460
|
-
await writer.write(new Slot(nextPtr, 1 /* INDEX */).toBytes());
|
|
2461
|
-
}
|
|
2462
|
-
} else if (this.header.tag === 2 /* ARRAY_LIST */) {
|
|
2463
|
-
throw new ExpectedTxStartException;
|
|
2464
|
-
}
|
|
2465
|
-
}
|
|
2466
|
-
return this.readMapSlot(nextPtr, keyHash, keyOffset + 1, writeMode, isTopLevel, target);
|
|
2467
|
-
}
|
|
2468
|
-
case 5 /* KV_PAIR */: {
|
|
2469
|
-
await this.core.seek(ptr);
|
|
2470
|
-
const kvPairBytes = new Uint8Array(KeyValuePair.length(this.header.hashSize));
|
|
2471
|
-
await reader.readFully(kvPairBytes);
|
|
2472
|
-
const kvPair = KeyValuePair.fromBytes(kvPairBytes, this.header.hashSize);
|
|
2473
|
-
if (arraysEqual(kvPair.hash, keyHash)) {
|
|
2474
|
-
if (writeMode === 1 /* READ_WRITE */ && !isTopLevel) {
|
|
2475
|
-
if (this.txStart !== null) {
|
|
2476
|
-
if (ptr < this.txStart) {
|
|
2477
|
-
const hashPos = await this.core.length();
|
|
2478
|
-
await this.core.seek(hashPos);
|
|
2479
|
-
const keySlotPos2 = hashPos + this.header.hashSize;
|
|
2480
|
-
const valueSlotPos2 = keySlotPos2 + Slot.LENGTH;
|
|
2481
|
-
await writer.write(kvPair.toBytes());
|
|
2482
|
-
const nextSlot = new Slot(hashPos, 5 /* KV_PAIR */);
|
|
2483
|
-
await this.core.seek(slotPos);
|
|
2484
|
-
await writer.write(nextSlot.toBytes());
|
|
2485
|
-
let nextSlotPtr2;
|
|
2486
|
-
if (target.kind === "kv_pair") {
|
|
2487
|
-
nextSlotPtr2 = new SlotPointer(slotPos, nextSlot);
|
|
2488
|
-
} else if (target.kind === "key") {
|
|
2489
|
-
nextSlotPtr2 = new SlotPointer(keySlotPos2, kvPair.keySlot);
|
|
2490
|
-
} else {
|
|
2491
|
-
nextSlotPtr2 = new SlotPointer(valueSlotPos2, kvPair.valueSlot);
|
|
2492
|
-
}
|
|
2493
|
-
return new HashMapGetResult(nextSlotPtr2, false);
|
|
2494
|
-
}
|
|
2495
|
-
} else if (this.header.tag === 2 /* ARRAY_LIST */) {
|
|
2496
|
-
throw new ExpectedTxStartException;
|
|
2497
|
-
}
|
|
2498
|
-
}
|
|
2499
|
-
const keySlotPos = ptr + this.header.hashSize;
|
|
2500
|
-
const valueSlotPos = keySlotPos + Slot.LENGTH;
|
|
2501
|
-
let nextSlotPtr;
|
|
2502
|
-
if (target.kind === "kv_pair") {
|
|
2503
|
-
nextSlotPtr = new SlotPointer(slotPos, slot);
|
|
2504
|
-
} else if (target.kind === "key") {
|
|
2505
|
-
nextSlotPtr = new SlotPointer(keySlotPos, kvPair.keySlot);
|
|
2506
|
-
} else {
|
|
2507
|
-
nextSlotPtr = new SlotPointer(valueSlotPos, kvPair.valueSlot);
|
|
2508
|
-
}
|
|
2509
|
-
return new HashMapGetResult(nextSlotPtr, false);
|
|
2510
|
-
} else {
|
|
2511
|
-
switch (writeMode) {
|
|
2512
|
-
case 0 /* READ_ONLY */:
|
|
2513
|
-
throw new KeyNotFoundException;
|
|
2514
|
-
case 1 /* READ_WRITE */: {
|
|
2515
|
-
if (keyOffset + 1 >= this.header.hashSize * 8 / BIT_COUNT) {
|
|
2516
|
-
throw new KeyOffsetExceededException;
|
|
2517
|
-
}
|
|
2518
|
-
const nextI = Number(bigIntShiftRight(kvPair.hash, (keyOffset + 1) * BIT_COUNT) & MASK);
|
|
2519
|
-
const nextIndexPos = await this.core.length();
|
|
2520
|
-
await this.core.seek(nextIndexPos);
|
|
2521
|
-
await writer.write(new Uint8Array(INDEX_BLOCK_SIZE));
|
|
2522
|
-
await this.core.seek(nextIndexPos + Slot.LENGTH * nextI);
|
|
2523
|
-
await writer.write(slot.toBytes());
|
|
2524
|
-
const res = await this.readMapSlot(nextIndexPos, keyHash, keyOffset + 1, writeMode, isTopLevel, target);
|
|
2525
|
-
await this.core.seek(slotPos);
|
|
2526
|
-
await writer.write(new Slot(nextIndexPos, 1 /* INDEX */).toBytes());
|
|
2527
|
-
return res;
|
|
2528
|
-
}
|
|
2529
|
-
default:
|
|
2530
|
-
throw new UnreachableException;
|
|
2531
|
-
}
|
|
2532
|
-
}
|
|
2533
|
-
}
|
|
2534
|
-
default:
|
|
2535
|
-
throw new UnexpectedTagException;
|
|
2536
|
-
}
|
|
2537
|
-
}
|
|
2538
|
-
async removeMapSlot(indexPos, keyHash, keyOffset, isTopLevel) {
|
|
2539
|
-
if (keyOffset > this.header.hashSize * 8 / BIT_COUNT) {
|
|
2540
|
-
throw new KeyOffsetExceededException;
|
|
2541
|
-
}
|
|
2542
|
-
const reader = this.core.reader();
|
|
2543
|
-
const writer = this.core.writer();
|
|
2544
|
-
const slotBlock = new Array(SLOT_COUNT);
|
|
2545
|
-
await this.core.seek(indexPos);
|
|
2546
|
-
const indexBlock = new Uint8Array(INDEX_BLOCK_SIZE);
|
|
2547
|
-
await reader.readFully(indexBlock);
|
|
2548
|
-
for (let i2 = 0;i2 < SLOT_COUNT; i2++) {
|
|
2549
|
-
const slotBytes = indexBlock.slice(i2 * Slot.LENGTH, (i2 + 1) * Slot.LENGTH);
|
|
2550
|
-
slotBlock[i2] = Slot.fromBytes(slotBytes);
|
|
2551
|
-
}
|
|
2552
|
-
const i = Number(bigIntShiftRight(keyHash, keyOffset * BIT_COUNT) & MASK);
|
|
2553
|
-
const slotPos = indexPos + Slot.LENGTH * i;
|
|
2554
|
-
const slot = slotBlock[i];
|
|
2555
|
-
let nextSlot;
|
|
2556
|
-
switch (slot.tag) {
|
|
2557
|
-
case 0 /* NONE */:
|
|
2558
|
-
throw new KeyNotFoundException;
|
|
2559
|
-
case 1 /* INDEX */:
|
|
2560
|
-
nextSlot = await this.removeMapSlot(Number(slot.value), keyHash, keyOffset + 1, isTopLevel);
|
|
2561
|
-
break;
|
|
2562
|
-
case 5 /* KV_PAIR */: {
|
|
2563
|
-
await this.core.seek(Number(slot.value));
|
|
2564
|
-
const kvPairBytes = new Uint8Array(KeyValuePair.length(this.header.hashSize));
|
|
2565
|
-
await reader.readFully(kvPairBytes);
|
|
2566
|
-
const kvPair = KeyValuePair.fromBytes(kvPairBytes, this.header.hashSize);
|
|
2567
|
-
if (arraysEqual(kvPair.hash, keyHash)) {
|
|
2568
|
-
nextSlot = new Slot;
|
|
2569
|
-
} else {
|
|
2570
|
-
throw new KeyNotFoundException;
|
|
2571
|
-
}
|
|
2572
|
-
break;
|
|
2573
|
-
}
|
|
2574
|
-
default:
|
|
2575
|
-
throw new UnexpectedTagException;
|
|
2576
|
-
}
|
|
2577
|
-
if (keyOffset === 0) {
|
|
2578
|
-
await this.core.seek(slotPos);
|
|
2579
|
-
await writer.write(nextSlot.toBytes());
|
|
2580
|
-
return new Slot(indexPos, 1 /* INDEX */);
|
|
2581
|
-
}
|
|
2582
|
-
let slotToReturnMaybe = new Slot;
|
|
2583
|
-
slotBlock[i] = nextSlot;
|
|
2584
|
-
for (const blockSlot of slotBlock) {
|
|
2585
|
-
if (blockSlot.tag === 0 /* NONE */)
|
|
2586
|
-
continue;
|
|
2587
|
-
if (slotToReturnMaybe !== null) {
|
|
2588
|
-
if (slotToReturnMaybe.tag !== 0 /* NONE */) {
|
|
2589
|
-
slotToReturnMaybe = null;
|
|
2590
|
-
break;
|
|
2591
|
-
}
|
|
2592
|
-
}
|
|
2593
|
-
slotToReturnMaybe = blockSlot;
|
|
2594
|
-
}
|
|
2595
|
-
if (slotToReturnMaybe !== null) {
|
|
2596
|
-
switch (slotToReturnMaybe.tag) {
|
|
2597
|
-
case 0 /* NONE */:
|
|
2598
|
-
case 5 /* KV_PAIR */:
|
|
2599
|
-
return slotToReturnMaybe;
|
|
2600
|
-
default:
|
|
2601
|
-
break;
|
|
2602
|
-
}
|
|
2603
|
-
}
|
|
2604
|
-
if (!isTopLevel) {
|
|
2605
|
-
if (this.txStart !== null) {
|
|
2606
|
-
if (indexPos < this.txStart) {
|
|
2607
|
-
const nextIndexPos = await this.core.length();
|
|
2608
|
-
await this.core.seek(nextIndexPos);
|
|
2609
|
-
await writer.write(indexBlock);
|
|
2610
|
-
const nextSlotPos = nextIndexPos + Slot.LENGTH * i;
|
|
2611
|
-
await this.core.seek(nextSlotPos);
|
|
2612
|
-
await writer.write(nextSlot.toBytes());
|
|
2613
|
-
return new Slot(nextIndexPos, 1 /* INDEX */);
|
|
2614
|
-
}
|
|
2615
|
-
} else if (this.header.tag === 2 /* ARRAY_LIST */) {
|
|
2616
|
-
throw new ExpectedTxStartException;
|
|
2617
|
-
}
|
|
2618
|
-
}
|
|
2619
|
-
await this.core.seek(slotPos);
|
|
2620
|
-
await writer.write(nextSlot.toBytes());
|
|
2621
|
-
return new Slot(indexPos, 1 /* INDEX */);
|
|
2622
|
-
}
|
|
2623
|
-
async readArrayListSlotAppend(header, writeMode, isTopLevel) {
|
|
2624
|
-
const writer = this.core.writer();
|
|
2625
|
-
let indexPos = header.ptr;
|
|
2626
|
-
const key = header.size;
|
|
2627
|
-
const prevShift = key < SLOT_COUNT ? 0 : Math.floor(Math.log(key - 1) / Math.log(SLOT_COUNT));
|
|
2628
|
-
const nextShift = key < SLOT_COUNT ? 0 : Math.floor(Math.log(key) / Math.log(SLOT_COUNT));
|
|
2629
|
-
if (prevShift !== nextShift) {
|
|
2630
|
-
const nextIndexPos = await this.core.length();
|
|
2631
|
-
await this.core.seek(nextIndexPos);
|
|
2632
|
-
await writer.write(new Uint8Array(INDEX_BLOCK_SIZE));
|
|
2633
|
-
await this.core.seek(nextIndexPos);
|
|
2634
|
-
await writer.write(new Slot(indexPos, 1 /* INDEX */).toBytes());
|
|
2635
|
-
indexPos = nextIndexPos;
|
|
2636
|
-
}
|
|
2637
|
-
const slotPtr = await this.readArrayListSlot(indexPos, key, nextShift, writeMode, isTopLevel);
|
|
2638
|
-
return new ArrayListAppendResult(new ArrayListHeader(indexPos, header.size + 1), slotPtr);
|
|
2639
|
-
}
|
|
2640
|
-
async readArrayListSlot(indexPos, key, shift, writeMode, isTopLevel) {
|
|
2641
|
-
if (shift >= MAX_BRANCH_LENGTH)
|
|
2642
|
-
throw new MaxShiftExceededException;
|
|
2643
|
-
const reader = this.core.reader();
|
|
2644
|
-
const i = key >>> shift * BIT_COUNT & SLOT_COUNT - 1;
|
|
2645
|
-
const slotPos = indexPos + Slot.LENGTH * i;
|
|
2646
|
-
await this.core.seek(slotPos);
|
|
2647
|
-
const slotBytes = new Uint8Array(Slot.LENGTH);
|
|
2648
|
-
await reader.readFully(slotBytes);
|
|
2649
|
-
const slot = Slot.fromBytes(slotBytes);
|
|
2650
|
-
if (shift === 0) {
|
|
2651
|
-
return new SlotPointer(slotPos, slot);
|
|
2652
|
-
}
|
|
2653
|
-
const ptr = Number(slot.value);
|
|
2654
|
-
switch (slot.tag) {
|
|
2655
|
-
case 0 /* NONE */: {
|
|
2656
|
-
switch (writeMode) {
|
|
2657
|
-
case 0 /* READ_ONLY */:
|
|
2658
|
-
throw new KeyNotFoundException;
|
|
2659
|
-
case 1 /* READ_WRITE */: {
|
|
2660
|
-
const writer = this.core.writer();
|
|
2661
|
-
const nextIndexPos = await this.core.length();
|
|
2662
|
-
await this.core.seek(nextIndexPos);
|
|
2663
|
-
await writer.write(new Uint8Array(INDEX_BLOCK_SIZE));
|
|
2664
|
-
if (isTopLevel) {
|
|
2665
|
-
const fileSize = await this.core.length();
|
|
2666
|
-
await this.core.seek(Header.LENGTH + ArrayListHeader.LENGTH);
|
|
2667
|
-
await writer.writeLong(fileSize);
|
|
2668
|
-
}
|
|
2669
|
-
await this.core.seek(slotPos);
|
|
2670
|
-
await writer.write(new Slot(nextIndexPos, 1 /* INDEX */).toBytes());
|
|
2671
|
-
return this.readArrayListSlot(nextIndexPos, key, shift - 1, writeMode, isTopLevel);
|
|
2672
|
-
}
|
|
2673
|
-
default:
|
|
2674
|
-
throw new UnreachableException;
|
|
2675
|
-
}
|
|
2676
|
-
}
|
|
2677
|
-
case 1 /* INDEX */: {
|
|
2678
|
-
let nextPtr = ptr;
|
|
2679
|
-
if (writeMode === 1 /* READ_WRITE */ && !isTopLevel) {
|
|
2680
|
-
if (this.txStart !== null) {
|
|
2681
|
-
if (nextPtr < this.txStart) {
|
|
2682
|
-
await this.core.seek(ptr);
|
|
2683
|
-
const indexBlock = new Uint8Array(INDEX_BLOCK_SIZE);
|
|
2684
|
-
await reader.readFully(indexBlock);
|
|
2685
|
-
const writer = this.core.writer();
|
|
2686
|
-
nextPtr = await this.core.length();
|
|
2687
|
-
await this.core.seek(nextPtr);
|
|
2688
|
-
await writer.write(indexBlock);
|
|
2689
|
-
await this.core.seek(slotPos);
|
|
2690
|
-
await writer.write(new Slot(nextPtr, 1 /* INDEX */).toBytes());
|
|
2691
|
-
}
|
|
2692
|
-
} else if (this.header.tag === 2 /* ARRAY_LIST */) {
|
|
2693
|
-
throw new ExpectedTxStartException;
|
|
2694
|
-
}
|
|
2695
|
-
}
|
|
2696
|
-
return this.readArrayListSlot(nextPtr, key, shift - 1, writeMode, isTopLevel);
|
|
2697
|
-
}
|
|
2698
|
-
default:
|
|
2699
|
-
throw new UnexpectedTagException;
|
|
2700
|
-
}
|
|
2701
|
-
}
|
|
2702
|
-
async readArrayListSlice(header, size) {
|
|
2703
|
-
const reader = this.core.reader();
|
|
2704
|
-
if (size > header.size || size < 0) {
|
|
2705
|
-
throw new KeyNotFoundException;
|
|
2706
|
-
}
|
|
2707
|
-
const prevShift = header.size < SLOT_COUNT + 1 ? 0 : Math.floor(Math.log(header.size - 1) / Math.log(SLOT_COUNT));
|
|
2708
|
-
const nextShift = size < SLOT_COUNT + 1 ? 0 : Math.floor(Math.log(size - 1) / Math.log(SLOT_COUNT));
|
|
2709
|
-
if (prevShift === nextShift) {
|
|
2710
|
-
return new ArrayListHeader(header.ptr, size);
|
|
2711
|
-
} else {
|
|
2712
|
-
let shift = prevShift;
|
|
2713
|
-
let indexPos = header.ptr;
|
|
2714
|
-
while (shift > nextShift) {
|
|
2715
|
-
await this.core.seek(indexPos);
|
|
2716
|
-
const slotBytes = new Uint8Array(Slot.LENGTH);
|
|
2717
|
-
await reader.readFully(slotBytes);
|
|
2718
|
-
const slot = Slot.fromBytes(slotBytes);
|
|
2719
|
-
shift -= 1;
|
|
2720
|
-
indexPos = Number(slot.value);
|
|
2721
|
-
}
|
|
2722
|
-
return new ArrayListHeader(indexPos, size);
|
|
2723
|
-
}
|
|
2724
|
-
}
|
|
2725
|
-
async readLinkedArrayListSlotAppend(header, writeMode, isTopLevel) {
|
|
2726
|
-
const writer = this.core.writer();
|
|
2727
|
-
let ptr = header.ptr;
|
|
2728
|
-
const key = header.size;
|
|
2729
|
-
let shift = header.shift;
|
|
2730
|
-
let slotPtr;
|
|
2731
|
-
try {
|
|
2732
|
-
slotPtr = await this.readLinkedArrayListSlot(ptr, key, shift, writeMode, isTopLevel);
|
|
2733
|
-
} catch (e) {
|
|
2734
|
-
if (e instanceof NoAvailableSlotsException) {
|
|
2735
|
-
const nextPtr = await this.core.length();
|
|
2736
|
-
await this.core.seek(nextPtr);
|
|
2737
|
-
await writer.write(new Uint8Array(LINKED_ARRAY_LIST_INDEX_BLOCK_SIZE));
|
|
2738
|
-
await this.core.seek(nextPtr);
|
|
2739
|
-
await writer.write(new LinkedArrayListSlot2(header.size, new Slot(ptr, 1 /* INDEX */, true)).toBytes());
|
|
2740
|
-
ptr = nextPtr;
|
|
2741
|
-
shift += 1;
|
|
2742
|
-
slotPtr = await this.readLinkedArrayListSlot(ptr, key, shift, writeMode, isTopLevel);
|
|
2743
|
-
} else {
|
|
2744
|
-
throw e;
|
|
2745
|
-
}
|
|
2746
|
-
}
|
|
2747
|
-
const newSlot = new Slot(0, 0 /* NONE */, true);
|
|
2748
|
-
slotPtr = slotPtr.withSlotPointer(slotPtr.slotPtr.withSlot(newSlot));
|
|
2749
|
-
if (slotPtr.slotPtr.position === null)
|
|
2750
|
-
throw new CursorNotWriteableException;
|
|
2751
|
-
const position = slotPtr.slotPtr.position;
|
|
2752
|
-
await this.core.seek(position);
|
|
2753
|
-
await writer.write(new LinkedArrayListSlot2(0, newSlot).toBytes());
|
|
2754
|
-
if (header.size < SLOT_COUNT && shift > 0) {
|
|
2755
|
-
throw new MustSetNewSlotsToFullException;
|
|
2756
|
-
}
|
|
2757
|
-
return new LinkedArrayListAppendResult(new LinkedArrayListHeader(shift, ptr, header.size + 1), slotPtr);
|
|
2758
|
-
}
|
|
2759
|
-
static blockLeafCount(block, shift, i) {
|
|
2760
|
-
let n = 0;
|
|
2761
|
-
if (shift === 0) {
|
|
2762
|
-
for (let blockI = 0;blockI < block.length; blockI++) {
|
|
2763
|
-
const blockSlot = block[blockI];
|
|
2764
|
-
if (!blockSlot.slot.empty() || blockI === i) {
|
|
2765
|
-
n += 1;
|
|
2766
|
-
}
|
|
2767
|
-
}
|
|
2768
|
-
} else {
|
|
2769
|
-
for (const blockSlot of block) {
|
|
2770
|
-
n += blockSlot.size;
|
|
2771
|
-
}
|
|
2772
|
-
}
|
|
2773
|
-
return n;
|
|
2774
|
-
}
|
|
2775
|
-
static slotLeafCount(slot, shift) {
|
|
2776
|
-
if (shift === 0) {
|
|
2777
|
-
if (slot.slot.empty()) {
|
|
2778
|
-
return 0;
|
|
2779
|
-
} else {
|
|
2780
|
-
return 1;
|
|
2781
|
-
}
|
|
2782
|
-
} else {
|
|
2783
|
-
return slot.size;
|
|
2784
|
-
}
|
|
2785
|
-
}
|
|
2786
|
-
static keyAndIndexForLinkedArrayList(slotBlock, key, shift) {
|
|
2787
|
-
let nextKey = key;
|
|
2788
|
-
let i = 0;
|
|
2789
|
-
const maxLeafCount = shift === 0 ? 1 : Math.pow(SLOT_COUNT, shift);
|
|
2790
|
-
while (true) {
|
|
2791
|
-
const slotLeafCount = Database3.slotLeafCount(slotBlock[i], shift);
|
|
2792
|
-
if (nextKey === slotLeafCount) {
|
|
2793
|
-
if (slotLeafCount === maxLeafCount || slotBlock[i].slot.full) {
|
|
2794
|
-
if (i < SLOT_COUNT - 1) {
|
|
2795
|
-
nextKey -= slotLeafCount;
|
|
2796
|
-
i += 1;
|
|
2797
|
-
} else {
|
|
2798
|
-
return null;
|
|
2799
|
-
}
|
|
2800
|
-
}
|
|
2801
|
-
break;
|
|
2802
|
-
} else if (nextKey < slotLeafCount) {
|
|
2803
|
-
break;
|
|
2804
|
-
} else if (i < SLOT_COUNT - 1) {
|
|
2805
|
-
nextKey -= slotLeafCount;
|
|
2806
|
-
i += 1;
|
|
2807
|
-
} else {
|
|
2808
|
-
return null;
|
|
2809
|
-
}
|
|
2810
|
-
}
|
|
2811
|
-
return { key: nextKey, index: i };
|
|
2812
|
-
}
|
|
2813
|
-
async readLinkedArrayListSlot(indexPos, key, shift, writeMode, isTopLevel) {
|
|
2814
|
-
if (shift >= MAX_BRANCH_LENGTH)
|
|
2815
|
-
throw new MaxShiftExceededException;
|
|
2816
|
-
const reader = this.core.reader();
|
|
2817
|
-
const writer = this.core.writer();
|
|
2818
|
-
const slotBlock = new Array(SLOT_COUNT);
|
|
2819
|
-
await this.core.seek(indexPos);
|
|
2820
|
-
const indexBlock = new Uint8Array(LINKED_ARRAY_LIST_INDEX_BLOCK_SIZE);
|
|
2821
|
-
await reader.readFully(indexBlock);
|
|
2822
|
-
for (let i2 = 0;i2 < SLOT_COUNT; i2++) {
|
|
2823
|
-
const slotBytes = indexBlock.slice(i2 * LinkedArrayListSlot2.LENGTH, (i2 + 1) * LinkedArrayListSlot2.LENGTH);
|
|
2824
|
-
slotBlock[i2] = LinkedArrayListSlot2.fromBytes(slotBytes);
|
|
2825
|
-
}
|
|
2826
|
-
const keyAndIndex = Database3.keyAndIndexForLinkedArrayList(slotBlock, key, shift);
|
|
2827
|
-
if (keyAndIndex === null)
|
|
2828
|
-
throw new NoAvailableSlotsException;
|
|
2829
|
-
const nextKey = keyAndIndex.key;
|
|
2830
|
-
const i = keyAndIndex.index;
|
|
2831
|
-
const slot = slotBlock[i];
|
|
2832
|
-
const slotPos = indexPos + LinkedArrayListSlot2.LENGTH * i;
|
|
2833
|
-
if (shift === 0) {
|
|
2834
|
-
const leafCount = Database3.blockLeafCount(slotBlock, shift, i);
|
|
2835
|
-
return new LinkedArrayListSlotPointer(new SlotPointer(slotPos, slot.slot), leafCount);
|
|
2836
|
-
}
|
|
2837
|
-
const ptr = Number(slot.slot.value);
|
|
2838
|
-
switch (slot.slot.tag) {
|
|
2839
|
-
case 0 /* NONE */: {
|
|
2840
|
-
switch (writeMode) {
|
|
2841
|
-
case 0 /* READ_ONLY */:
|
|
2842
|
-
throw new KeyNotFoundException;
|
|
2843
|
-
case 1 /* READ_WRITE */: {
|
|
2844
|
-
const nextIndexPos = await this.core.length();
|
|
2845
|
-
await this.core.seek(nextIndexPos);
|
|
2846
|
-
await writer.write(new Uint8Array(LINKED_ARRAY_LIST_INDEX_BLOCK_SIZE));
|
|
2847
|
-
const nextSlotPtr = await this.readLinkedArrayListSlot(nextIndexPos, nextKey, shift - 1, writeMode, isTopLevel);
|
|
2848
|
-
slotBlock[i] = slotBlock[i].withSize(nextSlotPtr.leafCount);
|
|
2849
|
-
const leafCount = Database3.blockLeafCount(slotBlock, shift, i);
|
|
2850
|
-
await this.core.seek(slotPos);
|
|
2851
|
-
await writer.write(new LinkedArrayListSlot2(nextSlotPtr.leafCount, new Slot(nextIndexPos, 1 /* INDEX */)).toBytes());
|
|
2852
|
-
return new LinkedArrayListSlotPointer(nextSlotPtr.slotPtr, leafCount);
|
|
2853
|
-
}
|
|
2854
|
-
default:
|
|
2855
|
-
throw new UnreachableException;
|
|
2856
|
-
}
|
|
2857
|
-
}
|
|
2858
|
-
case 1 /* INDEX */: {
|
|
2859
|
-
let nextPtr = ptr;
|
|
2860
|
-
if (writeMode === 1 /* READ_WRITE */ && !isTopLevel) {
|
|
2861
|
-
if (this.txStart !== null) {
|
|
2862
|
-
if (nextPtr < this.txStart) {
|
|
2863
|
-
await this.core.seek(ptr);
|
|
2864
|
-
const indexBlockCopy = new Uint8Array(LINKED_ARRAY_LIST_INDEX_BLOCK_SIZE);
|
|
2865
|
-
await reader.readFully(indexBlockCopy);
|
|
2866
|
-
nextPtr = await this.core.length();
|
|
2867
|
-
await this.core.seek(nextPtr);
|
|
2868
|
-
await writer.write(indexBlockCopy);
|
|
2869
|
-
}
|
|
2870
|
-
} else if (this.header.tag === 2 /* ARRAY_LIST */) {
|
|
2871
|
-
throw new ExpectedTxStartException;
|
|
2872
|
-
}
|
|
2873
|
-
}
|
|
2874
|
-
const nextSlotPtr = await this.readLinkedArrayListSlot(nextPtr, nextKey, shift - 1, writeMode, isTopLevel);
|
|
2875
|
-
slotBlock[i] = slotBlock[i].withSize(nextSlotPtr.leafCount);
|
|
2876
|
-
const leafCount = Database3.blockLeafCount(slotBlock, shift, i);
|
|
2877
|
-
if (writeMode === 1 /* READ_WRITE */ && !isTopLevel) {
|
|
2878
|
-
await this.core.seek(slotPos);
|
|
2879
|
-
await writer.write(new LinkedArrayListSlot2(nextSlotPtr.leafCount, new Slot(nextPtr, 1 /* INDEX */)).toBytes());
|
|
2880
|
-
}
|
|
2881
|
-
return new LinkedArrayListSlotPointer(nextSlotPtr.slotPtr, leafCount);
|
|
2882
|
-
}
|
|
2883
|
-
default:
|
|
2884
|
-
throw new UnexpectedTagException;
|
|
2885
|
-
}
|
|
2886
|
-
}
|
|
2887
|
-
async readLinkedArrayListBlocks(indexPos, key, shift, blocks) {
|
|
2888
|
-
const reader = this.core.reader();
|
|
2889
|
-
const slotBlock = new Array(SLOT_COUNT);
|
|
2890
|
-
await this.core.seek(indexPos);
|
|
2891
|
-
const indexBlock = new Uint8Array(LINKED_ARRAY_LIST_INDEX_BLOCK_SIZE);
|
|
2892
|
-
await reader.readFully(indexBlock);
|
|
2893
|
-
for (let i2 = 0;i2 < SLOT_COUNT; i2++) {
|
|
2894
|
-
const slotBytes = indexBlock.slice(i2 * LinkedArrayListSlot2.LENGTH, (i2 + 1) * LinkedArrayListSlot2.LENGTH);
|
|
2895
|
-
slotBlock[i2] = LinkedArrayListSlot2.fromBytes(slotBytes);
|
|
2896
|
-
}
|
|
2897
|
-
const keyAndIndex = Database3.keyAndIndexForLinkedArrayList(slotBlock, key, shift);
|
|
2898
|
-
if (keyAndIndex === null)
|
|
2899
|
-
throw new NoAvailableSlotsException;
|
|
2900
|
-
const nextKey = keyAndIndex.key;
|
|
2901
|
-
const i = keyAndIndex.index;
|
|
2902
|
-
const leafCount = Database3.blockLeafCount(slotBlock, shift, i);
|
|
2903
|
-
blocks.push(new LinkedArrayListBlockInfo(slotBlock, i, new LinkedArrayListSlot2(leafCount, new Slot(indexPos, 1 /* INDEX */))));
|
|
2904
|
-
if (shift === 0) {
|
|
2905
|
-
return;
|
|
2906
|
-
}
|
|
2907
|
-
const slot = slotBlock[i];
|
|
2908
|
-
switch (slot.slot.tag) {
|
|
2909
|
-
case 0 /* NONE */:
|
|
2910
|
-
throw new EmptySlotException;
|
|
2911
|
-
case 1 /* INDEX */:
|
|
2912
|
-
await this.readLinkedArrayListBlocks(Number(slot.slot.value), nextKey, shift - 1, blocks);
|
|
2913
|
-
break;
|
|
2914
|
-
default:
|
|
2915
|
-
throw new UnexpectedTagException;
|
|
2916
|
-
}
|
|
2917
|
-
}
|
|
2918
|
-
populateArray(arr) {
|
|
2919
|
-
for (let i = 0;i < arr.length; i++) {
|
|
2920
|
-
arr[i] = new LinkedArrayListSlot2(0, new Slot);
|
|
2921
|
-
}
|
|
2922
|
-
}
|
|
2923
|
-
async readLinkedArrayListSlice(header, offset, size) {
|
|
2924
|
-
const writer = this.core.writer();
|
|
2925
|
-
if (offset + size > header.size) {
|
|
2926
|
-
throw new KeyNotFoundException;
|
|
2927
|
-
}
|
|
2928
|
-
const leftBlocks = [];
|
|
2929
|
-
await this.readLinkedArrayListBlocks(header.ptr, offset, header.shift, leftBlocks);
|
|
2930
|
-
const rightBlocks = [];
|
|
2931
|
-
const rightKey = offset + size === 0 ? 0 : offset + size - 1;
|
|
2932
|
-
await this.readLinkedArrayListBlocks(header.ptr, rightKey, header.shift, rightBlocks);
|
|
2933
|
-
const blockCount = leftBlocks.length;
|
|
2934
|
-
let nextSlots = [null, null];
|
|
2935
|
-
let nextShift = 0;
|
|
2936
|
-
for (let i = 0;i < blockCount; i++) {
|
|
2937
|
-
const isLeafNode = nextSlots[0] === null;
|
|
2938
|
-
const leftBlock = leftBlocks[blockCount - i - 1];
|
|
2939
|
-
const rightBlock = rightBlocks[blockCount - i - 1];
|
|
2940
|
-
const origBlockInfos = [leftBlock, rightBlock];
|
|
2941
|
-
let nextBlocks = [null, null];
|
|
2942
|
-
if (leftBlock.parentSlot.slot.value === rightBlock.parentSlot.slot.value) {
|
|
2943
|
-
let slotI = 0;
|
|
2944
|
-
const newRootBlock = new Array(SLOT_COUNT);
|
|
2945
|
-
this.populateArray(newRootBlock);
|
|
2946
|
-
if (size > 0) {
|
|
2947
|
-
if (nextSlots[0] !== null) {
|
|
2948
|
-
newRootBlock[slotI] = nextSlots[0];
|
|
2949
|
-
} else {
|
|
2950
|
-
newRootBlock[slotI] = leftBlock.block[leftBlock.i];
|
|
2951
|
-
}
|
|
2952
|
-
slotI += 1;
|
|
2953
|
-
}
|
|
2954
|
-
if (size > 1) {
|
|
2955
|
-
for (let j = leftBlock.i + 1;j < rightBlock.i; j++) {
|
|
2956
|
-
const middleSlot = leftBlock.block[j];
|
|
2957
|
-
newRootBlock[slotI] = middleSlot;
|
|
2958
|
-
slotI += 1;
|
|
2959
|
-
}
|
|
2960
|
-
if (nextSlots[1] !== null) {
|
|
2961
|
-
newRootBlock[slotI] = nextSlots[1];
|
|
2962
|
-
} else {
|
|
2963
|
-
newRootBlock[slotI] = leftBlock.block[rightBlock.i];
|
|
2964
|
-
}
|
|
2965
|
-
}
|
|
2966
|
-
nextBlocks[0] = newRootBlock;
|
|
2967
|
-
} else {
|
|
2968
|
-
let slotI = 0;
|
|
2969
|
-
const newLeftBlock = new Array(SLOT_COUNT);
|
|
2970
|
-
this.populateArray(newLeftBlock);
|
|
2971
|
-
if (nextSlots[0] !== null) {
|
|
2972
|
-
newLeftBlock[slotI] = nextSlots[0];
|
|
2973
|
-
} else {
|
|
2974
|
-
newLeftBlock[slotI] = leftBlock.block[leftBlock.i];
|
|
2975
|
-
}
|
|
2976
|
-
slotI += 1;
|
|
2977
|
-
for (let j = leftBlock.i + 1;j < leftBlock.block.length; j++) {
|
|
2978
|
-
const nextSlot = leftBlock.block[j];
|
|
2979
|
-
newLeftBlock[slotI] = nextSlot;
|
|
2980
|
-
slotI += 1;
|
|
2981
|
-
}
|
|
2982
|
-
nextBlocks[0] = newLeftBlock;
|
|
2983
|
-
slotI = 0;
|
|
2984
|
-
const newRightBlock = new Array(SLOT_COUNT);
|
|
2985
|
-
this.populateArray(newRightBlock);
|
|
2986
|
-
for (let j = 0;j < rightBlock.i; j++) {
|
|
2987
|
-
const firstSlot = rightBlock.block[j];
|
|
2988
|
-
newRightBlock[slotI] = firstSlot;
|
|
2989
|
-
slotI += 1;
|
|
2990
|
-
}
|
|
2991
|
-
if (nextSlots[1] !== null) {
|
|
2992
|
-
newRightBlock[slotI] = nextSlots[1];
|
|
2993
|
-
} else {
|
|
2994
|
-
newRightBlock[slotI] = rightBlock.block[rightBlock.i];
|
|
2995
|
-
}
|
|
2996
|
-
nextBlocks[1] = newRightBlock;
|
|
2997
|
-
nextShift += 1;
|
|
2998
|
-
}
|
|
2999
|
-
nextSlots = [null, null];
|
|
3000
|
-
await this.core.seek(await this.core.length());
|
|
3001
|
-
for (let j = 0;j < 2; j++) {
|
|
3002
|
-
const blockMaybe = nextBlocks[j];
|
|
3003
|
-
const origBlockInfo = origBlockInfos[j];
|
|
3004
|
-
if (blockMaybe !== null) {
|
|
3005
|
-
let eql = true;
|
|
3006
|
-
for (let k = 0;k < blockMaybe.length; k++) {
|
|
3007
|
-
const blockSlot = blockMaybe[k];
|
|
3008
|
-
const origSlot = origBlockInfo.block[k];
|
|
3009
|
-
if (!blockSlot.slot.equals(origSlot.slot)) {
|
|
3010
|
-
eql = false;
|
|
3011
|
-
break;
|
|
3012
|
-
}
|
|
3013
|
-
}
|
|
3014
|
-
if (eql) {
|
|
3015
|
-
nextSlots[j] = origBlockInfo.parentSlot;
|
|
3016
|
-
} else {
|
|
3017
|
-
const nextPtr = await this.core.position();
|
|
3018
|
-
let leafCount = 0;
|
|
3019
|
-
for (let k = 0;k < blockMaybe.length; k++) {
|
|
3020
|
-
const blockSlot = blockMaybe[k];
|
|
3021
|
-
await writer.write(blockSlot.toBytes());
|
|
3022
|
-
if (isLeafNode) {
|
|
3023
|
-
if (!blockSlot.slot.empty()) {
|
|
3024
|
-
leafCount += 1;
|
|
3025
|
-
}
|
|
3026
|
-
} else {
|
|
3027
|
-
leafCount += blockSlot.size;
|
|
3028
|
-
}
|
|
3029
|
-
}
|
|
3030
|
-
nextSlots[j] = new LinkedArrayListSlot2(leafCount, j === 0 ? new Slot(nextPtr, 1 /* INDEX */, true) : new Slot(nextPtr, 1 /* INDEX */));
|
|
3031
|
-
}
|
|
3032
|
-
}
|
|
3033
|
-
}
|
|
3034
|
-
if (nextSlots[0] !== null && nextSlots[1] === null) {
|
|
3035
|
-
break;
|
|
3036
|
-
}
|
|
3037
|
-
}
|
|
3038
|
-
const rootSlot = nextSlots[0];
|
|
3039
|
-
if (rootSlot === null)
|
|
3040
|
-
throw new ExpectedRootNodeException;
|
|
3041
|
-
return new LinkedArrayListHeader(nextShift, Number(rootSlot.slot.value), size);
|
|
3042
|
-
}
|
|
3043
|
-
async readLinkedArrayListConcat(headerA, headerB) {
|
|
3044
|
-
const writer = this.core.writer();
|
|
3045
|
-
const blocksA = [];
|
|
3046
|
-
const keyA = headerA.size === 0 ? 0 : headerA.size - 1;
|
|
3047
|
-
await this.readLinkedArrayListBlocks(headerA.ptr, keyA, headerA.shift, blocksA);
|
|
3048
|
-
const blocksB = [];
|
|
3049
|
-
await this.readLinkedArrayListBlocks(headerB.ptr, 0, headerB.shift, blocksB);
|
|
3050
|
-
let nextSlots = [null, null];
|
|
3051
|
-
let nextShift = 0;
|
|
3052
|
-
for (let i = 0;i < Math.max(blocksA.length, blocksB.length); i++) {
|
|
3053
|
-
const blockInfos = [
|
|
3054
|
-
i < blocksA.length ? blocksA[blocksA.length - 1 - i] : null,
|
|
3055
|
-
i < blocksB.length ? blocksB[blocksB.length - 1 - i] : null
|
|
3056
|
-
];
|
|
3057
|
-
let nextBlocks = [null, null];
|
|
3058
|
-
const isLeafNode = nextSlots[0] === null;
|
|
3059
|
-
if (!isLeafNode) {
|
|
3060
|
-
nextShift += 1;
|
|
3061
|
-
}
|
|
3062
|
-
for (let j = 0;j < 2; j++) {
|
|
3063
|
-
const blockInfoMaybe = blockInfos[j];
|
|
3064
|
-
if (blockInfoMaybe !== null) {
|
|
3065
|
-
const block = new Array(SLOT_COUNT);
|
|
3066
|
-
this.populateArray(block);
|
|
3067
|
-
let targetI = 0;
|
|
3068
|
-
for (let sourceI = 0;sourceI < blockInfoMaybe.block.length; sourceI++) {
|
|
3069
|
-
const blockSlot = blockInfoMaybe.block[sourceI];
|
|
3070
|
-
if (!isLeafNode && blockInfoMaybe.i === sourceI) {
|
|
3071
|
-
continue;
|
|
3072
|
-
} else if (blockSlot.slot.empty()) {
|
|
3073
|
-
break;
|
|
3074
|
-
}
|
|
3075
|
-
block[targetI] = blockSlot;
|
|
3076
|
-
targetI += 1;
|
|
3077
|
-
}
|
|
3078
|
-
if (targetI === 0) {
|
|
3079
|
-
continue;
|
|
3080
|
-
}
|
|
3081
|
-
nextBlocks[j] = block;
|
|
3082
|
-
}
|
|
3083
|
-
}
|
|
3084
|
-
const slotsToWrite = new Array(SLOT_COUNT * 2);
|
|
3085
|
-
this.populateArray(slotsToWrite);
|
|
3086
|
-
let slotI = 0;
|
|
3087
|
-
if (nextBlocks[0] !== null) {
|
|
3088
|
-
for (const blockSlot of nextBlocks[0]) {
|
|
3089
|
-
if (blockSlot.slot.empty()) {
|
|
3090
|
-
break;
|
|
3091
|
-
}
|
|
3092
|
-
slotsToWrite[slotI] = blockSlot;
|
|
3093
|
-
slotI += 1;
|
|
3094
|
-
}
|
|
3095
|
-
}
|
|
3096
|
-
for (const slotMaybe of nextSlots) {
|
|
3097
|
-
if (slotMaybe !== null) {
|
|
3098
|
-
slotsToWrite[slotI] = slotMaybe;
|
|
3099
|
-
slotI += 1;
|
|
3100
|
-
}
|
|
3101
|
-
}
|
|
3102
|
-
if (nextBlocks[1] !== null) {
|
|
3103
|
-
for (const blockSlot of nextBlocks[1]) {
|
|
3104
|
-
if (blockSlot.slot.empty()) {
|
|
3105
|
-
break;
|
|
3106
|
-
}
|
|
3107
|
-
slotsToWrite[slotI] = blockSlot;
|
|
3108
|
-
slotI += 1;
|
|
3109
|
-
}
|
|
3110
|
-
}
|
|
3111
|
-
nextSlots = [null, null];
|
|
3112
|
-
const blocks = [new Array(SLOT_COUNT), new Array(SLOT_COUNT)];
|
|
3113
|
-
this.populateArray(blocks[0]);
|
|
3114
|
-
this.populateArray(blocks[1]);
|
|
3115
|
-
if (slotI > SLOT_COUNT) {
|
|
3116
|
-
if (headerA.size < headerB.size) {
|
|
3117
|
-
for (let j = 0;j < slotI - SLOT_COUNT; j++) {
|
|
3118
|
-
blocks[0][j] = slotsToWrite[j];
|
|
3119
|
-
}
|
|
3120
|
-
for (let j = 0;j < SLOT_COUNT; j++) {
|
|
3121
|
-
blocks[1][j] = slotsToWrite[j + (slotI - SLOT_COUNT)];
|
|
3122
|
-
}
|
|
3123
|
-
} else {
|
|
3124
|
-
for (let j = 0;j < SLOT_COUNT; j++) {
|
|
3125
|
-
blocks[0][j] = slotsToWrite[j];
|
|
3126
|
-
}
|
|
3127
|
-
for (let j = 0;j < slotI - SLOT_COUNT; j++) {
|
|
3128
|
-
blocks[1][j] = slotsToWrite[j + SLOT_COUNT];
|
|
3129
|
-
}
|
|
3130
|
-
}
|
|
3131
|
-
} else {
|
|
3132
|
-
for (let j = 0;j < slotI; j++) {
|
|
3133
|
-
blocks[0][j] = slotsToWrite[j];
|
|
3134
|
-
}
|
|
3135
|
-
}
|
|
3136
|
-
await this.core.seek(await this.core.length());
|
|
3137
|
-
for (let blockI = 0;blockI < blocks.length; blockI++) {
|
|
3138
|
-
const block = blocks[blockI];
|
|
3139
|
-
if (block[0].slot.empty()) {
|
|
3140
|
-
break;
|
|
3141
|
-
}
|
|
3142
|
-
const nextPtr = await this.core.position();
|
|
3143
|
-
let leafCount = 0;
|
|
3144
|
-
for (const blockSlot of block) {
|
|
3145
|
-
await writer.write(blockSlot.toBytes());
|
|
3146
|
-
if (isLeafNode) {
|
|
3147
|
-
if (!blockSlot.slot.empty()) {
|
|
3148
|
-
leafCount += 1;
|
|
3149
|
-
}
|
|
3150
|
-
} else {
|
|
3151
|
-
leafCount += blockSlot.size;
|
|
3152
|
-
}
|
|
3153
|
-
}
|
|
3154
|
-
nextSlots[blockI] = new LinkedArrayListSlot2(leafCount, new Slot(nextPtr, 1 /* INDEX */, true));
|
|
3155
|
-
}
|
|
3156
|
-
}
|
|
3157
|
-
let rootPtr;
|
|
3158
|
-
if (nextSlots[0] !== null) {
|
|
3159
|
-
if (nextSlots[1] !== null) {
|
|
3160
|
-
const block = new Array(SLOT_COUNT);
|
|
3161
|
-
this.populateArray(block);
|
|
3162
|
-
block[0] = nextSlots[0];
|
|
3163
|
-
block[1] = nextSlots[1];
|
|
3164
|
-
const newPtr = await this.core.length();
|
|
3165
|
-
for (const blockSlot of block) {
|
|
3166
|
-
await writer.write(blockSlot.toBytes());
|
|
3167
|
-
}
|
|
3168
|
-
if (nextShift === MAX_BRANCH_LENGTH)
|
|
3169
|
-
throw new MaxShiftExceededException;
|
|
3170
|
-
nextShift += 1;
|
|
3171
|
-
rootPtr = newPtr;
|
|
3172
|
-
} else {
|
|
3173
|
-
rootPtr = Number(nextSlots[0].slot.value);
|
|
3174
|
-
}
|
|
3175
|
-
} else {
|
|
3176
|
-
rootPtr = headerA.ptr;
|
|
3177
|
-
}
|
|
3178
|
-
return new LinkedArrayListHeader(nextShift, rootPtr, headerA.size + headerB.size);
|
|
3179
|
-
}
|
|
3180
|
-
}
|
|
3181
|
-
async function remapSlot(sourceCore, targetCore, hashSize, offsetMap, slot) {
|
|
3182
|
-
switch (slot.tag) {
|
|
3183
|
-
case 0 /* NONE */:
|
|
3184
|
-
case 8 /* UINT */:
|
|
3185
|
-
case 9 /* INT */:
|
|
3186
|
-
case 10 /* FLOAT */:
|
|
3187
|
-
case 7 /* SHORT_BYTES */:
|
|
3188
|
-
return slot;
|
|
3189
|
-
case 6 /* BYTES */: {
|
|
3190
|
-
const mapped = offsetMap.get(Number(slot.value));
|
|
3191
|
-
if (mapped !== undefined)
|
|
3192
|
-
return new Slot(mapped, slot.tag, slot.full);
|
|
3193
|
-
const newOffset = await remapBytes(sourceCore, targetCore, slot);
|
|
3194
|
-
offsetMap.set(Number(slot.value), newOffset);
|
|
3195
|
-
return new Slot(newOffset, slot.tag, slot.full);
|
|
3196
|
-
}
|
|
3197
|
-
case 1 /* INDEX */: {
|
|
3198
|
-
const mapped = offsetMap.get(Number(slot.value));
|
|
3199
|
-
if (mapped !== undefined)
|
|
3200
|
-
return new Slot(mapped, slot.tag, slot.full);
|
|
3201
|
-
const newOffset = await remapIndex(sourceCore, targetCore, hashSize, offsetMap, slot);
|
|
3202
|
-
offsetMap.set(Number(slot.value), newOffset);
|
|
3203
|
-
return new Slot(newOffset, slot.tag, slot.full);
|
|
3204
|
-
}
|
|
3205
|
-
case 2 /* ARRAY_LIST */: {
|
|
3206
|
-
const mapped = offsetMap.get(Number(slot.value));
|
|
3207
|
-
if (mapped !== undefined)
|
|
3208
|
-
return new Slot(mapped, slot.tag, slot.full);
|
|
3209
|
-
const newOffset = await remapArrayList(sourceCore, targetCore, hashSize, offsetMap, slot);
|
|
3210
|
-
offsetMap.set(Number(slot.value), newOffset);
|
|
3211
|
-
return new Slot(newOffset, slot.tag, slot.full);
|
|
3212
|
-
}
|
|
3213
|
-
case 3 /* LINKED_ARRAY_LIST */: {
|
|
3214
|
-
const mapped = offsetMap.get(Number(slot.value));
|
|
3215
|
-
if (mapped !== undefined)
|
|
3216
|
-
return new Slot(mapped, slot.tag, slot.full);
|
|
3217
|
-
const newOffset = await remapLinkedArrayList(sourceCore, targetCore, hashSize, offsetMap, slot);
|
|
3218
|
-
offsetMap.set(Number(slot.value), newOffset);
|
|
3219
|
-
return new Slot(newOffset, slot.tag, slot.full);
|
|
3220
|
-
}
|
|
3221
|
-
case 4 /* HASH_MAP */:
|
|
3222
|
-
case 11 /* HASH_SET */: {
|
|
3223
|
-
const mapped = offsetMap.get(Number(slot.value));
|
|
3224
|
-
if (mapped !== undefined)
|
|
3225
|
-
return new Slot(mapped, slot.tag, slot.full);
|
|
3226
|
-
const newOffset = await remapHashMapOrSet(sourceCore, targetCore, hashSize, offsetMap, slot, false);
|
|
3227
|
-
offsetMap.set(Number(slot.value), newOffset);
|
|
3228
|
-
return new Slot(newOffset, slot.tag, slot.full);
|
|
3229
|
-
}
|
|
3230
|
-
case 12 /* COUNTED_HASH_MAP */:
|
|
3231
|
-
case 13 /* COUNTED_HASH_SET */: {
|
|
3232
|
-
const mapped = offsetMap.get(Number(slot.value));
|
|
3233
|
-
if (mapped !== undefined)
|
|
3234
|
-
return new Slot(mapped, slot.tag, slot.full);
|
|
3235
|
-
const newOffset = await remapHashMapOrSet(sourceCore, targetCore, hashSize, offsetMap, slot, true);
|
|
3236
|
-
offsetMap.set(Number(slot.value), newOffset);
|
|
3237
|
-
return new Slot(newOffset, slot.tag, slot.full);
|
|
3238
|
-
}
|
|
3239
|
-
case 5 /* KV_PAIR */: {
|
|
3240
|
-
const mapped = offsetMap.get(Number(slot.value));
|
|
3241
|
-
if (mapped !== undefined)
|
|
3242
|
-
return new Slot(mapped, slot.tag, slot.full);
|
|
3243
|
-
const newOffset = await remapKvPair(sourceCore, targetCore, hashSize, offsetMap, slot);
|
|
3244
|
-
offsetMap.set(Number(slot.value), newOffset);
|
|
3245
|
-
return new Slot(newOffset, slot.tag, slot.full);
|
|
3246
|
-
}
|
|
3247
|
-
default:
|
|
3248
|
-
throw new UnexpectedTagException;
|
|
3249
|
-
}
|
|
3250
|
-
}
|
|
3251
|
-
async function remapBytes(sourceCore, targetCore, slot) {
|
|
3252
|
-
await sourceCore.seek(Number(slot.value));
|
|
3253
|
-
const sourceReader = sourceCore.reader();
|
|
3254
|
-
const length = await sourceReader.readLong();
|
|
3255
|
-
const formatTagSize = slot.full ? 2 : 0;
|
|
3256
|
-
const totalPayload = length + formatTagSize;
|
|
3257
|
-
const newOffset = await targetCore.length();
|
|
3258
|
-
await targetCore.seek(newOffset);
|
|
3259
|
-
const targetWriter = targetCore.writer();
|
|
3260
|
-
await targetWriter.writeLong(length);
|
|
3261
|
-
let remaining = totalPayload;
|
|
3262
|
-
while (remaining > 0) {
|
|
3263
|
-
const chunk = Math.min(remaining, 4096);
|
|
3264
|
-
const buf = new Uint8Array(chunk);
|
|
3265
|
-
await sourceReader.readFully(buf);
|
|
3266
|
-
await targetWriter.write(buf);
|
|
3267
|
-
remaining -= chunk;
|
|
3268
|
-
}
|
|
3269
|
-
return newOffset;
|
|
3270
|
-
}
|
|
3271
|
-
async function remapIndex(sourceCore, targetCore, hashSize, offsetMap, slot) {
|
|
3272
|
-
await sourceCore.seek(Number(slot.value));
|
|
3273
|
-
const sourceReader = sourceCore.reader();
|
|
3274
|
-
const blockBytes = new Uint8Array(INDEX_BLOCK_SIZE);
|
|
3275
|
-
await sourceReader.readFully(blockBytes);
|
|
3276
|
-
const remappedSlots = [];
|
|
3277
|
-
for (let i = 0;i < SLOT_COUNT; i++) {
|
|
3278
|
-
const slotBytes = blockBytes.slice(i * Slot.LENGTH, (i + 1) * Slot.LENGTH);
|
|
3279
|
-
const childSlot = Slot.fromBytes(slotBytes);
|
|
3280
|
-
remappedSlots.push(await remapSlot(sourceCore, targetCore, hashSize, offsetMap, childSlot));
|
|
3281
|
-
}
|
|
3282
|
-
const newOffset = await targetCore.length();
|
|
3283
|
-
await targetCore.seek(newOffset);
|
|
3284
|
-
const targetWriter = targetCore.writer();
|
|
3285
|
-
for (const s of remappedSlots) {
|
|
3286
|
-
await targetWriter.write(s.toBytes());
|
|
3287
|
-
}
|
|
3288
|
-
return newOffset;
|
|
3289
|
-
}
|
|
3290
|
-
async function remapArrayList(sourceCore, targetCore, hashSize, offsetMap, slot) {
|
|
3291
|
-
await sourceCore.seek(Number(slot.value));
|
|
3292
|
-
const sourceReader = sourceCore.reader();
|
|
3293
|
-
const headerBytes = new Uint8Array(ArrayListHeader.LENGTH);
|
|
3294
|
-
await sourceReader.readFully(headerBytes);
|
|
3295
|
-
const header = ArrayListHeader.fromBytes(headerBytes);
|
|
3296
|
-
const indexSlot = new Slot(header.ptr, 1 /* INDEX */);
|
|
3297
|
-
const remappedIndex = await remapSlot(sourceCore, targetCore, hashSize, offsetMap, indexSlot);
|
|
3298
|
-
const newOffset = await targetCore.length();
|
|
3299
|
-
await targetCore.seek(newOffset);
|
|
3300
|
-
const targetWriter = targetCore.writer();
|
|
3301
|
-
await targetWriter.write(new ArrayListHeader(Number(remappedIndex.value), header.size).toBytes());
|
|
3302
|
-
return newOffset;
|
|
3303
|
-
}
|
|
3304
|
-
async function remapLinkedArrayList(sourceCore, targetCore, hashSize, offsetMap, slot) {
|
|
3305
|
-
await sourceCore.seek(Number(slot.value));
|
|
3306
|
-
const sourceReader = sourceCore.reader();
|
|
3307
|
-
const headerBytes = new Uint8Array(LinkedArrayListHeader.LENGTH);
|
|
3308
|
-
await sourceReader.readFully(headerBytes);
|
|
3309
|
-
const header = LinkedArrayListHeader.fromBytes(headerBytes);
|
|
3310
|
-
const remappedPtr = await remapLinkedArrayListBlock(sourceCore, targetCore, hashSize, offsetMap, header.ptr);
|
|
3311
|
-
const newOffset = await targetCore.length();
|
|
3312
|
-
await targetCore.seek(newOffset);
|
|
3313
|
-
const targetWriter = targetCore.writer();
|
|
3314
|
-
await targetWriter.write(new LinkedArrayListHeader(header.shift, remappedPtr, header.size).toBytes());
|
|
3315
|
-
return newOffset;
|
|
3316
|
-
}
|
|
3317
|
-
async function remapLinkedArrayListBlock(sourceCore, targetCore, hashSize, offsetMap, blockOffset) {
|
|
3318
|
-
const mapped = offsetMap.get(blockOffset);
|
|
3319
|
-
if (mapped !== undefined)
|
|
3320
|
-
return mapped;
|
|
3321
|
-
await sourceCore.seek(blockOffset);
|
|
3322
|
-
const sourceReader = sourceCore.reader();
|
|
3323
|
-
const blockBytes = new Uint8Array(LINKED_ARRAY_LIST_INDEX_BLOCK_SIZE);
|
|
3324
|
-
await sourceReader.readFully(blockBytes);
|
|
3325
|
-
const slots = [];
|
|
3326
|
-
for (let i = 0;i < SLOT_COUNT; i++) {
|
|
3327
|
-
const slotBytes = blockBytes.slice(i * LinkedArrayListSlot2.LENGTH, (i + 1) * LinkedArrayListSlot2.LENGTH);
|
|
3328
|
-
slots.push(LinkedArrayListSlot2.fromBytes(slotBytes));
|
|
3329
|
-
}
|
|
3330
|
-
const remappedSlots = [];
|
|
3331
|
-
for (const s of slots) {
|
|
3332
|
-
if (s.slot.tag === 1 /* INDEX */) {
|
|
3333
|
-
const remappedPtr = await remapLinkedArrayListBlock(sourceCore, targetCore, hashSize, offsetMap, Number(s.slot.value));
|
|
3334
|
-
remappedSlots.push(new LinkedArrayListSlot2(s.size, new Slot(remappedPtr, 1 /* INDEX */, s.slot.full)));
|
|
3335
|
-
} else if (s.slot.empty()) {
|
|
3336
|
-
remappedSlots.push(s);
|
|
3337
|
-
} else {
|
|
3338
|
-
const remapped = await remapSlot(sourceCore, targetCore, hashSize, offsetMap, s.slot);
|
|
3339
|
-
remappedSlots.push(new LinkedArrayListSlot2(s.size, remapped));
|
|
3340
|
-
}
|
|
3341
|
-
}
|
|
3342
|
-
const newOffset = await targetCore.length();
|
|
3343
|
-
await targetCore.seek(newOffset);
|
|
3344
|
-
const targetWriter = targetCore.writer();
|
|
3345
|
-
for (const s of remappedSlots) {
|
|
3346
|
-
await targetWriter.write(s.toBytes());
|
|
3347
|
-
}
|
|
3348
|
-
offsetMap.set(blockOffset, newOffset);
|
|
3349
|
-
return newOffset;
|
|
3350
|
-
}
|
|
3351
|
-
async function remapHashMapOrSet(sourceCore, targetCore, hashSize, offsetMap, slot, counted) {
|
|
3352
|
-
await sourceCore.seek(Number(slot.value));
|
|
3353
|
-
const sourceReader = sourceCore.reader();
|
|
3354
|
-
let countValue = -1;
|
|
3355
|
-
if (counted) {
|
|
3356
|
-
countValue = await sourceReader.readLong();
|
|
3357
|
-
}
|
|
3358
|
-
const blockBytes = new Uint8Array(INDEX_BLOCK_SIZE);
|
|
3359
|
-
await sourceReader.readFully(blockBytes);
|
|
3360
|
-
const remappedSlots = [];
|
|
3361
|
-
for (let i = 0;i < SLOT_COUNT; i++) {
|
|
3362
|
-
const slotBytes = blockBytes.slice(i * Slot.LENGTH, (i + 1) * Slot.LENGTH);
|
|
3363
|
-
const childSlot = Slot.fromBytes(slotBytes);
|
|
3364
|
-
remappedSlots.push(await remapSlot(sourceCore, targetCore, hashSize, offsetMap, childSlot));
|
|
3365
|
-
}
|
|
3366
|
-
const newOffset = await targetCore.length();
|
|
3367
|
-
await targetCore.seek(newOffset);
|
|
3368
|
-
const targetWriter = targetCore.writer();
|
|
3369
|
-
if (counted) {
|
|
3370
|
-
await targetWriter.writeLong(countValue);
|
|
3371
|
-
}
|
|
3372
|
-
for (const s of remappedSlots) {
|
|
3373
|
-
await targetWriter.write(s.toBytes());
|
|
3374
|
-
}
|
|
3375
|
-
return newOffset;
|
|
3376
|
-
}
|
|
3377
|
-
async function remapKvPair(sourceCore, targetCore, hashSize, offsetMap, slot) {
|
|
3378
|
-
await sourceCore.seek(Number(slot.value));
|
|
3379
|
-
const sourceReader = sourceCore.reader();
|
|
3380
|
-
const kvPairBytes = new Uint8Array(KeyValuePair.length(hashSize));
|
|
3381
|
-
await sourceReader.readFully(kvPairBytes);
|
|
3382
|
-
const kvPair = KeyValuePair.fromBytes(kvPairBytes, hashSize);
|
|
3383
|
-
const remappedKey = await remapSlot(sourceCore, targetCore, hashSize, offsetMap, kvPair.keySlot);
|
|
3384
|
-
const remappedValue = await remapSlot(sourceCore, targetCore, hashSize, offsetMap, kvPair.valueSlot);
|
|
3385
|
-
const newOffset = await targetCore.length();
|
|
3386
|
-
await targetCore.seek(newOffset);
|
|
3387
|
-
const targetWriter = targetCore.writer();
|
|
3388
|
-
await targetWriter.write(new KeyValuePair(remappedValue, remappedKey, kvPair.hash).toBytes());
|
|
3389
|
-
return newOffset;
|
|
3390
|
-
}
|
|
3391
|
-
// src/read-array-list.ts
|
|
3392
|
-
class ReadArrayList {
|
|
3393
|
-
cursor;
|
|
3394
|
-
constructor(cursor) {
|
|
3395
|
-
if (cursor) {
|
|
3396
|
-
switch (cursor.slotPtr.slot.tag) {
|
|
3397
|
-
case 0 /* NONE */:
|
|
3398
|
-
case 2 /* ARRAY_LIST */:
|
|
3399
|
-
this.cursor = cursor;
|
|
3400
|
-
break;
|
|
3401
|
-
default:
|
|
3402
|
-
throw new UnexpectedTagException;
|
|
3403
|
-
}
|
|
3404
|
-
}
|
|
3405
|
-
}
|
|
3406
|
-
slot() {
|
|
3407
|
-
return this.cursor.slot();
|
|
3408
|
-
}
|
|
3409
|
-
async count() {
|
|
3410
|
-
return this.cursor.count();
|
|
3411
|
-
}
|
|
3412
|
-
async iterator() {
|
|
3413
|
-
return this.cursor.iterator();
|
|
3414
|
-
}
|
|
3415
|
-
async* [Symbol.asyncIterator]() {
|
|
3416
|
-
yield* this.cursor;
|
|
3417
|
-
}
|
|
3418
|
-
async getCursor(index) {
|
|
3419
|
-
return this.cursor.readPath([new ArrayListGet2(index)]);
|
|
3420
|
-
}
|
|
3421
|
-
async getSlot(index) {
|
|
3422
|
-
return this.cursor.readPathSlot([new ArrayListGet2(index)]);
|
|
3423
|
-
}
|
|
3424
|
-
}
|
|
3425
|
-
// src/write-array-list.ts
|
|
3426
|
-
class WriteArrayList extends ReadArrayList {
|
|
3427
|
-
constructor() {
|
|
3428
|
-
super();
|
|
3429
|
-
}
|
|
3430
|
-
static async create(cursor) {
|
|
3431
|
-
const list = new WriteArrayList;
|
|
3432
|
-
const newCursor = await cursor.writePath([new ArrayListInit]);
|
|
3433
|
-
list.cursor = newCursor;
|
|
3434
|
-
return list;
|
|
3435
|
-
}
|
|
3436
|
-
async iterator() {
|
|
3437
|
-
return this.cursor.iterator();
|
|
3438
|
-
}
|
|
3439
|
-
async* [Symbol.asyncIterator]() {
|
|
3440
|
-
yield* this.cursor;
|
|
3441
|
-
}
|
|
3442
|
-
async put(index, data) {
|
|
3443
|
-
await this.cursor.writePath([
|
|
3444
|
-
new ArrayListGet2(index),
|
|
3445
|
-
new WriteData(data)
|
|
3446
|
-
]);
|
|
3447
|
-
}
|
|
3448
|
-
async putCursor(index) {
|
|
3449
|
-
return this.cursor.writePath([new ArrayListGet2(index)]);
|
|
3450
|
-
}
|
|
3451
|
-
async append(data) {
|
|
3452
|
-
await this.cursor.writePath([
|
|
3453
|
-
new ArrayListAppend,
|
|
3454
|
-
new WriteData(data)
|
|
3455
|
-
]);
|
|
3456
|
-
}
|
|
3457
|
-
async appendCursor() {
|
|
3458
|
-
return this.cursor.writePath([new ArrayListAppend]);
|
|
3459
|
-
}
|
|
3460
|
-
async appendContext(data, fn) {
|
|
3461
|
-
await this.cursor.writePath([
|
|
3462
|
-
new ArrayListAppend,
|
|
3463
|
-
new WriteData(data),
|
|
3464
|
-
new Context(fn)
|
|
3465
|
-
]);
|
|
3466
|
-
}
|
|
3467
|
-
async slice(size) {
|
|
3468
|
-
await this.cursor.writePath([new ArrayListSlice(size)]);
|
|
3469
|
-
}
|
|
3470
|
-
}
|
|
3471
|
-
// src/read-hash-map.ts
|
|
3472
|
-
class ReadHashMap {
|
|
3473
|
-
cursor;
|
|
3474
|
-
constructor(cursor) {
|
|
3475
|
-
if (cursor) {
|
|
3476
|
-
switch (cursor.slotPtr.slot.tag) {
|
|
3477
|
-
case 0 /* NONE */:
|
|
3478
|
-
case 4 /* HASH_MAP */:
|
|
3479
|
-
case 11 /* HASH_SET */:
|
|
3480
|
-
this.cursor = cursor;
|
|
3481
|
-
break;
|
|
3482
|
-
default:
|
|
3483
|
-
throw new UnexpectedTagException;
|
|
3484
|
-
}
|
|
3485
|
-
}
|
|
3486
|
-
}
|
|
3487
|
-
slot() {
|
|
3488
|
-
return this.cursor.slot();
|
|
3489
|
-
}
|
|
3490
|
-
async iterator() {
|
|
3491
|
-
return this.cursor.iterator();
|
|
3492
|
-
}
|
|
3493
|
-
async* [Symbol.asyncIterator]() {
|
|
3494
|
-
yield* this.cursor;
|
|
3495
|
-
}
|
|
3496
|
-
async getCursor(key) {
|
|
3497
|
-
const hash = await this.resolveHash(key);
|
|
3498
|
-
return this.cursor.readPath([new HashMapGet(new HashMapGetValue(hash))]);
|
|
3499
|
-
}
|
|
3500
|
-
async getSlot(key) {
|
|
3501
|
-
const hash = await this.resolveHash(key);
|
|
3502
|
-
return this.cursor.readPathSlot([new HashMapGet(new HashMapGetValue(hash))]);
|
|
3503
|
-
}
|
|
3504
|
-
async getKeyCursor(key) {
|
|
3505
|
-
const hash = await this.resolveHash(key);
|
|
3506
|
-
return this.cursor.readPath([new HashMapGet(new HashMapGetKey(hash))]);
|
|
3507
|
-
}
|
|
3508
|
-
async getKeySlot(key) {
|
|
3509
|
-
const hash = await this.resolveHash(key);
|
|
3510
|
-
return this.cursor.readPathSlot([new HashMapGet(new HashMapGetKey(hash))]);
|
|
3511
|
-
}
|
|
3512
|
-
async getKeyValuePair(key) {
|
|
3513
|
-
const hash = await this.resolveHash(key);
|
|
3514
|
-
const cursor = await this.cursor.readPath([new HashMapGet(new HashMapGetKVPair(hash))]);
|
|
3515
|
-
if (cursor === null) {
|
|
3516
|
-
return null;
|
|
3517
|
-
} else {
|
|
3518
|
-
return cursor.readKeyValuePair();
|
|
3519
|
-
}
|
|
3520
|
-
}
|
|
3521
|
-
async resolveHash(key) {
|
|
3522
|
-
if (key instanceof Uint8Array) {
|
|
3523
|
-
return key;
|
|
3524
|
-
} else if (typeof key === "string") {
|
|
3525
|
-
return this.cursor.db.hasher.digest(new TextEncoder().encode(key));
|
|
3526
|
-
} else {
|
|
3527
|
-
return this.cursor.db.hasher.digest(key.value);
|
|
3528
|
-
}
|
|
3529
|
-
}
|
|
3530
|
-
}
|
|
3531
|
-
// src/write-hash-map.ts
|
|
3532
|
-
class WriteHashMap extends ReadHashMap {
|
|
3533
|
-
constructor() {
|
|
3534
|
-
super();
|
|
3535
|
-
}
|
|
3536
|
-
static async create(cursor) {
|
|
3537
|
-
const map = new WriteHashMap;
|
|
3538
|
-
const newCursor = await cursor.writePath([new HashMapInit(false, false)]);
|
|
3539
|
-
map.cursor = newCursor;
|
|
3540
|
-
return map;
|
|
3541
|
-
}
|
|
3542
|
-
async iterator() {
|
|
3543
|
-
return this.cursor.iterator();
|
|
3544
|
-
}
|
|
3545
|
-
async* [Symbol.asyncIterator]() {
|
|
3546
|
-
yield* this.cursor;
|
|
3547
|
-
}
|
|
3548
|
-
async put(key, data) {
|
|
3549
|
-
if (typeof key === "string") {
|
|
3550
|
-
const hash = await this.cursor.db.hasher.digest(new TextEncoder().encode(key));
|
|
3551
|
-
await this.putKeyInternal(hash, new Bytes(key));
|
|
3552
|
-
await this.putInternal(hash, data);
|
|
3553
|
-
} else if (key instanceof Bytes) {
|
|
3554
|
-
const hash = await this.cursor.db.hasher.digest(key.value);
|
|
3555
|
-
await this.putKeyInternal(hash, key);
|
|
3556
|
-
await this.putInternal(hash, data);
|
|
3557
|
-
} else {
|
|
3558
|
-
await this.putInternal(key, data);
|
|
3559
|
-
}
|
|
3560
|
-
}
|
|
3561
|
-
async putCursor(key) {
|
|
3562
|
-
if (typeof key === "string") {
|
|
3563
|
-
const hash = await this.cursor.db.hasher.digest(new TextEncoder().encode(key));
|
|
3564
|
-
await this.putKeyInternal(hash, new Bytes(key));
|
|
3565
|
-
return this.putCursorInternal(hash);
|
|
3566
|
-
} else if (key instanceof Bytes) {
|
|
3567
|
-
const hash = await this.cursor.db.hasher.digest(key.value);
|
|
3568
|
-
await this.putKeyInternal(hash, key);
|
|
3569
|
-
return this.putCursorInternal(hash);
|
|
3570
|
-
} else {
|
|
3571
|
-
return this.putCursorInternal(key);
|
|
3572
|
-
}
|
|
3573
|
-
}
|
|
3574
|
-
async putKey(key, data) {
|
|
3575
|
-
const hash = await this.resolveHash(key);
|
|
3576
|
-
await this.putKeyInternal(hash, data);
|
|
3577
|
-
}
|
|
3578
|
-
async putKeyCursor(key) {
|
|
3579
|
-
const hash = await this.resolveHash(key);
|
|
3580
|
-
return this.putKeyCursorInternal(hash);
|
|
3581
|
-
}
|
|
3582
|
-
async remove(key) {
|
|
3583
|
-
const hash = await this.resolveHash(key);
|
|
3584
|
-
try {
|
|
3585
|
-
await this.cursor.writePath([new HashMapRemove(hash)]);
|
|
3586
|
-
} catch (e) {
|
|
3587
|
-
if (e instanceof KeyNotFoundException) {
|
|
3588
|
-
return false;
|
|
3589
|
-
}
|
|
3590
|
-
throw e;
|
|
3591
|
-
}
|
|
3592
|
-
return true;
|
|
3593
|
-
}
|
|
3594
|
-
async putInternal(hash, data) {
|
|
3595
|
-
await this.cursor.writePath([
|
|
3596
|
-
new HashMapGet(new HashMapGetValue(hash)),
|
|
3597
|
-
new WriteData(data)
|
|
3598
|
-
]);
|
|
3599
|
-
}
|
|
3600
|
-
async putCursorInternal(hash) {
|
|
3601
|
-
return this.cursor.writePath([
|
|
3602
|
-
new HashMapGet(new HashMapGetValue(hash))
|
|
3603
|
-
]);
|
|
3604
|
-
}
|
|
3605
|
-
async putKeyInternal(hash, data) {
|
|
3606
|
-
const cursor = await this.cursor.writePath([
|
|
3607
|
-
new HashMapGet(new HashMapGetKey(hash))
|
|
3608
|
-
]);
|
|
3609
|
-
await cursor.writeIfEmpty(data);
|
|
3610
|
-
}
|
|
3611
|
-
async putKeyCursorInternal(hash) {
|
|
3612
|
-
return this.cursor.writePath([
|
|
3613
|
-
new HashMapGet(new HashMapGetKey(hash))
|
|
3614
|
-
]);
|
|
3615
|
-
}
|
|
3616
|
-
}
|
|
3617
|
-
// src/read-hash-set.ts
|
|
3618
|
-
class ReadHashSet {
|
|
3619
|
-
cursor;
|
|
3620
|
-
constructor(cursor) {
|
|
3621
|
-
if (cursor) {
|
|
3622
|
-
switch (cursor.slotPtr.slot.tag) {
|
|
3623
|
-
case 0 /* NONE */:
|
|
3624
|
-
case 4 /* HASH_MAP */:
|
|
3625
|
-
case 11 /* HASH_SET */:
|
|
3626
|
-
this.cursor = cursor;
|
|
3627
|
-
break;
|
|
3628
|
-
default:
|
|
3629
|
-
throw new UnexpectedTagException;
|
|
3630
|
-
}
|
|
3631
|
-
}
|
|
3632
|
-
}
|
|
3633
|
-
slot() {
|
|
3634
|
-
return this.cursor.slot();
|
|
3635
|
-
}
|
|
3636
|
-
async iterator() {
|
|
3637
|
-
return this.cursor.iterator();
|
|
3638
|
-
}
|
|
3639
|
-
async* [Symbol.asyncIterator]() {
|
|
3640
|
-
yield* this.cursor;
|
|
3641
|
-
}
|
|
3642
|
-
async getCursor(key) {
|
|
3643
|
-
const hash = await this.resolveHash(key);
|
|
3644
|
-
return this.cursor.readPath([new HashMapGet(new HashMapGetKey(hash))]);
|
|
3645
|
-
}
|
|
3646
|
-
async getSlot(key) {
|
|
3647
|
-
const hash = await this.resolveHash(key);
|
|
3648
|
-
return this.cursor.readPathSlot([new HashMapGet(new HashMapGetKey(hash))]);
|
|
3649
|
-
}
|
|
3650
|
-
async resolveHash(key) {
|
|
3651
|
-
if (key instanceof Uint8Array) {
|
|
3652
|
-
return key;
|
|
3653
|
-
} else if (typeof key === "string") {
|
|
3654
|
-
return this.cursor.db.hasher.digest(new TextEncoder().encode(key));
|
|
3655
|
-
} else {
|
|
3656
|
-
return this.cursor.db.hasher.digest(key.value);
|
|
3657
|
-
}
|
|
3658
|
-
}
|
|
3659
|
-
}
|
|
3660
|
-
// src/write-hash-set.ts
|
|
3661
|
-
class WriteHashSet extends ReadHashSet {
|
|
3662
|
-
constructor() {
|
|
3663
|
-
super();
|
|
3664
|
-
}
|
|
3665
|
-
static async create(cursor) {
|
|
3666
|
-
const set = new WriteHashSet;
|
|
3667
|
-
const newCursor = await cursor.writePath([new HashMapInit(false, true)]);
|
|
3668
|
-
set.cursor = newCursor;
|
|
3669
|
-
return set;
|
|
3670
|
-
}
|
|
3671
|
-
async iterator() {
|
|
3672
|
-
return this.cursor.iterator();
|
|
3673
|
-
}
|
|
3674
|
-
async* [Symbol.asyncIterator]() {
|
|
3675
|
-
yield* this.cursor;
|
|
3676
|
-
}
|
|
3677
|
-
async put(key, data) {
|
|
3678
|
-
if (typeof key === "string") {
|
|
3679
|
-
const bytes = new TextEncoder().encode(key);
|
|
3680
|
-
const hash = await this.cursor.db.hasher.digest(bytes);
|
|
3681
|
-
await this.putInternal(hash, new Bytes(bytes));
|
|
3682
|
-
} else if (key instanceof Bytes) {
|
|
3683
|
-
const hash = await this.cursor.db.hasher.digest(key.value);
|
|
3684
|
-
await this.putInternal(hash, key);
|
|
3685
|
-
} else {
|
|
3686
|
-
await this.putInternal(key, data);
|
|
3687
|
-
}
|
|
3688
|
-
}
|
|
3689
|
-
async putCursor(key) {
|
|
3690
|
-
const hash = await this.resolveHash(key);
|
|
3691
|
-
return this.putCursorInternal(hash);
|
|
3692
|
-
}
|
|
3693
|
-
async remove(key) {
|
|
3694
|
-
const hash = await this.resolveHash(key);
|
|
3695
|
-
try {
|
|
3696
|
-
await this.cursor.writePath([new HashMapRemove(hash)]);
|
|
3697
|
-
} catch (e) {
|
|
3698
|
-
if (e instanceof KeyNotFoundException) {
|
|
3699
|
-
return false;
|
|
3700
|
-
}
|
|
3701
|
-
throw e;
|
|
3702
|
-
}
|
|
3703
|
-
return true;
|
|
3704
|
-
}
|
|
3705
|
-
async putInternal(hash, data) {
|
|
3706
|
-
const cursor = await this.cursor.writePath([
|
|
3707
|
-
new HashMapGet(new HashMapGetKey(hash))
|
|
3708
|
-
]);
|
|
3709
|
-
await cursor.writeIfEmpty(data);
|
|
3710
|
-
}
|
|
3711
|
-
async putCursorInternal(hash) {
|
|
3712
|
-
return this.cursor.writePath([
|
|
3713
|
-
new HashMapGet(new HashMapGetKey(hash))
|
|
3714
|
-
]);
|
|
3715
|
-
}
|
|
3716
|
-
}
|
|
3717
|
-
// src/read-linked-array-list.ts
|
|
3718
|
-
class ReadLinkedArrayList {
|
|
3719
|
-
cursor;
|
|
3720
|
-
constructor(cursor) {
|
|
3721
|
-
if (cursor) {
|
|
3722
|
-
switch (cursor.slotPtr.slot.tag) {
|
|
3723
|
-
case 0 /* NONE */:
|
|
3724
|
-
case 3 /* LINKED_ARRAY_LIST */:
|
|
3725
|
-
this.cursor = cursor;
|
|
3726
|
-
break;
|
|
3727
|
-
default:
|
|
3728
|
-
throw new UnexpectedTagException;
|
|
3729
|
-
}
|
|
3730
|
-
}
|
|
3731
|
-
}
|
|
3732
|
-
slot() {
|
|
3733
|
-
return this.cursor.slot();
|
|
3734
|
-
}
|
|
3735
|
-
async count() {
|
|
3736
|
-
return this.cursor.count();
|
|
3737
|
-
}
|
|
3738
|
-
async iterator() {
|
|
3739
|
-
return this.cursor.iterator();
|
|
3740
|
-
}
|
|
3741
|
-
async* [Symbol.asyncIterator]() {
|
|
3742
|
-
yield* this.cursor;
|
|
3743
|
-
}
|
|
3744
|
-
async getCursor(index) {
|
|
3745
|
-
return this.cursor.readPath([new LinkedArrayListGet(index)]);
|
|
3746
|
-
}
|
|
3747
|
-
async getSlot(index) {
|
|
3748
|
-
return this.cursor.readPathSlot([new LinkedArrayListGet(index)]);
|
|
3749
|
-
}
|
|
3750
|
-
}
|
|
3751
|
-
// src/write-linked-array-list.ts
|
|
3752
|
-
class WriteLinkedArrayList extends ReadLinkedArrayList {
|
|
3753
|
-
constructor() {
|
|
3754
|
-
super();
|
|
3755
|
-
}
|
|
3756
|
-
static async create(cursor) {
|
|
3757
|
-
const list = new WriteLinkedArrayList;
|
|
3758
|
-
const newCursor = await cursor.writePath([new LinkedArrayListInit]);
|
|
3759
|
-
list.cursor = newCursor;
|
|
3760
|
-
return list;
|
|
3761
|
-
}
|
|
3762
|
-
async iterator() {
|
|
3763
|
-
return this.cursor.iterator();
|
|
3764
|
-
}
|
|
3765
|
-
async* [Symbol.asyncIterator]() {
|
|
3766
|
-
yield* this.cursor;
|
|
3767
|
-
}
|
|
3768
|
-
async put(index, data) {
|
|
3769
|
-
await this.cursor.writePath([
|
|
3770
|
-
new LinkedArrayListGet(index),
|
|
3771
|
-
new WriteData(data)
|
|
3772
|
-
]);
|
|
3773
|
-
}
|
|
3774
|
-
async putCursor(index) {
|
|
3775
|
-
return this.cursor.writePath([new LinkedArrayListGet(index)]);
|
|
3776
|
-
}
|
|
3777
|
-
async append(data) {
|
|
3778
|
-
await this.cursor.writePath([
|
|
3779
|
-
new LinkedArrayListAppend,
|
|
3780
|
-
new WriteData(data)
|
|
3781
|
-
]);
|
|
3782
|
-
}
|
|
3783
|
-
async appendCursor() {
|
|
3784
|
-
return this.cursor.writePath([new LinkedArrayListAppend]);
|
|
3785
|
-
}
|
|
3786
|
-
async slice(offset, size) {
|
|
3787
|
-
await this.cursor.writePath([
|
|
3788
|
-
new LinkedArrayListSlice(offset, size)
|
|
3789
|
-
]);
|
|
3790
|
-
}
|
|
3791
|
-
async concat(list) {
|
|
3792
|
-
await this.cursor.writePath([new LinkedArrayListConcat(list)]);
|
|
3793
|
-
}
|
|
3794
|
-
async insert(index, data) {
|
|
3795
|
-
await this.cursor.writePath([
|
|
3796
|
-
new LinkedArrayListInsert(index),
|
|
3797
|
-
new WriteData(data)
|
|
3798
|
-
]);
|
|
3799
|
-
}
|
|
3800
|
-
async insertCursor(index) {
|
|
3801
|
-
return this.cursor.writePath([new LinkedArrayListInsert(index)]);
|
|
3802
|
-
}
|
|
3803
|
-
async remove(index) {
|
|
3804
|
-
await this.cursor.writePath([new LinkedArrayListRemove(index)]);
|
|
3805
|
-
}
|
|
3806
|
-
}
|
|
3807
|
-
// src/read-counted-hash-map.ts
|
|
3808
|
-
class ReadCountedHashMap extends ReadHashMap {
|
|
3809
|
-
constructor(cursor) {
|
|
3810
|
-
super();
|
|
3811
|
-
switch (cursor.slotPtr.slot.tag) {
|
|
3812
|
-
case 0 /* NONE */:
|
|
3813
|
-
case 12 /* COUNTED_HASH_MAP */:
|
|
3814
|
-
case 13 /* COUNTED_HASH_SET */:
|
|
3815
|
-
this.cursor = cursor;
|
|
3816
|
-
break;
|
|
3817
|
-
default:
|
|
3818
|
-
throw new UnexpectedTagException;
|
|
3819
|
-
}
|
|
3820
|
-
}
|
|
3821
|
-
async count() {
|
|
3822
|
-
return this.cursor.count();
|
|
3823
|
-
}
|
|
3824
|
-
}
|
|
3825
|
-
// src/write-counted-hash-map.ts
|
|
3826
|
-
class WriteCountedHashMap extends WriteHashMap {
|
|
3827
|
-
constructor() {
|
|
3828
|
-
super();
|
|
3829
|
-
}
|
|
3830
|
-
static async create(cursor) {
|
|
3831
|
-
const map = new WriteCountedHashMap;
|
|
3832
|
-
switch (cursor.slotPtr.slot.tag) {
|
|
3833
|
-
case 0 /* NONE */:
|
|
3834
|
-
case 12 /* COUNTED_HASH_MAP */:
|
|
3835
|
-
case 13 /* COUNTED_HASH_SET */: {
|
|
3836
|
-
const newCursor = await cursor.writePath([new HashMapInit(true, false)]);
|
|
3837
|
-
map.cursor = newCursor;
|
|
3838
|
-
break;
|
|
3839
|
-
}
|
|
3840
|
-
default:
|
|
3841
|
-
throw new UnexpectedTagException;
|
|
3842
|
-
}
|
|
3843
|
-
return map;
|
|
3844
|
-
}
|
|
3845
|
-
async count() {
|
|
3846
|
-
return this.cursor.count();
|
|
3847
|
-
}
|
|
3848
|
-
}
|
|
3849
|
-
// src/read-counted-hash-set.ts
|
|
3850
|
-
class ReadCountedHashSet extends ReadHashSet {
|
|
3851
|
-
constructor(cursor) {
|
|
3852
|
-
super();
|
|
3853
|
-
switch (cursor.slotPtr.slot.tag) {
|
|
3854
|
-
case 0 /* NONE */:
|
|
3855
|
-
case 12 /* COUNTED_HASH_MAP */:
|
|
3856
|
-
case 13 /* COUNTED_HASH_SET */:
|
|
3857
|
-
this.cursor = cursor;
|
|
3858
|
-
break;
|
|
3859
|
-
default:
|
|
3860
|
-
throw new UnexpectedTagException;
|
|
3861
|
-
}
|
|
3862
|
-
}
|
|
3863
|
-
async count() {
|
|
3864
|
-
return this.cursor.count();
|
|
3865
|
-
}
|
|
3866
|
-
}
|
|
3867
|
-
// src/write-counted-hash-set.ts
|
|
3868
|
-
class WriteCountedHashSet extends WriteHashSet {
|
|
3869
|
-
constructor() {
|
|
3870
|
-
super();
|
|
3871
|
-
}
|
|
3872
|
-
static async create(cursor) {
|
|
3873
|
-
const set = new WriteCountedHashSet;
|
|
3874
|
-
switch (cursor.slotPtr.slot.tag) {
|
|
3875
|
-
case 0 /* NONE */:
|
|
3876
|
-
case 12 /* COUNTED_HASH_MAP */:
|
|
3877
|
-
case 13 /* COUNTED_HASH_SET */: {
|
|
3878
|
-
const newCursor = await cursor.writePath([new HashMapInit(true, true)]);
|
|
3879
|
-
set.cursor = newCursor;
|
|
3880
|
-
break;
|
|
3881
|
-
}
|
|
3882
|
-
default:
|
|
3883
|
-
throw new UnexpectedTagException;
|
|
3884
|
-
}
|
|
3885
|
-
return set;
|
|
3886
|
-
}
|
|
3887
|
-
async count() {
|
|
3888
|
-
return this.cursor.count();
|
|
3889
|
-
}
|
|
3890
|
-
}
|
|
3891
|
-
export {
|
|
3892
|
-
tagValueOf,
|
|
3893
|
-
Writer,
|
|
3894
|
-
WriteNotAllowedException,
|
|
3895
|
-
WriteMode,
|
|
3896
|
-
WriteLinkedArrayList,
|
|
3897
|
-
WriteKeyValuePairCursor,
|
|
3898
|
-
WriteHashSet,
|
|
3899
|
-
WriteHashMap,
|
|
3900
|
-
WriteData,
|
|
3901
|
-
WriteCursorIterator,
|
|
3902
|
-
WriteCursor,
|
|
3903
|
-
WriteCountedHashSet,
|
|
3904
|
-
WriteCountedHashMap,
|
|
3905
|
-
WriteArrayList,
|
|
3906
|
-
VERSION,
|
|
3907
|
-
UnreachableException,
|
|
3908
|
-
UnexpectedWriterPositionException,
|
|
3909
|
-
UnexpectedTagException,
|
|
3910
|
-
Uint,
|
|
3911
|
-
TopLevelArrayListHeader,
|
|
3912
|
-
Tag,
|
|
3913
|
-
StreamTooLongException,
|
|
3914
|
-
SlotPointer,
|
|
3915
|
-
Slot,
|
|
3916
|
-
SLOT_COUNT,
|
|
3917
|
-
Reader,
|
|
3918
|
-
ReadLinkedArrayList,
|
|
3919
|
-
ReadHashSet,
|
|
3920
|
-
ReadHashMap,
|
|
3921
|
-
ReadCursor,
|
|
3922
|
-
ReadCountedHashSet,
|
|
3923
|
-
ReadCountedHashMap,
|
|
3924
|
-
ReadArrayList,
|
|
3925
|
-
PathPartMustBeAtEndException,
|
|
3926
|
-
NotImplementedException,
|
|
3927
|
-
NoAvailableSlotsException,
|
|
3928
|
-
MustSetNewSlotsToFullException,
|
|
3929
|
-
MaxShiftExceededException,
|
|
3930
|
-
MAX_BRANCH_LENGTH,
|
|
3931
|
-
MASK,
|
|
3932
|
-
MAGIC_NUMBER,
|
|
3933
|
-
LinkedArrayListSlotPointer,
|
|
3934
|
-
LinkedArrayListSlot2 as LinkedArrayListSlot,
|
|
3935
|
-
LinkedArrayListSlice,
|
|
3936
|
-
LinkedArrayListRemove,
|
|
3937
|
-
LinkedArrayListInsert,
|
|
3938
|
-
LinkedArrayListInit,
|
|
3939
|
-
LinkedArrayListHeader,
|
|
3940
|
-
LinkedArrayListGet,
|
|
3941
|
-
LinkedArrayListConcat,
|
|
3942
|
-
LinkedArrayListBlockInfo,
|
|
3943
|
-
LinkedArrayListAppend,
|
|
3944
|
-
LINKED_ARRAY_LIST_INDEX_BLOCK_SIZE,
|
|
3945
|
-
KeyValuePairCursor,
|
|
3946
|
-
KeyValuePair,
|
|
3947
|
-
KeyOffsetExceededException,
|
|
3948
|
-
KeyNotFoundException,
|
|
3949
|
-
InvalidVersionException,
|
|
3950
|
-
InvalidTopLevelTypeException,
|
|
3951
|
-
InvalidOffsetException,
|
|
3952
|
-
InvalidHashSizeException,
|
|
3953
|
-
InvalidFormatTagSizeException,
|
|
3954
|
-
InvalidDatabaseException,
|
|
3955
|
-
Int,
|
|
3956
|
-
INDEX_BLOCK_SIZE,
|
|
3957
|
-
Header,
|
|
3958
|
-
Hasher,
|
|
3959
|
-
HashMapRemove,
|
|
3960
|
-
HashMapInit,
|
|
3961
|
-
HashMapGetValue,
|
|
3962
|
-
HashMapGetKey,
|
|
3963
|
-
HashMapGetKVPair,
|
|
3964
|
-
HashMapGet,
|
|
3965
|
-
Float,
|
|
3966
|
-
ExpectedUnsignedLongException,
|
|
3967
|
-
ExpectedTxStartException,
|
|
3968
|
-
ExpectedRootNodeException,
|
|
3969
|
-
EndOfStreamException,
|
|
3970
|
-
EmptySlotException,
|
|
3971
|
-
DatabaseException,
|
|
3972
|
-
Database3 as Database,
|
|
3973
|
-
CursorNotWriteableException,
|
|
3974
|
-
CursorIterator,
|
|
3975
|
-
CoreMemory,
|
|
3976
|
-
CoreFile,
|
|
3977
|
-
CoreBufferedFile,
|
|
3978
|
-
Context,
|
|
3979
|
-
Bytes,
|
|
3980
|
-
BIT_COUNT,
|
|
3981
|
-
ArrayListSlice,
|
|
3982
|
-
ArrayListInit,
|
|
3983
|
-
ArrayListHeader,
|
|
3984
|
-
ArrayListGet2 as ArrayListGet,
|
|
3985
|
-
ArrayListAppend
|
|
3986
|
-
};
|
|
1
|
+
// Tag
|
|
2
|
+
export { Tag, tagValueOf } from './tag.js';
|
|
3
|
+
// Slot
|
|
4
|
+
export { Slot } from './slot.js';
|
|
5
|
+
export { SlotPointer } from './slot-pointer.js';
|
|
6
|
+
// Writeable Data
|
|
7
|
+
export { Uint, Int, Float, Bytes } from './writeable-data.js';
|
|
8
|
+
// Exceptions
|
|
9
|
+
export { DatabaseException, NotImplementedException, UnreachableException, InvalidDatabaseException, InvalidVersionException, InvalidHashSizeException, KeyNotFoundException, WriteNotAllowedException, UnexpectedTagException, CursorNotWriteableException, ExpectedTxStartException, KeyOffsetExceededException, PathPartMustBeAtEndException, StreamTooLongException, EndOfStreamException, InvalidOffsetException, InvalidTopLevelTypeException, ExpectedUnsignedLongException, NoAvailableSlotsException, MustSetNewSlotsToFullException, EmptySlotException, ExpectedRootNodeException, InvalidFormatTagSizeException, UnexpectedWriterPositionException, MaxShiftExceededException, } from './exceptions.js';
|
|
10
|
+
export { CoreMemory } from './core-memory.js';
|
|
11
|
+
export { CoreFile } from './core-file.js';
|
|
12
|
+
export { CoreBufferedFile } from './core-buffered-file.js';
|
|
13
|
+
export { Hasher } from './hasher.js';
|
|
14
|
+
// Database
|
|
15
|
+
export { Database, WriteMode, Header, ArrayListHeader, TopLevelArrayListHeader, BTreeHeader, KeyValuePair, BTreeNode, BTreeNodeKind, BTreeNodeRef, BTreeInsertResult, BTreeWriteSlot, BTreeJoinResult, BTreeSplitResult, SortedNode, SortedSplit, SortedInsertResult, SortedRemoveResult, SortedSlot, SortedEntry, VERSION, MAGIC_NUMBER, BIT_COUNT, SLOT_COUNT, MASK, INDEX_BLOCK_SIZE, MAX_BRANCH_LENGTH, BTREE_SLOT_COUNT, BTREE_SPLIT_COUNT, BTREE_NODE_HEADER_SIZE, BTREE_LEAF_BLOCK_SIZE, BTREE_BRANCH_BLOCK_SIZE, SORTED_LEAF_BLOCK_SIZE, SORTED_BRANCH_BLOCK_SIZE, ArrayListInit, ArrayListGet, ArrayListAppend, ArrayListSlice, LinkedArrayListInit, LinkedArrayListGet, LinkedArrayListAppend, LinkedArrayListSlice, LinkedArrayListConcat, LinkedArrayListInsert, LinkedArrayListRemove, HashMapInit, HashMapGet, HashMapRemove, SortedMapInit, SortedMapGet, SortedMapGetIndex, SortedMapRemove, WriteData, Context, HashMapGetKVPair, HashMapGetKey, HashMapGetValue, SortedMapGetKVPair, SortedMapGetKey, SortedMapGetValue, } from './database.js';
|
|
16
|
+
// Cursors
|
|
17
|
+
export { ReadCursor, Reader, CursorIterator, KeyValuePairCursor } from './read-cursor.js';
|
|
18
|
+
export { WriteCursor, Writer, WriteCursorIterator, WriteKeyValuePairCursor } from './write-cursor.js';
|
|
19
|
+
// Collections
|
|
20
|
+
export { ReadArrayList } from './read-array-list.js';
|
|
21
|
+
export { WriteArrayList } from './write-array-list.js';
|
|
22
|
+
export { ReadHashMap } from './read-hash-map.js';
|
|
23
|
+
export { WriteHashMap } from './write-hash-map.js';
|
|
24
|
+
export { ReadHashSet } from './read-hash-set.js';
|
|
25
|
+
export { WriteHashSet } from './write-hash-set.js';
|
|
26
|
+
export { ReadLinkedArrayList } from './read-linked-array-list.js';
|
|
27
|
+
export { WriteLinkedArrayList } from './write-linked-array-list.js';
|
|
28
|
+
export { ReadCountedHashMap } from './read-counted-hash-map.js';
|
|
29
|
+
export { WriteCountedHashMap } from './write-counted-hash-map.js';
|
|
30
|
+
export { ReadCountedHashSet } from './read-counted-hash-set.js';
|
|
31
|
+
export { WriteCountedHashSet } from './write-counted-hash-set.js';
|
|
32
|
+
export { ReadSortedMap } from './read-sorted-map.js';
|
|
33
|
+
export { WriteSortedMap } from './write-sorted-map.js';
|
|
34
|
+
export { ReadSortedSet } from './read-sorted-set.js';
|
|
35
|
+
export { WriteSortedSet } from './write-sorted-set.js';
|