@ipld/car 4.1.6 → 5.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +4 -0
- package/README.md +12 -4
- package/dist/index.min.js +5 -0
- package/{types → dist/src}/api.d.ts +19 -19
- package/dist/src/api.d.ts.map +1 -0
- package/{types/lib → dist/src}/buffer-writer.d.ts +10 -10
- package/{types/lib → dist/src}/buffer-writer.d.ts.map +1 -1
- package/dist/src/coding.d.ts +41 -0
- package/dist/src/coding.d.ts.map +1 -0
- package/{types/lib → dist/src}/decoder.d.ts +3 -3
- package/{types/lib → dist/src}/decoder.d.ts.map +1 -1
- package/{types/lib → dist/src}/encoder.d.ts +2 -2
- package/{types/lib → dist/src}/encoder.d.ts.map +1 -1
- package/{types/lib → dist/src}/header-validator.d.ts +0 -0
- package/dist/src/header-validator.d.ts.map +1 -0
- package/dist/src/index-browser.d.ts +8 -0
- package/dist/src/index-browser.d.ts.map +1 -0
- package/dist/src/index.d.ts +9 -0
- package/dist/src/index.d.ts.map +1 -0
- package/{types/lib → dist/src}/indexed-reader-browser.d.ts +0 -0
- package/dist/src/indexed-reader-browser.d.ts.map +1 -0
- package/{types/lib → dist/src}/indexed-reader.d.ts +13 -13
- package/dist/src/indexed-reader.d.ts.map +1 -0
- package/{types/lib → dist/src}/indexer.d.ts +9 -9
- package/{types/lib → dist/src}/indexer.d.ts.map +1 -1
- package/{types/lib → dist/src}/iterator-channel.d.ts +0 -0
- package/{types/lib → dist/src}/iterator-channel.d.ts.map +1 -1
- package/{types/lib → dist/src}/iterator.d.ts +8 -8
- package/{types/lib → dist/src}/iterator.d.ts.map +1 -1
- package/{types/lib → dist/src}/reader-browser.d.ts +10 -10
- package/{types/lib → dist/src}/reader-browser.d.ts.map +1 -1
- package/{types/lib → dist/src}/reader.d.ts +5 -5
- package/{types/lib → dist/src}/reader.d.ts.map +1 -1
- package/{types/lib → dist/src}/writer-browser.d.ts +10 -10
- package/{types/lib → dist/src}/writer-browser.d.ts.map +1 -1
- package/{types/lib → dist/src}/writer.d.ts +4 -4
- package/{types/lib → dist/src}/writer.d.ts.map +1 -1
- package/package.json +102 -209
- package/{api.ts → src/api.ts} +14 -14
- package/{lib → src}/buffer-writer.js +5 -5
- package/src/coding.ts +56 -0
- package/{lib → src}/decoder.js +7 -7
- package/{lib → src}/encoder.js +1 -1
- package/src/header-validator.js +74 -0
- package/{lib → src}/header.ipldsch +0 -0
- package/src/index-browser.js +14 -0
- package/src/index.js +16 -0
- package/{lib → src}/indexed-reader-browser.js +0 -0
- package/{lib → src}/indexed-reader.js +9 -9
- package/{lib → src}/indexer.js +4 -4
- package/{lib → src}/iterator-channel.js +0 -0
- package/{lib → src}/iterator.js +4 -4
- package/{lib → src}/reader-browser.js +7 -7
- package/{lib → src}/reader.js +5 -5
- package/{lib → src}/writer-browser.js +7 -7
- package/{lib → src}/writer.js +3 -3
- package/LICENSE-APACHE +0 -13
- package/LICENSE-MIT +0 -7
- package/buffer-writer +0 -1
- package/car-browser.js +0 -14
- package/car.js +0 -16
- package/cjs/browser-test/common.js +0 -301
- package/cjs/browser-test/node-test-file-streams.js +0 -71
- package/cjs/browser-test/node-test-indexed-reader.js +0 -51
- package/cjs/browser-test/node-test-large.js +0 -135
- package/cjs/browser-test/node-test-raw.js +0 -68
- package/cjs/browser-test/node-test-updateroots.js +0 -78
- package/cjs/browser-test/test-buffer-writer.js +0 -330
- package/cjs/browser-test/test-errors.js +0 -90
- package/cjs/browser-test/test-indexer.js +0 -80
- package/cjs/browser-test/test-interface.js +0 -21
- package/cjs/browser-test/test-iterator.js +0 -83
- package/cjs/browser-test/test-reader.js +0 -278
- package/cjs/browser-test/test-writer.js +0 -286
- package/cjs/browser-test/verify-store-reader.js +0 -142
- package/cjs/car-browser.js +0 -18
- package/cjs/car.js +0 -20
- package/cjs/lib/buffer-writer.js +0 -164
- package/cjs/lib/decoder.js +0 -301
- package/cjs/lib/encoder.js +0 -44
- package/cjs/lib/header-validator.js +0 -29
- package/cjs/lib/indexed-reader-browser.js +0 -13
- package/cjs/lib/indexed-reader.js +0 -90
- package/cjs/lib/indexer.js +0 -41
- package/cjs/lib/iterator-channel.js +0 -77
- package/cjs/lib/iterator.js +0 -97
- package/cjs/lib/reader-browser.js +0 -62
- package/cjs/lib/reader.js +0 -38
- package/cjs/lib/writer-browser.js +0 -118
- package/cjs/lib/writer.js +0 -51
- package/cjs/node-test/common.js +0 -301
- package/cjs/node-test/node-test-file-streams.js +0 -71
- package/cjs/node-test/node-test-indexed-reader.js +0 -51
- package/cjs/node-test/node-test-large.js +0 -135
- package/cjs/node-test/node-test-raw.js +0 -68
- package/cjs/node-test/node-test-updateroots.js +0 -78
- package/cjs/node-test/test-buffer-writer.js +0 -330
- package/cjs/node-test/test-errors.js +0 -90
- package/cjs/node-test/test-indexer.js +0 -80
- package/cjs/node-test/test-interface.js +0 -21
- package/cjs/node-test/test-iterator.js +0 -83
- package/cjs/node-test/test-reader.js +0 -278
- package/cjs/node-test/test-writer.js +0 -286
- package/cjs/node-test/verify-store-reader.js +0 -142
- package/decoder +0 -1
- package/esm/browser-test/common.js +0 -274
- package/esm/browser-test/node-test-file-streams.js +0 -76
- package/esm/browser-test/node-test-indexed-reader.js +0 -53
- package/esm/browser-test/node-test-large.js +0 -109
- package/esm/browser-test/node-test-raw.js +0 -63
- package/esm/browser-test/node-test-updateroots.js +0 -76
- package/esm/browser-test/test-buffer-writer.js +0 -311
- package/esm/browser-test/test-errors.js +0 -91
- package/esm/browser-test/test-indexer.js +0 -85
- package/esm/browser-test/test-interface.js +0 -24
- package/esm/browser-test/test-iterator.js +0 -91
- package/esm/browser-test/test-reader.js +0 -270
- package/esm/browser-test/test-writer.js +0 -297
- package/esm/browser-test/verify-store-reader.js +0 -122
- package/esm/car-browser.js +0 -16
- package/esm/car.js +0 -18
- package/esm/lib/buffer-writer.js +0 -129
- package/esm/lib/decoder.js +0 -265
- package/esm/lib/encoder.js +0 -35
- package/esm/lib/header-validator.js +0 -23
- package/esm/lib/indexed-reader-browser.js +0 -6
- package/esm/lib/indexed-reader.js +0 -78
- package/esm/lib/indexer.js +0 -38
- package/esm/lib/iterator-channel.js +0 -71
- package/esm/lib/iterator.js +0 -92
- package/esm/lib/reader-browser.js +0 -57
- package/esm/lib/reader.js +0 -26
- package/esm/lib/writer-browser.js +0 -115
- package/esm/lib/writer.js +0 -42
- package/esm/node-test/common.js +0 -274
- package/esm/node-test/node-test-file-streams.js +0 -76
- package/esm/node-test/node-test-indexed-reader.js +0 -53
- package/esm/node-test/node-test-large.js +0 -109
- package/esm/node-test/node-test-raw.js +0 -63
- package/esm/node-test/node-test-updateroots.js +0 -76
- package/esm/node-test/test-buffer-writer.js +0 -311
- package/esm/node-test/test-errors.js +0 -91
- package/esm/node-test/test-indexer.js +0 -85
- package/esm/node-test/test-interface.js +0 -24
- package/esm/node-test/test-iterator.js +0 -91
- package/esm/node-test/test-reader.js +0 -270
- package/esm/node-test/test-writer.js +0 -297
- package/esm/node-test/verify-store-reader.js +0 -122
- package/esm/package.json +0 -9
- package/examples/car-to-fixture.js +0 -66
- package/examples/dump-car.js +0 -58
- package/examples/dump-index.js +0 -24
- package/examples/package.json +0 -27
- package/examples/round-trip.js +0 -45
- package/examples/test-examples.js +0 -115
- package/examples/verify-car.js +0 -87
- package/index.js +0 -1
- package/indexed-reader +0 -1
- package/indexer +0 -1
- package/iterator +0 -1
- package/lib/coding.ts +0 -56
- package/lib/header-validator.js +0 -33
- package/reader +0 -1
- package/test/_fixtures_to_js.mjs +0 -24
- package/test/common.js +0 -210
- package/test/go.car +0 -0
- package/test/go.carv2 +0 -0
- package/test/node-test-file-streams.js +0 -84
- package/test/node-test-indexed-reader.js +0 -45
- package/test/node-test-large.js +0 -112
- package/test/node-test-raw.js +0 -83
- package/test/node-test-updateroots.js +0 -89
- package/test/test-buffer-writer.js +0 -256
- package/test/test-errors.js +0 -98
- package/test/test-indexer.js +0 -87
- package/test/test-interface.js +0 -24
- package/test/test-iterator.js +0 -74
- package/test/test-reader.js +0 -245
- package/test/test-writer.js +0 -336
- package/test/verify-store-reader.js +0 -191
- package/tsconfig.json +0 -48
- package/types/api.d.ts.map +0 -1
- package/types/car-browser.d.ts +0 -8
- package/types/car-browser.d.ts.map +0 -1
- package/types/car.d.ts +0 -9
- package/types/car.d.ts.map +0 -1
- package/types/lib/coding.d.ts +0 -41
- package/types/lib/coding.d.ts.map +0 -1
- package/types/lib/header-validator.d.ts.map +0 -1
- package/types/lib/indexed-reader-browser.d.ts.map +0 -1
- package/types/lib/indexed-reader.d.ts.map +0 -1
- package/types/test/_fixtures_to_js.d.mts +0 -3
- package/types/test/_fixtures_to_js.d.mts.map +0 -1
- package/types/test/common.d.ts +0 -73
- package/types/test/common.d.ts.map +0 -1
- package/types/test/fixtures-expectations.d.ts +0 -63
- package/types/test/fixtures-expectations.d.ts.map +0 -1
- package/types/test/fixtures.d.ts +0 -3
- package/types/test/fixtures.d.ts.map +0 -1
- package/types/test/node-test-file-streams.d.ts +0 -3
- package/types/test/node-test-file-streams.d.ts.map +0 -1
- package/types/test/node-test-indexed-reader.d.ts +0 -2
- package/types/test/node-test-indexed-reader.d.ts.map +0 -1
- package/types/test/node-test-large.d.ts +0 -2
- package/types/test/node-test-large.d.ts.map +0 -1
- package/types/test/node-test-raw.d.ts +0 -2
- package/types/test/node-test-raw.d.ts.map +0 -1
- package/types/test/node-test-updateroots.d.ts +0 -2
- package/types/test/node-test-updateroots.d.ts.map +0 -1
- package/types/test/test-buffer-writer.d.ts +0 -2
- package/types/test/test-buffer-writer.d.ts.map +0 -1
- package/types/test/test-errors.d.ts +0 -2
- package/types/test/test-errors.d.ts.map +0 -1
- package/types/test/test-indexer.d.ts +0 -2
- package/types/test/test-indexer.d.ts.map +0 -1
- package/types/test/test-interface.d.ts +0 -2
- package/types/test/test-interface.d.ts.map +0 -1
- package/types/test/test-iterator.d.ts +0 -2
- package/types/test/test-iterator.d.ts.map +0 -1
- package/types/test/test-reader.d.ts +0 -2
- package/types/test/test-reader.d.ts.map +0 -1
- package/types/test/test-writer.d.ts +0 -2
- package/types/test/test-writer.d.ts.map +0 -1
- package/types/test/verify-store-reader.d.ts +0 -29
- package/types/test/verify-store-reader.d.ts.map +0 -1
- package/writer +0 -1
package/esm/car.js
DELETED
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
import { CarReader } from './lib/reader.js';
|
|
2
|
-
import { CarIndexer } from './lib/indexer.js';
|
|
3
|
-
import {
|
|
4
|
-
CarBlockIterator,
|
|
5
|
-
CarCIDIterator
|
|
6
|
-
} from './lib/iterator.js';
|
|
7
|
-
import { CarWriter } from './lib/writer.js';
|
|
8
|
-
import { CarIndexedReader } from './lib/indexed-reader.js';
|
|
9
|
-
import * as CarBufferWriter from './lib/buffer-writer.js';
|
|
10
|
-
export {
|
|
11
|
-
CarReader,
|
|
12
|
-
CarIndexer,
|
|
13
|
-
CarBlockIterator,
|
|
14
|
-
CarCIDIterator,
|
|
15
|
-
CarWriter,
|
|
16
|
-
CarIndexedReader,
|
|
17
|
-
CarBufferWriter
|
|
18
|
-
};
|
package/esm/lib/buffer-writer.js
DELETED
|
@@ -1,129 +0,0 @@
|
|
|
1
|
-
import varint from 'varint';
|
|
2
|
-
import {
|
|
3
|
-
Token,
|
|
4
|
-
Type
|
|
5
|
-
} from 'cborg';
|
|
6
|
-
import { tokensToLength } from 'cborg/length';
|
|
7
|
-
import * as CBOR from '@ipld/dag-cbor';
|
|
8
|
-
class CarBufferWriter {
|
|
9
|
-
constructor(bytes, headerSize) {
|
|
10
|
-
this.bytes = bytes;
|
|
11
|
-
this.byteOffset = headerSize;
|
|
12
|
-
this.roots = [];
|
|
13
|
-
this.headerSize = headerSize;
|
|
14
|
-
}
|
|
15
|
-
addRoot(root, options) {
|
|
16
|
-
addRoot(this, root, options);
|
|
17
|
-
return this;
|
|
18
|
-
}
|
|
19
|
-
write(block) {
|
|
20
|
-
addBlock(this, block);
|
|
21
|
-
return this;
|
|
22
|
-
}
|
|
23
|
-
close(options) {
|
|
24
|
-
return close(this, options);
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
export const addRoot = (writer, root, options = {}) => {
|
|
28
|
-
const {
|
|
29
|
-
resize = false
|
|
30
|
-
} = options;
|
|
31
|
-
const {bytes, headerSize, byteOffset, roots} = writer;
|
|
32
|
-
writer.roots.push(root);
|
|
33
|
-
const size = headerLength(writer);
|
|
34
|
-
if (size > headerSize) {
|
|
35
|
-
if (size - headerSize + byteOffset < bytes.byteLength) {
|
|
36
|
-
if (resize) {
|
|
37
|
-
resizeHeader(writer, size);
|
|
38
|
-
} else {
|
|
39
|
-
roots.pop();
|
|
40
|
-
throw new RangeError(`Header of size ${ headerSize } has no capacity for new root ${ root }.
|
|
41
|
-
However there is a space in the buffer and you could call addRoot(root, { resize: root }) to resize header to make a space for this root.`);
|
|
42
|
-
}
|
|
43
|
-
} else {
|
|
44
|
-
roots.pop();
|
|
45
|
-
throw new RangeError(`Buffer has no capacity for a new root ${ root }`);
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
};
|
|
49
|
-
export const blockLength = ({cid, bytes}) => {
|
|
50
|
-
const size = cid.bytes.byteLength + bytes.byteLength;
|
|
51
|
-
return varint.encodingLength(size) + size;
|
|
52
|
-
};
|
|
53
|
-
export const addBlock = (writer, {cid, bytes}) => {
|
|
54
|
-
const byteLength = cid.bytes.byteLength + bytes.byteLength;
|
|
55
|
-
const size = varint.encode(byteLength);
|
|
56
|
-
if (writer.byteOffset + size.length + byteLength > writer.bytes.byteLength) {
|
|
57
|
-
throw new RangeError('Buffer has no capacity for this block');
|
|
58
|
-
} else {
|
|
59
|
-
writeBytes(writer, size);
|
|
60
|
-
writeBytes(writer, cid.bytes);
|
|
61
|
-
writeBytes(writer, bytes);
|
|
62
|
-
}
|
|
63
|
-
};
|
|
64
|
-
export const close = (writer, options = {}) => {
|
|
65
|
-
const {
|
|
66
|
-
resize = false
|
|
67
|
-
} = options;
|
|
68
|
-
const {roots, bytes, byteOffset, headerSize} = writer;
|
|
69
|
-
const headerBytes = CBOR.encode({
|
|
70
|
-
version: 1,
|
|
71
|
-
roots
|
|
72
|
-
});
|
|
73
|
-
const varintBytes = varint.encode(headerBytes.length);
|
|
74
|
-
const size = varintBytes.length + headerBytes.byteLength;
|
|
75
|
-
const offset = headerSize - size;
|
|
76
|
-
if (offset === 0) {
|
|
77
|
-
writeHeader(writer, varintBytes, headerBytes);
|
|
78
|
-
return bytes.subarray(0, byteOffset);
|
|
79
|
-
} else if (resize) {
|
|
80
|
-
resizeHeader(writer, size);
|
|
81
|
-
writeHeader(writer, varintBytes, headerBytes);
|
|
82
|
-
return bytes.subarray(0, writer.byteOffset);
|
|
83
|
-
} else {
|
|
84
|
-
throw new RangeError(`Header size was overestimated.
|
|
85
|
-
You can use close({ resize: true }) to resize header`);
|
|
86
|
-
}
|
|
87
|
-
};
|
|
88
|
-
export const resizeHeader = (writer, byteLength) => {
|
|
89
|
-
const {bytes, headerSize} = writer;
|
|
90
|
-
bytes.set(bytes.subarray(headerSize, writer.byteOffset), byteLength);
|
|
91
|
-
writer.byteOffset += byteLength - headerSize;
|
|
92
|
-
writer.headerSize = byteLength;
|
|
93
|
-
};
|
|
94
|
-
const writeBytes = (writer, bytes) => {
|
|
95
|
-
writer.bytes.set(bytes, writer.byteOffset);
|
|
96
|
-
writer.byteOffset += bytes.length;
|
|
97
|
-
};
|
|
98
|
-
const writeHeader = ({bytes}, varint, header) => {
|
|
99
|
-
bytes.set(varint);
|
|
100
|
-
bytes.set(header, varint.length);
|
|
101
|
-
};
|
|
102
|
-
const headerPreludeTokens = [
|
|
103
|
-
new Token(Type.map, 2),
|
|
104
|
-
new Token(Type.string, 'version'),
|
|
105
|
-
new Token(Type.uint, 1),
|
|
106
|
-
new Token(Type.string, 'roots')
|
|
107
|
-
];
|
|
108
|
-
const CID_TAG = new Token(Type.tag, 42);
|
|
109
|
-
export const calculateHeaderLength = rootLengths => {
|
|
110
|
-
const tokens = [...headerPreludeTokens];
|
|
111
|
-
tokens.push(new Token(Type.array, rootLengths.length));
|
|
112
|
-
for (const rootLength of rootLengths) {
|
|
113
|
-
tokens.push(CID_TAG);
|
|
114
|
-
tokens.push(new Token(Type.bytes, { length: rootLength + 1 }));
|
|
115
|
-
}
|
|
116
|
-
const length = tokensToLength(tokens);
|
|
117
|
-
return varint.encodingLength(length) + length;
|
|
118
|
-
};
|
|
119
|
-
export const headerLength = ({roots}) => calculateHeaderLength(roots.map(cid => cid.bytes.byteLength));
|
|
120
|
-
export const estimateHeaderLength = (rootCount, rootByteLength = 36) => calculateHeaderLength(new Array(rootCount).fill(rootByteLength));
|
|
121
|
-
export const createWriter = (buffer, options = {}) => {
|
|
122
|
-
const {roots = [], byteOffset = 0, byteLength = buffer.byteLength, headerSize = headerLength({ roots })} = options;
|
|
123
|
-
const bytes = new Uint8Array(buffer, byteOffset, byteLength);
|
|
124
|
-
const writer = new CarBufferWriter(bytes, headerSize);
|
|
125
|
-
for (const root of roots) {
|
|
126
|
-
writer.addRoot(root);
|
|
127
|
-
}
|
|
128
|
-
return writer;
|
|
129
|
-
};
|
package/esm/lib/decoder.js
DELETED
|
@@ -1,265 +0,0 @@
|
|
|
1
|
-
import varint from 'varint';
|
|
2
|
-
import { CID } from 'multiformats/cid';
|
|
3
|
-
import * as Digest from 'multiformats/hashes/digest';
|
|
4
|
-
import { decode as decodeDagCbor } from '@ipld/dag-cbor';
|
|
5
|
-
import { CarHeader as headerValidator } from './header-validator.js';
|
|
6
|
-
const CIDV0_BYTES = {
|
|
7
|
-
SHA2_256: 18,
|
|
8
|
-
LENGTH: 32,
|
|
9
|
-
DAG_PB: 112
|
|
10
|
-
};
|
|
11
|
-
const V2_HEADER_LENGTH = 16 + 8 + 8 + 8;
|
|
12
|
-
async function readVarint(reader) {
|
|
13
|
-
const bytes = await reader.upTo(8);
|
|
14
|
-
if (!bytes.length) {
|
|
15
|
-
throw new Error('Unexpected end of data');
|
|
16
|
-
}
|
|
17
|
-
const i = varint.decode(bytes);
|
|
18
|
-
reader.seek(varint.decode.bytes);
|
|
19
|
-
return i;
|
|
20
|
-
}
|
|
21
|
-
async function readV2Header(reader) {
|
|
22
|
-
const bytes = await reader.exactly(V2_HEADER_LENGTH);
|
|
23
|
-
const dv = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
|
|
24
|
-
let offset = 0;
|
|
25
|
-
const header = {
|
|
26
|
-
version: 2,
|
|
27
|
-
characteristics: [
|
|
28
|
-
dv.getBigUint64(offset, true),
|
|
29
|
-
dv.getBigUint64(offset += 8, true)
|
|
30
|
-
],
|
|
31
|
-
dataOffset: Number(dv.getBigUint64(offset += 8, true)),
|
|
32
|
-
dataSize: Number(dv.getBigUint64(offset += 8, true)),
|
|
33
|
-
indexOffset: Number(dv.getBigUint64(offset += 8, true))
|
|
34
|
-
};
|
|
35
|
-
reader.seek(V2_HEADER_LENGTH);
|
|
36
|
-
return header;
|
|
37
|
-
}
|
|
38
|
-
export async function readHeader(reader, strictVersion) {
|
|
39
|
-
const length = await readVarint(reader);
|
|
40
|
-
if (length === 0) {
|
|
41
|
-
throw new Error('Invalid CAR header (zero length)');
|
|
42
|
-
}
|
|
43
|
-
const header = await reader.exactly(length);
|
|
44
|
-
reader.seek(length);
|
|
45
|
-
const block = decodeDagCbor(header);
|
|
46
|
-
if (!headerValidator(block)) {
|
|
47
|
-
throw new Error('Invalid CAR header format');
|
|
48
|
-
}
|
|
49
|
-
if (block.version !== 1 && block.version !== 2 || strictVersion !== undefined && block.version !== strictVersion) {
|
|
50
|
-
throw new Error(`Invalid CAR version: ${ block.version }${ strictVersion !== undefined ? ` (expected ${ strictVersion })` : '' }`);
|
|
51
|
-
}
|
|
52
|
-
const hasRoots = Array.isArray(block.roots);
|
|
53
|
-
if (block.version === 1 && !hasRoots || block.version === 2 && hasRoots) {
|
|
54
|
-
throw new Error('Invalid CAR header format');
|
|
55
|
-
}
|
|
56
|
-
if (block.version === 1) {
|
|
57
|
-
return block;
|
|
58
|
-
}
|
|
59
|
-
const v2Header = await readV2Header(reader);
|
|
60
|
-
reader.seek(v2Header.dataOffset - reader.pos);
|
|
61
|
-
const v1Header = await readHeader(reader, 1);
|
|
62
|
-
return Object.assign(v1Header, v2Header);
|
|
63
|
-
}
|
|
64
|
-
async function readMultihash(reader) {
|
|
65
|
-
const bytes = await reader.upTo(8);
|
|
66
|
-
varint.decode(bytes);
|
|
67
|
-
const codeLength = varint.decode.bytes;
|
|
68
|
-
const length = varint.decode(bytes.subarray(varint.decode.bytes));
|
|
69
|
-
const lengthLength = varint.decode.bytes;
|
|
70
|
-
const mhLength = codeLength + lengthLength + length;
|
|
71
|
-
const multihash = await reader.exactly(mhLength);
|
|
72
|
-
reader.seek(mhLength);
|
|
73
|
-
return multihash;
|
|
74
|
-
}
|
|
75
|
-
async function readCid(reader) {
|
|
76
|
-
const first = await reader.exactly(2);
|
|
77
|
-
if (first[0] === CIDV0_BYTES.SHA2_256 && first[1] === CIDV0_BYTES.LENGTH) {
|
|
78
|
-
const bytes = await reader.exactly(34);
|
|
79
|
-
reader.seek(34);
|
|
80
|
-
const multihash = Digest.decode(bytes);
|
|
81
|
-
return CID.create(0, CIDV0_BYTES.DAG_PB, multihash);
|
|
82
|
-
}
|
|
83
|
-
const version = await readVarint(reader);
|
|
84
|
-
if (version !== 1) {
|
|
85
|
-
throw new Error(`Unexpected CID version (${ version })`);
|
|
86
|
-
}
|
|
87
|
-
const codec = await readVarint(reader);
|
|
88
|
-
const bytes = await readMultihash(reader);
|
|
89
|
-
const multihash = Digest.decode(bytes);
|
|
90
|
-
return CID.create(version, codec, multihash);
|
|
91
|
-
}
|
|
92
|
-
export async function readBlockHead(reader) {
|
|
93
|
-
const start = reader.pos;
|
|
94
|
-
let length = await readVarint(reader);
|
|
95
|
-
if (length === 0) {
|
|
96
|
-
throw new Error('Invalid CAR section (zero length)');
|
|
97
|
-
}
|
|
98
|
-
length += reader.pos - start;
|
|
99
|
-
const cid = await readCid(reader);
|
|
100
|
-
const blockLength = length - Number(reader.pos - start);
|
|
101
|
-
return {
|
|
102
|
-
cid,
|
|
103
|
-
length,
|
|
104
|
-
blockLength
|
|
105
|
-
};
|
|
106
|
-
}
|
|
107
|
-
async function readBlock(reader) {
|
|
108
|
-
const {cid, blockLength} = await readBlockHead(reader);
|
|
109
|
-
const bytes = await reader.exactly(blockLength);
|
|
110
|
-
reader.seek(blockLength);
|
|
111
|
-
return {
|
|
112
|
-
bytes,
|
|
113
|
-
cid
|
|
114
|
-
};
|
|
115
|
-
}
|
|
116
|
-
async function readBlockIndex(reader) {
|
|
117
|
-
const offset = reader.pos;
|
|
118
|
-
const {cid, length, blockLength} = await readBlockHead(reader);
|
|
119
|
-
const index = {
|
|
120
|
-
cid,
|
|
121
|
-
length,
|
|
122
|
-
blockLength,
|
|
123
|
-
offset,
|
|
124
|
-
blockOffset: reader.pos
|
|
125
|
-
};
|
|
126
|
-
reader.seek(index.blockLength);
|
|
127
|
-
return index;
|
|
128
|
-
}
|
|
129
|
-
export function createDecoder(reader) {
|
|
130
|
-
const headerPromise = (async () => {
|
|
131
|
-
const header = await readHeader(reader);
|
|
132
|
-
if (header.version === 2) {
|
|
133
|
-
const v1length = reader.pos - header.dataOffset;
|
|
134
|
-
reader = limitReader(reader, header.dataSize - v1length);
|
|
135
|
-
}
|
|
136
|
-
return header;
|
|
137
|
-
})();
|
|
138
|
-
return {
|
|
139
|
-
header: () => headerPromise,
|
|
140
|
-
async *blocks() {
|
|
141
|
-
await headerPromise;
|
|
142
|
-
while ((await reader.upTo(8)).length > 0) {
|
|
143
|
-
yield await readBlock(reader);
|
|
144
|
-
}
|
|
145
|
-
},
|
|
146
|
-
async *blocksIndex() {
|
|
147
|
-
await headerPromise;
|
|
148
|
-
while ((await reader.upTo(8)).length > 0) {
|
|
149
|
-
yield await readBlockIndex(reader);
|
|
150
|
-
}
|
|
151
|
-
}
|
|
152
|
-
};
|
|
153
|
-
}
|
|
154
|
-
export function bytesReader(bytes) {
|
|
155
|
-
let pos = 0;
|
|
156
|
-
return {
|
|
157
|
-
async upTo(length) {
|
|
158
|
-
return bytes.subarray(pos, pos + Math.min(length, bytes.length - pos));
|
|
159
|
-
},
|
|
160
|
-
async exactly(length) {
|
|
161
|
-
if (length > bytes.length - pos) {
|
|
162
|
-
throw new Error('Unexpected end of data');
|
|
163
|
-
}
|
|
164
|
-
return bytes.subarray(pos, pos + length);
|
|
165
|
-
},
|
|
166
|
-
seek(length) {
|
|
167
|
-
pos += length;
|
|
168
|
-
},
|
|
169
|
-
get pos() {
|
|
170
|
-
return pos;
|
|
171
|
-
}
|
|
172
|
-
};
|
|
173
|
-
}
|
|
174
|
-
export function chunkReader(readChunk) {
|
|
175
|
-
let pos = 0;
|
|
176
|
-
let have = 0;
|
|
177
|
-
let offset = 0;
|
|
178
|
-
let currentChunk = new Uint8Array(0);
|
|
179
|
-
const read = async length => {
|
|
180
|
-
have = currentChunk.length - offset;
|
|
181
|
-
const bufa = [currentChunk.subarray(offset)];
|
|
182
|
-
while (have < length) {
|
|
183
|
-
const chunk = await readChunk();
|
|
184
|
-
if (chunk == null) {
|
|
185
|
-
break;
|
|
186
|
-
}
|
|
187
|
-
if (have < 0) {
|
|
188
|
-
if (chunk.length > have) {
|
|
189
|
-
bufa.push(chunk.subarray(-have));
|
|
190
|
-
}
|
|
191
|
-
} else {
|
|
192
|
-
bufa.push(chunk);
|
|
193
|
-
}
|
|
194
|
-
have += chunk.length;
|
|
195
|
-
}
|
|
196
|
-
currentChunk = new Uint8Array(bufa.reduce((p, c) => p + c.length, 0));
|
|
197
|
-
let off = 0;
|
|
198
|
-
for (const b of bufa) {
|
|
199
|
-
currentChunk.set(b, off);
|
|
200
|
-
off += b.length;
|
|
201
|
-
}
|
|
202
|
-
offset = 0;
|
|
203
|
-
};
|
|
204
|
-
return {
|
|
205
|
-
async upTo(length) {
|
|
206
|
-
if (currentChunk.length - offset < length) {
|
|
207
|
-
await read(length);
|
|
208
|
-
}
|
|
209
|
-
return currentChunk.subarray(offset, offset + Math.min(currentChunk.length - offset, length));
|
|
210
|
-
},
|
|
211
|
-
async exactly(length) {
|
|
212
|
-
if (currentChunk.length - offset < length) {
|
|
213
|
-
await read(length);
|
|
214
|
-
}
|
|
215
|
-
if (currentChunk.length - offset < length) {
|
|
216
|
-
throw new Error('Unexpected end of data');
|
|
217
|
-
}
|
|
218
|
-
return currentChunk.subarray(offset, offset + length);
|
|
219
|
-
},
|
|
220
|
-
seek(length) {
|
|
221
|
-
pos += length;
|
|
222
|
-
offset += length;
|
|
223
|
-
},
|
|
224
|
-
get pos() {
|
|
225
|
-
return pos;
|
|
226
|
-
}
|
|
227
|
-
};
|
|
228
|
-
}
|
|
229
|
-
export function asyncIterableReader(asyncIterable) {
|
|
230
|
-
const iterator = asyncIterable[Symbol.asyncIterator]();
|
|
231
|
-
async function readChunk() {
|
|
232
|
-
const next = await iterator.next();
|
|
233
|
-
if (next.done) {
|
|
234
|
-
return null;
|
|
235
|
-
}
|
|
236
|
-
return next.value;
|
|
237
|
-
}
|
|
238
|
-
return chunkReader(readChunk);
|
|
239
|
-
}
|
|
240
|
-
export function limitReader(reader, byteLimit) {
|
|
241
|
-
let bytesRead = 0;
|
|
242
|
-
return {
|
|
243
|
-
async upTo(length) {
|
|
244
|
-
let bytes = await reader.upTo(length);
|
|
245
|
-
if (bytes.length + bytesRead > byteLimit) {
|
|
246
|
-
bytes = bytes.subarray(0, byteLimit - bytesRead);
|
|
247
|
-
}
|
|
248
|
-
return bytes;
|
|
249
|
-
},
|
|
250
|
-
async exactly(length) {
|
|
251
|
-
const bytes = await reader.exactly(length);
|
|
252
|
-
if (bytes.length + bytesRead > byteLimit) {
|
|
253
|
-
throw new Error('Unexpected end of data');
|
|
254
|
-
}
|
|
255
|
-
return bytes;
|
|
256
|
-
},
|
|
257
|
-
seek(length) {
|
|
258
|
-
bytesRead += length;
|
|
259
|
-
reader.seek(length);
|
|
260
|
-
},
|
|
261
|
-
get pos() {
|
|
262
|
-
return reader.pos;
|
|
263
|
-
}
|
|
264
|
-
};
|
|
265
|
-
}
|
package/esm/lib/encoder.js
DELETED
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
import varint from 'varint';
|
|
2
|
-
import { encode as dagCborEncode } from '@ipld/dag-cbor';
|
|
3
|
-
export function createHeader(roots) {
|
|
4
|
-
const headerBytes = dagCborEncode({
|
|
5
|
-
version: 1,
|
|
6
|
-
roots
|
|
7
|
-
});
|
|
8
|
-
const varintBytes = varint.encode(headerBytes.length);
|
|
9
|
-
const header = new Uint8Array(varintBytes.length + headerBytes.length);
|
|
10
|
-
header.set(varintBytes, 0);
|
|
11
|
-
header.set(headerBytes, varintBytes.length);
|
|
12
|
-
return header;
|
|
13
|
-
}
|
|
14
|
-
function createEncoder(writer) {
|
|
15
|
-
return {
|
|
16
|
-
async setRoots(roots) {
|
|
17
|
-
const bytes = createHeader(roots);
|
|
18
|
-
await writer.write(bytes);
|
|
19
|
-
},
|
|
20
|
-
async writeBlock(block) {
|
|
21
|
-
const {cid, bytes} = block;
|
|
22
|
-
await writer.write(new Uint8Array(varint.encode(cid.bytes.length + bytes.length)));
|
|
23
|
-
await writer.write(cid.bytes);
|
|
24
|
-
if (bytes.length) {
|
|
25
|
-
await writer.write(bytes);
|
|
26
|
-
}
|
|
27
|
-
},
|
|
28
|
-
async close() {
|
|
29
|
-
await writer.end();
|
|
30
|
-
}
|
|
31
|
-
};
|
|
32
|
-
}
|
|
33
|
-
export {
|
|
34
|
-
createEncoder
|
|
35
|
-
};
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
const Kinds = {
|
|
2
|
-
Null: obj => obj === null,
|
|
3
|
-
Int: obj => Number.isInteger(obj),
|
|
4
|
-
Float: obj => typeof obj === 'number' && Number.isFinite(obj),
|
|
5
|
-
String: obj => typeof obj === 'string',
|
|
6
|
-
Bool: obj => typeof obj === 'boolean',
|
|
7
|
-
Bytes: obj => obj instanceof Uint8Array,
|
|
8
|
-
Link: obj => !Kinds.Null(obj) && typeof obj === 'object' && obj.asCID === obj,
|
|
9
|
-
List: obj => Array.isArray(obj),
|
|
10
|
-
Map: obj => !Kinds.Null(obj) && typeof obj === 'object' && obj.asCID !== obj && !Kinds.List(obj) && !Kinds.Bytes(obj)
|
|
11
|
-
};
|
|
12
|
-
const Types = {
|
|
13
|
-
Int: Kinds.Int,
|
|
14
|
-
'CarHeader > version': obj => Types.Int(obj),
|
|
15
|
-
'CarHeader > roots (anon) > valueType (anon)': Kinds.Link,
|
|
16
|
-
'CarHeader > roots (anon)': obj => Kinds.List(obj) && Array.prototype.every.call(obj, Types['CarHeader > roots (anon) > valueType (anon)']),
|
|
17
|
-
'CarHeader > roots': obj => Types['CarHeader > roots (anon)'](obj),
|
|
18
|
-
CarHeader: obj => {
|
|
19
|
-
const keys = obj && Object.keys(obj);
|
|
20
|
-
return Kinds.Map(obj) && ['version'].every(k => keys.includes(k)) && Object.entries(obj).every(([name, value]) => Types['CarHeader > ' + name] && Types['CarHeader > ' + name](value));
|
|
21
|
-
}
|
|
22
|
-
};
|
|
23
|
-
export const CarHeader = Types.CarHeader;
|
|
@@ -1,78 +0,0 @@
|
|
|
1
|
-
import fs from 'fs';
|
|
2
|
-
import { Readable } from 'stream';
|
|
3
|
-
import { CID } from 'multiformats/cid';
|
|
4
|
-
import { CarIndexer } from './indexer.js';
|
|
5
|
-
import { CarReader as NodeCarReader } from './reader.js';
|
|
6
|
-
export class CarIndexedReader {
|
|
7
|
-
constructor(version, path, roots, index, order) {
|
|
8
|
-
this._version = version;
|
|
9
|
-
this._path = path;
|
|
10
|
-
this._roots = roots;
|
|
11
|
-
this._index = index;
|
|
12
|
-
this._order = order;
|
|
13
|
-
this._fd = null;
|
|
14
|
-
}
|
|
15
|
-
get version() {
|
|
16
|
-
return this._version;
|
|
17
|
-
}
|
|
18
|
-
async getRoots() {
|
|
19
|
-
return this._roots;
|
|
20
|
-
}
|
|
21
|
-
async has(key) {
|
|
22
|
-
return this._index.has(key.toString());
|
|
23
|
-
}
|
|
24
|
-
async get(key) {
|
|
25
|
-
const blockIndex = this._index.get(key.toString());
|
|
26
|
-
if (!blockIndex) {
|
|
27
|
-
return undefined;
|
|
28
|
-
}
|
|
29
|
-
if (!this._fd) {
|
|
30
|
-
this._fd = await fs.promises.open(this._path, 'r');
|
|
31
|
-
}
|
|
32
|
-
const readIndex = {
|
|
33
|
-
cid: key,
|
|
34
|
-
length: 0,
|
|
35
|
-
offset: 0,
|
|
36
|
-
blockLength: blockIndex.blockLength,
|
|
37
|
-
blockOffset: blockIndex.blockOffset
|
|
38
|
-
};
|
|
39
|
-
return NodeCarReader.readRaw(this._fd, readIndex);
|
|
40
|
-
}
|
|
41
|
-
async *blocks() {
|
|
42
|
-
for (const cidStr of this._order) {
|
|
43
|
-
const block = await this.get(CID.parse(cidStr));
|
|
44
|
-
if (!block) {
|
|
45
|
-
throw new Error('Unexpected internal error');
|
|
46
|
-
}
|
|
47
|
-
yield block;
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
async *cids() {
|
|
51
|
-
for (const cidStr of this._order) {
|
|
52
|
-
yield CID.parse(cidStr);
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
async close() {
|
|
56
|
-
if (this._fd) {
|
|
57
|
-
return this._fd.close();
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
static async fromFile(path) {
|
|
61
|
-
if (typeof path !== 'string') {
|
|
62
|
-
throw new TypeError('fromFile() requires a file path string');
|
|
63
|
-
}
|
|
64
|
-
const iterable = await CarIndexer.fromIterable(Readable.from(fs.createReadStream(path)));
|
|
65
|
-
const index = new Map();
|
|
66
|
-
const order = [];
|
|
67
|
-
for await (const {cid, blockLength, blockOffset} of iterable) {
|
|
68
|
-
const cidStr = cid.toString();
|
|
69
|
-
index.set(cidStr, {
|
|
70
|
-
blockLength,
|
|
71
|
-
blockOffset
|
|
72
|
-
});
|
|
73
|
-
order.push(cidStr);
|
|
74
|
-
}
|
|
75
|
-
return new CarIndexedReader(iterable.version, path, await iterable.getRoots(), index, order);
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
export const __browser = false;
|
package/esm/lib/indexer.js
DELETED
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
asyncIterableReader,
|
|
3
|
-
bytesReader,
|
|
4
|
-
createDecoder
|
|
5
|
-
} from './decoder.js';
|
|
6
|
-
export class CarIndexer {
|
|
7
|
-
constructor(version, roots, iterator) {
|
|
8
|
-
this._version = version;
|
|
9
|
-
this._roots = roots;
|
|
10
|
-
this._iterator = iterator;
|
|
11
|
-
}
|
|
12
|
-
get version() {
|
|
13
|
-
return this._version;
|
|
14
|
-
}
|
|
15
|
-
async getRoots() {
|
|
16
|
-
return this._roots;
|
|
17
|
-
}
|
|
18
|
-
[Symbol.asyncIterator]() {
|
|
19
|
-
return this._iterator;
|
|
20
|
-
}
|
|
21
|
-
static async fromBytes(bytes) {
|
|
22
|
-
if (!(bytes instanceof Uint8Array)) {
|
|
23
|
-
throw new TypeError('fromBytes() requires a Uint8Array');
|
|
24
|
-
}
|
|
25
|
-
return decodeIndexerComplete(bytesReader(bytes));
|
|
26
|
-
}
|
|
27
|
-
static async fromIterable(asyncIterable) {
|
|
28
|
-
if (!asyncIterable || !(typeof asyncIterable[Symbol.asyncIterator] === 'function')) {
|
|
29
|
-
throw new TypeError('fromIterable() requires an async iterable');
|
|
30
|
-
}
|
|
31
|
-
return decodeIndexerComplete(asyncIterableReader(asyncIterable));
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
async function decodeIndexerComplete(reader) {
|
|
35
|
-
const decoder = createDecoder(reader);
|
|
36
|
-
const {version, roots} = await decoder.header();
|
|
37
|
-
return new CarIndexer(version, roots, decoder.blocksIndex());
|
|
38
|
-
}
|
|
@@ -1,71 +0,0 @@
|
|
|
1
|
-
function noop() {
|
|
2
|
-
}
|
|
3
|
-
export function create() {
|
|
4
|
-
const chunkQueue = [];
|
|
5
|
-
let drainer = null;
|
|
6
|
-
let drainerResolver = noop;
|
|
7
|
-
let ended = false;
|
|
8
|
-
let outWait = null;
|
|
9
|
-
let outWaitResolver = noop;
|
|
10
|
-
const makeDrainer = () => {
|
|
11
|
-
if (!drainer) {
|
|
12
|
-
drainer = new Promise(resolve => {
|
|
13
|
-
drainerResolver = () => {
|
|
14
|
-
drainer = null;
|
|
15
|
-
drainerResolver = noop;
|
|
16
|
-
resolve();
|
|
17
|
-
};
|
|
18
|
-
});
|
|
19
|
-
}
|
|
20
|
-
return drainer;
|
|
21
|
-
};
|
|
22
|
-
const writer = {
|
|
23
|
-
write(chunk) {
|
|
24
|
-
chunkQueue.push(chunk);
|
|
25
|
-
const drainer = makeDrainer();
|
|
26
|
-
outWaitResolver();
|
|
27
|
-
return drainer;
|
|
28
|
-
},
|
|
29
|
-
async end() {
|
|
30
|
-
ended = true;
|
|
31
|
-
const drainer = makeDrainer();
|
|
32
|
-
outWaitResolver();
|
|
33
|
-
await drainer;
|
|
34
|
-
}
|
|
35
|
-
};
|
|
36
|
-
const iterator = {
|
|
37
|
-
async next() {
|
|
38
|
-
const chunk = chunkQueue.shift();
|
|
39
|
-
if (chunk) {
|
|
40
|
-
if (chunkQueue.length === 0) {
|
|
41
|
-
drainerResolver();
|
|
42
|
-
}
|
|
43
|
-
return {
|
|
44
|
-
done: false,
|
|
45
|
-
value: chunk
|
|
46
|
-
};
|
|
47
|
-
}
|
|
48
|
-
if (ended) {
|
|
49
|
-
drainerResolver();
|
|
50
|
-
return {
|
|
51
|
-
done: true,
|
|
52
|
-
value: undefined
|
|
53
|
-
};
|
|
54
|
-
}
|
|
55
|
-
if (!outWait) {
|
|
56
|
-
outWait = new Promise(resolve => {
|
|
57
|
-
outWaitResolver = () => {
|
|
58
|
-
outWait = null;
|
|
59
|
-
outWaitResolver = noop;
|
|
60
|
-
return resolve(iterator.next());
|
|
61
|
-
};
|
|
62
|
-
});
|
|
63
|
-
}
|
|
64
|
-
return outWait;
|
|
65
|
-
}
|
|
66
|
-
};
|
|
67
|
-
return {
|
|
68
|
-
writer,
|
|
69
|
-
iterator
|
|
70
|
-
};
|
|
71
|
-
}
|