xitdb 0.1.0 → 0.2.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/dist/core-buffered-file.d.ts +41 -0
- package/dist/core-file.d.ts +18 -0
- package/dist/core-memory.d.ts +36 -0
- package/dist/core.d.ts +23 -0
- package/dist/database.d.ts +244 -0
- package/dist/exceptions.d.ts +51 -0
- package/dist/hasher.d.ts +9 -0
- package/dist/index.d.ts +26 -0
- package/dist/index.js +429 -266
- package/dist/read-array-list.d.ts +13 -0
- package/dist/read-counted-hash-map.d.ts +7 -0
- package/dist/read-counted-hash-set.d.ts +7 -0
- package/dist/read-cursor.d.ts +57 -0
- package/dist/read-hash-map.d.ts +27 -0
- package/dist/read-hash-set.d.ts +18 -0
- package/dist/read-linked-array-list.d.ts +13 -0
- package/dist/slot-pointer.d.ts +7 -0
- package/dist/slot.d.ts +15 -0
- package/{src/slotted.ts → dist/slotted.d.ts} +1 -2
- package/dist/tag.d.ts +17 -0
- package/dist/write-array-list.d.ts +16 -0
- package/dist/write-counted-hash-map.d.ts +7 -0
- package/dist/write-counted-hash-set.d.ts +7 -0
- package/dist/write-cursor.d.ts +36 -0
- package/dist/write-hash-map.d.ts +25 -0
- package/dist/write-hash-set.d.ts +19 -0
- package/dist/write-linked-array-list.d.ts +19 -0
- package/dist/writeable-data.d.ts +20 -0
- package/package.json +12 -1
- package/.claude/settings.local.json +0 -9
- package/bun.lock +0 -24
- package/bunfig.toml +0 -1
- package/example/README.md +0 -46
- package/example/dump.ts +0 -201
- package/src/core-buffered-file.ts +0 -226
- package/src/core-file.ts +0 -137
- package/src/core-memory.ts +0 -179
- package/src/core.ts +0 -25
- package/src/database.ts +0 -2232
- package/src/exceptions.ts +0 -31
- package/src/hasher.ts +0 -52
- package/src/index.ts +0 -110
- package/src/read-array-list.ts +0 -45
- package/src/read-counted-hash-map.ts +0 -28
- package/src/read-counted-hash-set.ts +0 -28
- package/src/read-cursor.ts +0 -546
- package/src/read-hash-map.ts +0 -117
- package/src/read-hash-set.ts +0 -70
- package/src/read-linked-array-list.ts +0 -45
- package/src/slot-pointer.ts +0 -15
- package/src/slot.ts +0 -51
- package/src/tag.ts +0 -23
- package/src/write-array-list.ts +0 -65
- package/src/write-counted-hash-map.ts +0 -31
- package/src/write-counted-hash-set.ts +0 -31
- package/src/write-cursor.ts +0 -166
- package/src/write-hash-map.ts +0 -129
- package/src/write-hash-set.ts +0 -86
- package/src/write-linked-array-list.ts +0 -80
- package/src/writeable-data.ts +0 -67
- package/tests/database.test.ts +0 -2519
- package/tests/fixtures/test.db +0 -0
- package/tsconfig.json +0 -17
package/src/read-hash-set.ts
DELETED
|
@@ -1,70 +0,0 @@
|
|
|
1
|
-
import { Tag } from './tag';
|
|
2
|
-
import { Slot } from './slot';
|
|
3
|
-
import type { Slotted } from './slotted';
|
|
4
|
-
import { ReadCursor, CursorIterator } from './read-cursor';
|
|
5
|
-
import { HashMapGet, HashMapGetKey } from './database';
|
|
6
|
-
import { UnexpectedTagException } from './exceptions';
|
|
7
|
-
import { Bytes } from './writeable-data';
|
|
8
|
-
|
|
9
|
-
export class ReadHashSet implements Slotted {
|
|
10
|
-
public cursor!: ReadCursor;
|
|
11
|
-
|
|
12
|
-
protected constructor() {}
|
|
13
|
-
|
|
14
|
-
static async create(cursor: ReadCursor): Promise<ReadHashSet> {
|
|
15
|
-
const set = new ReadHashSet();
|
|
16
|
-
switch (cursor.slotPtr.slot.tag) {
|
|
17
|
-
case Tag.NONE:
|
|
18
|
-
case Tag.HASH_MAP:
|
|
19
|
-
case Tag.HASH_SET:
|
|
20
|
-
set.cursor = cursor;
|
|
21
|
-
break;
|
|
22
|
-
default:
|
|
23
|
-
throw new UnexpectedTagException();
|
|
24
|
-
}
|
|
25
|
-
return set;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
slot(): Slot {
|
|
29
|
-
return this.cursor.slot();
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
iterator(): CursorIterator {
|
|
33
|
-
return this.cursor.iterator();
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
async *[Symbol.asyncIterator](): AsyncIterator<ReadCursor> {
|
|
37
|
-
yield* this.cursor;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
// Methods that take a string key and hash it
|
|
41
|
-
async getCursorByString(key: string): Promise<ReadCursor | null> {
|
|
42
|
-
const hash = await this.cursor.db.hasher.digest(new TextEncoder().encode(key));
|
|
43
|
-
return this.getCursor(hash);
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
async getSlotByString(key: string): Promise<Slot | null> {
|
|
47
|
-
const hash = await this.cursor.db.hasher.digest(new TextEncoder().encode(key));
|
|
48
|
-
return this.getSlot(hash);
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
// Methods that take Bytes key and hash it
|
|
52
|
-
async getCursorByBytes(key: Bytes): Promise<ReadCursor | null> {
|
|
53
|
-
const hash = await this.cursor.db.hasher.digest(key.value);
|
|
54
|
-
return this.getCursor(hash);
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
async getSlotByBytes(key: Bytes): Promise<Slot | null> {
|
|
58
|
-
const hash = await this.cursor.db.hasher.digest(key.value);
|
|
59
|
-
return this.getSlot(hash);
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
// Methods that take hash directly
|
|
63
|
-
async getCursor(hash: Uint8Array): Promise<ReadCursor | null> {
|
|
64
|
-
return this.cursor.readPath([new HashMapGet(new HashMapGetKey(hash))]);
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
async getSlot(hash: Uint8Array): Promise<Slot | null> {
|
|
68
|
-
return this.cursor.readPathSlot([new HashMapGet(new HashMapGetKey(hash))]);
|
|
69
|
-
}
|
|
70
|
-
}
|
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
import { Tag } from './tag';
|
|
2
|
-
import { Slot } from './slot';
|
|
3
|
-
import type { Slotted } from './slotted';
|
|
4
|
-
import { ReadCursor, CursorIterator } from './read-cursor';
|
|
5
|
-
import { LinkedArrayListGet } from './database';
|
|
6
|
-
import { UnexpectedTagException } from './exceptions';
|
|
7
|
-
|
|
8
|
-
export class ReadLinkedArrayList implements Slotted {
|
|
9
|
-
public cursor: ReadCursor;
|
|
10
|
-
|
|
11
|
-
constructor(cursor: ReadCursor) {
|
|
12
|
-
switch (cursor.slotPtr.slot.tag) {
|
|
13
|
-
case Tag.NONE:
|
|
14
|
-
case Tag.LINKED_ARRAY_LIST:
|
|
15
|
-
this.cursor = cursor;
|
|
16
|
-
break;
|
|
17
|
-
default:
|
|
18
|
-
throw new UnexpectedTagException();
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
slot(): Slot {
|
|
23
|
-
return this.cursor.slot();
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
async count(): Promise<number> {
|
|
27
|
-
return this.cursor.count();
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
iterator(): CursorIterator {
|
|
31
|
-
return this.cursor.iterator();
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
async *[Symbol.asyncIterator](): AsyncIterator<ReadCursor> {
|
|
35
|
-
yield* this.cursor;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
async getCursor(index: number): Promise<ReadCursor | null> {
|
|
39
|
-
return this.cursor.readPath([new LinkedArrayListGet(index)]);
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
async getSlot(index: number): Promise<Slot | null> {
|
|
43
|
-
return this.cursor.readPathSlot([new LinkedArrayListGet(index)]);
|
|
44
|
-
}
|
|
45
|
-
}
|
package/src/slot-pointer.ts
DELETED
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import { Slot } from './slot';
|
|
2
|
-
|
|
3
|
-
export class SlotPointer {
|
|
4
|
-
readonly position: number | null;
|
|
5
|
-
readonly slot: Slot;
|
|
6
|
-
|
|
7
|
-
constructor(position: number | null, slot: Slot) {
|
|
8
|
-
this.position = position;
|
|
9
|
-
this.slot = slot;
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
withSlot(slot: Slot): SlotPointer {
|
|
13
|
-
return new SlotPointer(this.position, slot);
|
|
14
|
-
}
|
|
15
|
-
}
|
package/src/slot.ts
DELETED
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
import { Tag, tagValueOf } from './tag';
|
|
2
|
-
import type { WriteableData } from './writeable-data';
|
|
3
|
-
|
|
4
|
-
export class Slot implements WriteableData {
|
|
5
|
-
static readonly LENGTH = 9;
|
|
6
|
-
|
|
7
|
-
readonly value: bigint;
|
|
8
|
-
readonly tag: Tag;
|
|
9
|
-
readonly full: boolean;
|
|
10
|
-
|
|
11
|
-
constructor(value: number | bigint = 0n, tag: Tag = Tag.NONE, full: boolean = false) {
|
|
12
|
-
this.value = typeof value === 'bigint' ? value : BigInt(value);
|
|
13
|
-
this.tag = tag;
|
|
14
|
-
this.full = full;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
withTag(tag: Tag): Slot {
|
|
18
|
-
return new Slot(this.value, tag, this.full);
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
withFull(full: boolean): Slot {
|
|
22
|
-
return new Slot(this.value, this.tag, full);
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
empty(): boolean {
|
|
26
|
-
return this.tag === Tag.NONE && !this.full;
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
toBytes(): Uint8Array {
|
|
30
|
-
const buffer = new ArrayBuffer(Slot.LENGTH);
|
|
31
|
-
const view = new DataView(buffer);
|
|
32
|
-
let tagInt = this.full ? 0b1000_0000 : 0;
|
|
33
|
-
tagInt = tagInt | this.tag;
|
|
34
|
-
view.setUint8(0, tagInt);
|
|
35
|
-
view.setBigInt64(1, this.value, false);
|
|
36
|
-
return new Uint8Array(buffer);
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
static fromBytes(bytes: Uint8Array): Slot {
|
|
40
|
-
const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
|
|
41
|
-
const tagByte = view.getUint8(0);
|
|
42
|
-
const full = (tagByte & 0b1000_0000) !== 0;
|
|
43
|
-
const tag = tagValueOf(tagByte & 0b0111_1111);
|
|
44
|
-
const value = view.getBigInt64(1, false);
|
|
45
|
-
return new Slot(value, tag, full);
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
equals(other: Slot): boolean {
|
|
49
|
-
return this.value === other.value && this.tag === other.tag && this.full === other.full;
|
|
50
|
-
}
|
|
51
|
-
}
|
package/src/tag.ts
DELETED
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
export const enum Tag {
|
|
2
|
-
NONE = 0,
|
|
3
|
-
INDEX = 1,
|
|
4
|
-
ARRAY_LIST = 2,
|
|
5
|
-
LINKED_ARRAY_LIST = 3,
|
|
6
|
-
HASH_MAP = 4,
|
|
7
|
-
KV_PAIR = 5,
|
|
8
|
-
BYTES = 6,
|
|
9
|
-
SHORT_BYTES = 7,
|
|
10
|
-
UINT = 8,
|
|
11
|
-
INT = 9,
|
|
12
|
-
FLOAT = 10,
|
|
13
|
-
HASH_SET = 11,
|
|
14
|
-
COUNTED_HASH_MAP = 12,
|
|
15
|
-
COUNTED_HASH_SET = 13,
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
export function tagValueOf(n: number): Tag {
|
|
19
|
-
if (n < 0 || n > 13) {
|
|
20
|
-
throw new Error(`Invalid tag value: ${n}`);
|
|
21
|
-
}
|
|
22
|
-
return n as Tag;
|
|
23
|
-
}
|
package/src/write-array-list.ts
DELETED
|
@@ -1,65 +0,0 @@
|
|
|
1
|
-
import { ReadArrayList } from './read-array-list';
|
|
2
|
-
import { WriteCursor, WriteCursorIterator } from './write-cursor';
|
|
3
|
-
import {
|
|
4
|
-
ArrayListInit,
|
|
5
|
-
ArrayListGet,
|
|
6
|
-
ArrayListAppend,
|
|
7
|
-
ArrayListSlice,
|
|
8
|
-
WriteData,
|
|
9
|
-
Context,
|
|
10
|
-
type ContextFunction,
|
|
11
|
-
} from './database';
|
|
12
|
-
import type { WriteableData } from './writeable-data';
|
|
13
|
-
|
|
14
|
-
export class WriteArrayList extends ReadArrayList {
|
|
15
|
-
constructor(cursor: WriteCursor) {
|
|
16
|
-
super(cursor);
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
static async create(cursor: WriteCursor): Promise<WriteArrayList> {
|
|
20
|
-
const newCursor = await cursor.writePath([new ArrayListInit()]);
|
|
21
|
-
return new WriteArrayList(newCursor);
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
override iterator(): WriteCursorIterator {
|
|
25
|
-
return (this.cursor as WriteCursor).iterator();
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
override async *[Symbol.asyncIterator](): AsyncIterator<WriteCursor> {
|
|
29
|
-
yield* this.cursor as WriteCursor;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
async put(index: number, data: WriteableData): Promise<void> {
|
|
33
|
-
await (this.cursor as WriteCursor).writePath([
|
|
34
|
-
new ArrayListGet(index),
|
|
35
|
-
new WriteData(data),
|
|
36
|
-
]);
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
async putCursor(index: number): Promise<WriteCursor> {
|
|
40
|
-
return (this.cursor as WriteCursor).writePath([new ArrayListGet(index)]);
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
async append(data: WriteableData): Promise<void> {
|
|
44
|
-
await (this.cursor as WriteCursor).writePath([
|
|
45
|
-
new ArrayListAppend(),
|
|
46
|
-
new WriteData(data),
|
|
47
|
-
]);
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
async appendCursor(): Promise<WriteCursor> {
|
|
51
|
-
return (this.cursor as WriteCursor).writePath([new ArrayListAppend()]);
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
async appendContext(data: WriteableData | null, fn: ContextFunction): Promise<void> {
|
|
55
|
-
await (this.cursor as WriteCursor).writePath([
|
|
56
|
-
new ArrayListAppend(),
|
|
57
|
-
new WriteData(data),
|
|
58
|
-
new Context(fn),
|
|
59
|
-
]);
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
async slice(size: number): Promise<void> {
|
|
63
|
-
await (this.cursor as WriteCursor).writePath([new ArrayListSlice(size)]);
|
|
64
|
-
}
|
|
65
|
-
}
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
import { Tag } from './tag';
|
|
2
|
-
import { WriteHashMap } from './write-hash-map';
|
|
3
|
-
import { WriteCursor } from './write-cursor';
|
|
4
|
-
import { HashMapInit } from './database';
|
|
5
|
-
import { UnexpectedTagException } from './exceptions';
|
|
6
|
-
|
|
7
|
-
export class WriteCountedHashMap extends WriteHashMap {
|
|
8
|
-
protected constructor() {
|
|
9
|
-
super();
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
static override async create(cursor: WriteCursor): Promise<WriteCountedHashMap> {
|
|
13
|
-
const map = new WriteCountedHashMap();
|
|
14
|
-
switch (cursor.slotPtr.slot.tag) {
|
|
15
|
-
case Tag.NONE:
|
|
16
|
-
case Tag.COUNTED_HASH_MAP:
|
|
17
|
-
case Tag.COUNTED_HASH_SET: {
|
|
18
|
-
const newCursor = await cursor.writePath([new HashMapInit(true, false)]);
|
|
19
|
-
map.cursor = newCursor;
|
|
20
|
-
break;
|
|
21
|
-
}
|
|
22
|
-
default:
|
|
23
|
-
throw new UnexpectedTagException();
|
|
24
|
-
}
|
|
25
|
-
return map;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
async count(): Promise<number> {
|
|
29
|
-
return this.cursor.count();
|
|
30
|
-
}
|
|
31
|
-
}
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
import { Tag } from './tag';
|
|
2
|
-
import { WriteHashSet } from './write-hash-set';
|
|
3
|
-
import { WriteCursor } from './write-cursor';
|
|
4
|
-
import { HashMapInit } from './database';
|
|
5
|
-
import { UnexpectedTagException } from './exceptions';
|
|
6
|
-
|
|
7
|
-
export class WriteCountedHashSet extends WriteHashSet {
|
|
8
|
-
protected constructor() {
|
|
9
|
-
super();
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
static override async create(cursor: WriteCursor): Promise<WriteCountedHashSet> {
|
|
13
|
-
const set = new WriteCountedHashSet();
|
|
14
|
-
switch (cursor.slotPtr.slot.tag) {
|
|
15
|
-
case Tag.NONE:
|
|
16
|
-
case Tag.COUNTED_HASH_MAP:
|
|
17
|
-
case Tag.COUNTED_HASH_SET: {
|
|
18
|
-
const newCursor = await cursor.writePath([new HashMapInit(true, true)]);
|
|
19
|
-
set.cursor = newCursor;
|
|
20
|
-
break;
|
|
21
|
-
}
|
|
22
|
-
default:
|
|
23
|
-
throw new UnexpectedTagException();
|
|
24
|
-
}
|
|
25
|
-
return set;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
async count(): Promise<number> {
|
|
29
|
-
return this.cursor.count();
|
|
30
|
-
}
|
|
31
|
-
}
|
package/src/write-cursor.ts
DELETED
|
@@ -1,166 +0,0 @@
|
|
|
1
|
-
import { Tag } from './tag';
|
|
2
|
-
import { Slot } from './slot';
|
|
3
|
-
import { SlotPointer } from './slot-pointer';
|
|
4
|
-
import {
|
|
5
|
-
Database,
|
|
6
|
-
WriteMode,
|
|
7
|
-
WriteData,
|
|
8
|
-
type PathPart,
|
|
9
|
-
} from './database';
|
|
10
|
-
import {
|
|
11
|
-
ReadCursor,
|
|
12
|
-
KeyValuePairCursor,
|
|
13
|
-
CursorIterator,
|
|
14
|
-
} from './read-cursor';
|
|
15
|
-
import {
|
|
16
|
-
CursorNotWriteableException,
|
|
17
|
-
EndOfStreamException,
|
|
18
|
-
UnexpectedWriterPositionException,
|
|
19
|
-
} from './exceptions';
|
|
20
|
-
import type { WriteableData } from './writeable-data';
|
|
21
|
-
|
|
22
|
-
export class WriteKeyValuePairCursor extends KeyValuePairCursor {
|
|
23
|
-
override valueCursor: WriteCursor;
|
|
24
|
-
override keyCursor: WriteCursor;
|
|
25
|
-
|
|
26
|
-
constructor(valueCursor: WriteCursor, keyCursor: WriteCursor, hash: Uint8Array) {
|
|
27
|
-
super(valueCursor, keyCursor, hash);
|
|
28
|
-
this.valueCursor = valueCursor;
|
|
29
|
-
this.keyCursor = keyCursor;
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
export class WriteCursor extends ReadCursor {
|
|
34
|
-
constructor(slotPtr: SlotPointer, db: Database) {
|
|
35
|
-
super(slotPtr, db);
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
async writePath(path: PathPart[]): Promise<WriteCursor> {
|
|
39
|
-
const slotPtr = await this.db.readSlotPointer(WriteMode.READ_WRITE, path, 0, this.slotPtr);
|
|
40
|
-
if (this.db.txStart === null) {
|
|
41
|
-
await this.db.core.sync();
|
|
42
|
-
}
|
|
43
|
-
return new WriteCursor(slotPtr, this.db);
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
async write(data: WriteableData | null): Promise<void> {
|
|
47
|
-
const cursor = await this.writePath([new WriteData(data)]);
|
|
48
|
-
this.slotPtr = cursor.slotPtr;
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
async writeIfEmpty(data: WriteableData): Promise<void> {
|
|
52
|
-
if (this.slotPtr.slot.empty()) {
|
|
53
|
-
await this.write(data);
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
override async readKeyValuePair(): Promise<WriteKeyValuePairCursor> {
|
|
58
|
-
const kvPairCursor = await super.readKeyValuePair();
|
|
59
|
-
return new WriteKeyValuePairCursor(
|
|
60
|
-
new WriteCursor(kvPairCursor.valueCursor.slotPtr, this.db),
|
|
61
|
-
new WriteCursor(kvPairCursor.keyCursor.slotPtr, this.db),
|
|
62
|
-
kvPairCursor.hash
|
|
63
|
-
);
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
async writer(): Promise<Writer> {
|
|
67
|
-
const writer = this.db.core.writer();
|
|
68
|
-
const ptrPos = await this.db.core.length();
|
|
69
|
-
await this.db.core.seek(ptrPos);
|
|
70
|
-
await writer.writeLong(0);
|
|
71
|
-
const startPosition = await this.db.core.length();
|
|
72
|
-
return new Writer(this, 0, new Slot(ptrPos, Tag.BYTES), startPosition, 0);
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
override async *[Symbol.asyncIterator](): AsyncIterator<WriteCursor> {
|
|
76
|
-
const iterator = new WriteCursorIterator(this);
|
|
77
|
-
await iterator.init();
|
|
78
|
-
while (await iterator.hasNext()) {
|
|
79
|
-
const next = await iterator.next();
|
|
80
|
-
if (next !== null) {
|
|
81
|
-
yield next;
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
override iterator(): WriteCursorIterator {
|
|
87
|
-
return new WriteCursorIterator(this);
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
export class Writer {
|
|
92
|
-
parent: WriteCursor;
|
|
93
|
-
size: number;
|
|
94
|
-
slot: Slot;
|
|
95
|
-
startPosition: number;
|
|
96
|
-
relativePosition: number;
|
|
97
|
-
formatTag: Uint8Array | null = null;
|
|
98
|
-
|
|
99
|
-
constructor(
|
|
100
|
-
parent: WriteCursor,
|
|
101
|
-
size: number,
|
|
102
|
-
slot: Slot,
|
|
103
|
-
startPosition: number,
|
|
104
|
-
relativePosition: number
|
|
105
|
-
) {
|
|
106
|
-
this.parent = parent;
|
|
107
|
-
this.size = size;
|
|
108
|
-
this.slot = slot;
|
|
109
|
-
this.startPosition = startPosition;
|
|
110
|
-
this.relativePosition = relativePosition;
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
async write(buffer: Uint8Array): Promise<void> {
|
|
114
|
-
if (this.size < this.relativePosition) throw new EndOfStreamException();
|
|
115
|
-
await this.parent.db.core.seek(this.startPosition + this.relativePosition);
|
|
116
|
-
const writer = this.parent.db.core.writer();
|
|
117
|
-
await writer.write(buffer);
|
|
118
|
-
this.relativePosition += buffer.length;
|
|
119
|
-
if (this.relativePosition > this.size) {
|
|
120
|
-
this.size = this.relativePosition;
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
async finish(): Promise<void> {
|
|
125
|
-
const writer = this.parent.db.core.writer();
|
|
126
|
-
|
|
127
|
-
if (this.formatTag !== null) {
|
|
128
|
-
this.slot = this.slot.withFull(true);
|
|
129
|
-
const formatTagPos = await this.parent.db.core.length();
|
|
130
|
-
await this.parent.db.core.seek(formatTagPos);
|
|
131
|
-
if (this.startPosition + this.size !== formatTagPos) throw new UnexpectedWriterPositionException();
|
|
132
|
-
await writer.write(this.formatTag);
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
await this.parent.db.core.seek(Number(this.slot.value));
|
|
136
|
-
await writer.writeLong(this.size);
|
|
137
|
-
|
|
138
|
-
if (this.parent.slotPtr.position === null) throw new CursorNotWriteableException();
|
|
139
|
-
const position = this.parent.slotPtr.position;
|
|
140
|
-
await this.parent.db.core.seek(position);
|
|
141
|
-
await writer.write(this.slot.toBytes());
|
|
142
|
-
|
|
143
|
-
this.parent.slotPtr = this.parent.slotPtr.withSlot(this.slot);
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
seek(position: number): void {
|
|
147
|
-
if (position <= this.size) {
|
|
148
|
-
this.relativePosition = position;
|
|
149
|
-
}
|
|
150
|
-
}
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
export class WriteCursorIterator extends CursorIterator {
|
|
154
|
-
constructor(cursor: WriteCursor) {
|
|
155
|
-
super(cursor);
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
override async next(): Promise<WriteCursor | null> {
|
|
159
|
-
const readCursor = await super.next();
|
|
160
|
-
if (readCursor !== null) {
|
|
161
|
-
return new WriteCursor(readCursor.slotPtr, readCursor.db);
|
|
162
|
-
} else {
|
|
163
|
-
return null;
|
|
164
|
-
}
|
|
165
|
-
}
|
|
166
|
-
}
|
package/src/write-hash-map.ts
DELETED
|
@@ -1,129 +0,0 @@
|
|
|
1
|
-
import { ReadHashMap } from './read-hash-map';
|
|
2
|
-
import { WriteCursor, WriteCursorIterator, WriteKeyValuePairCursor } from './write-cursor';
|
|
3
|
-
import {
|
|
4
|
-
HashMapInit,
|
|
5
|
-
HashMapGet,
|
|
6
|
-
HashMapGetValue,
|
|
7
|
-
HashMapGetKey,
|
|
8
|
-
HashMapRemove,
|
|
9
|
-
WriteData,
|
|
10
|
-
} from './database';
|
|
11
|
-
import type { WriteableData } from './writeable-data';
|
|
12
|
-
import { Bytes } from './writeable-data';
|
|
13
|
-
import { KeyNotFoundException } from './exceptions';
|
|
14
|
-
|
|
15
|
-
export class WriteHashMap extends ReadHashMap {
|
|
16
|
-
protected constructor() {
|
|
17
|
-
super();
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
static async create(cursor: WriteCursor): Promise<WriteHashMap> {
|
|
21
|
-
const map = new WriteHashMap();
|
|
22
|
-
const newCursor = await cursor.writePath([new HashMapInit(false, false)]);
|
|
23
|
-
map.cursor = newCursor;
|
|
24
|
-
return map;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
override iterator(): WriteCursorIterator {
|
|
28
|
-
return (this.cursor as WriteCursor).iterator();
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
override async *[Symbol.asyncIterator](): AsyncIterator<WriteCursor> {
|
|
32
|
-
yield* this.cursor as WriteCursor;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
// Methods that take a string key and hash it
|
|
36
|
-
async putByString(key: string, data: WriteableData): Promise<void> {
|
|
37
|
-
const hash = await this.cursor.db.hasher.digest(new TextEncoder().encode(key));
|
|
38
|
-
await this.putKey(hash, new Bytes(key));
|
|
39
|
-
await this.put(hash, data);
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
async putCursorByString(key: string): Promise<WriteCursor> {
|
|
43
|
-
const hash = await this.cursor.db.hasher.digest(new TextEncoder().encode(key));
|
|
44
|
-
await this.putKey(hash, new Bytes(key));
|
|
45
|
-
return this.putCursor(hash);
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
async putKeyByString(key: string, data: WriteableData): Promise<void> {
|
|
49
|
-
const hash = await this.cursor.db.hasher.digest(new TextEncoder().encode(key));
|
|
50
|
-
await this.putKey(hash, data);
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
async putKeyCursorByString(key: string): Promise<WriteCursor> {
|
|
54
|
-
const hash = await this.cursor.db.hasher.digest(new TextEncoder().encode(key));
|
|
55
|
-
return this.putKeyCursor(hash);
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
async removeByString(key: string): Promise<boolean> {
|
|
59
|
-
const hash = await this.cursor.db.hasher.digest(new TextEncoder().encode(key));
|
|
60
|
-
return this.remove(hash);
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
// Methods that take Bytes key and hash it
|
|
64
|
-
async putByBytes(key: Bytes, data: WriteableData): Promise<void> {
|
|
65
|
-
const hash = await this.cursor.db.hasher.digest(key.value);
|
|
66
|
-
await this.putKey(hash, key);
|
|
67
|
-
await this.put(hash, data);
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
async putCursorByBytes(key: Bytes): Promise<WriteCursor> {
|
|
71
|
-
const hash = await this.cursor.db.hasher.digest(key.value);
|
|
72
|
-
await this.putKey(hash, key);
|
|
73
|
-
return this.putCursor(hash);
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
async putKeyByBytes(key: Bytes, data: WriteableData): Promise<void> {
|
|
77
|
-
const hash = await this.cursor.db.hasher.digest(key.value);
|
|
78
|
-
await this.putKey(hash, data);
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
async putKeyCursorByBytes(key: Bytes): Promise<WriteCursor> {
|
|
82
|
-
const hash = await this.cursor.db.hasher.digest(key.value);
|
|
83
|
-
return this.putKeyCursor(hash);
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
async removeByBytes(key: Bytes): Promise<boolean> {
|
|
87
|
-
const hash = await this.cursor.db.hasher.digest(key.value);
|
|
88
|
-
return this.remove(hash);
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
// Methods that take hash directly
|
|
92
|
-
async put(hash: Uint8Array, data: WriteableData): Promise<void> {
|
|
93
|
-
await (this.cursor as WriteCursor).writePath([
|
|
94
|
-
new HashMapGet(new HashMapGetValue(hash)),
|
|
95
|
-
new WriteData(data),
|
|
96
|
-
]);
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
async putCursor(hash: Uint8Array): Promise<WriteCursor> {
|
|
100
|
-
return (this.cursor as WriteCursor).writePath([
|
|
101
|
-
new HashMapGet(new HashMapGetValue(hash)),
|
|
102
|
-
]);
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
async putKey(hash: Uint8Array, data: WriteableData): Promise<void> {
|
|
106
|
-
const cursor = await (this.cursor as WriteCursor).writePath([
|
|
107
|
-
new HashMapGet(new HashMapGetKey(hash)),
|
|
108
|
-
]);
|
|
109
|
-
await cursor.writeIfEmpty(data);
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
async putKeyCursor(hash: Uint8Array): Promise<WriteCursor> {
|
|
113
|
-
return (this.cursor as WriteCursor).writePath([
|
|
114
|
-
new HashMapGet(new HashMapGetKey(hash)),
|
|
115
|
-
]);
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
async remove(hash: Uint8Array): Promise<boolean> {
|
|
119
|
-
try {
|
|
120
|
-
await (this.cursor as WriteCursor).writePath([new HashMapRemove(hash)]);
|
|
121
|
-
} catch (e) {
|
|
122
|
-
if (e instanceof KeyNotFoundException) {
|
|
123
|
-
return false;
|
|
124
|
-
}
|
|
125
|
-
throw e;
|
|
126
|
-
}
|
|
127
|
-
return true;
|
|
128
|
-
}
|
|
129
|
-
}
|