microcbor 1.2.0 → 1.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -13,6 +13,8 @@ export declare class Decoder<T extends CBORValue = CBORValue> implements AsyncIt
|
|
|
13
13
|
private readonly constantView;
|
|
14
14
|
private readonly iter;
|
|
15
15
|
private readonly onFree?;
|
|
16
|
+
private readonly touchedChunks;
|
|
17
|
+
private readonly freedChunks;
|
|
16
18
|
constructor(source: AsyncIterable<Uint8Array>, options?: AsyncDecodeOptions);
|
|
17
19
|
[Symbol.asyncIterator]: () => this;
|
|
18
20
|
private allocate;
|
|
@@ -8,6 +8,8 @@ export class Decoder {
|
|
|
8
8
|
this.chunks = [];
|
|
9
9
|
this.constantBuffer = new ArrayBuffer(8);
|
|
10
10
|
this.constantView = new DataView(this.constantBuffer);
|
|
11
|
+
this.touchedChunks = new WeakSet();
|
|
12
|
+
this.freedChunks = new WeakSet();
|
|
11
13
|
this[_a] = () => this;
|
|
12
14
|
this.constant = (size, f) => {
|
|
13
15
|
return async () => {
|
|
@@ -30,6 +32,16 @@ export class Decoder {
|
|
|
30
32
|
this.iter = source[Symbol.asyncIterator]();
|
|
31
33
|
}
|
|
32
34
|
async allocate(size) {
|
|
35
|
+
// If we need more data, first call onFree for all touched chunks
|
|
36
|
+
// This allows the transform stream to provide more chunks
|
|
37
|
+
if (this.byteLength < size && this.onFree !== undefined) {
|
|
38
|
+
for (const chunk of this.chunks) {
|
|
39
|
+
if (this.touchedChunks.has(chunk) && !this.freedChunks.has(chunk)) {
|
|
40
|
+
this.freedChunks.add(chunk);
|
|
41
|
+
this.onFree(chunk);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
33
45
|
while (this.byteLength < size) {
|
|
34
46
|
const { done, value } = await this.iter.next();
|
|
35
47
|
if (done) {
|
|
@@ -38,6 +50,12 @@ export class Decoder {
|
|
|
38
50
|
else {
|
|
39
51
|
this.chunks.push(value);
|
|
40
52
|
this.byteLength += value.byteLength;
|
|
53
|
+
// If we still need more data after adding this chunk,
|
|
54
|
+
// immediately call onFree to allow the next chunk to flow
|
|
55
|
+
if (this.byteLength < size && this.onFree !== undefined && !this.freedChunks.has(value)) {
|
|
56
|
+
this.freedChunks.add(value);
|
|
57
|
+
this.onFree(value);
|
|
58
|
+
}
|
|
41
59
|
}
|
|
42
60
|
}
|
|
43
61
|
}
|
|
@@ -49,6 +67,10 @@ export class Decoder {
|
|
|
49
67
|
let deleteCount = 0;
|
|
50
68
|
for (let i = 0; byteLength < target.byteLength; i++) {
|
|
51
69
|
const chunk = this.chunks[i];
|
|
70
|
+
// Track which chunks we touched
|
|
71
|
+
if (!this.touchedChunks.has(chunk)) {
|
|
72
|
+
this.touchedChunks.add(chunk);
|
|
73
|
+
}
|
|
52
74
|
const capacity = target.byteLength - byteLength;
|
|
53
75
|
const length = chunk.byteLength - this.offset;
|
|
54
76
|
if (length <= capacity) {
|
|
@@ -67,9 +89,14 @@ export class Decoder {
|
|
|
67
89
|
this.byteLength -= capacity;
|
|
68
90
|
}
|
|
69
91
|
}
|
|
92
|
+
// Call onFree for chunks that are being removed (fully consumed)
|
|
70
93
|
if (this.onFree !== undefined) {
|
|
71
94
|
for (let i = 0; i < deleteCount; i++) {
|
|
72
|
-
this.
|
|
95
|
+
const chunk = this.chunks[i];
|
|
96
|
+
if (!this.freedChunks.has(chunk)) {
|
|
97
|
+
this.freedChunks.add(chunk);
|
|
98
|
+
this.onFree(chunk);
|
|
99
|
+
}
|
|
73
100
|
}
|
|
74
101
|
}
|
|
75
102
|
this.chunks.splice(0, deleteCount);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "microcbor",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.1",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"files": [
|
|
6
6
|
"lib"
|
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
},
|
|
33
33
|
"homepage": "https://github.com/joeltg/microcbor#readme",
|
|
34
34
|
"devDependencies": {
|
|
35
|
-
"@ava/typescript": "^
|
|
35
|
+
"@ava/typescript": "^6.0.0",
|
|
36
36
|
"@types/node": "^22.13.9",
|
|
37
37
|
"ava": "^6.2.0",
|
|
38
38
|
"cbor": "^10.0.3",
|