@ipld/car 4.1.5 → 5.0.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/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 +4 -4
- 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
|
@@ -1,270 +0,0 @@
|
|
|
1
|
-
import { CarReader } from '../lib/reader-browser.js';
|
|
2
|
-
import { CarWriter } from '../lib/writer-browser.js';
|
|
3
|
-
import {
|
|
4
|
-
bytesReader,
|
|
5
|
-
readHeader
|
|
6
|
-
} from '../lib/decoder.js';
|
|
7
|
-
import * as Block from 'multiformats/block';
|
|
8
|
-
import { sha256 } from 'multiformats/hashes/sha2';
|
|
9
|
-
import * as raw from 'multiformats/codecs/raw';
|
|
10
|
-
import { base64 } from 'multiformats/bases/base64';
|
|
11
|
-
import * as dagPb from '@ipld/dag-pb';
|
|
12
|
-
import {
|
|
13
|
-
carBytes,
|
|
14
|
-
makeIterable,
|
|
15
|
-
assert,
|
|
16
|
-
goCarV2Bytes,
|
|
17
|
-
goCarV2Roots,
|
|
18
|
-
goCarV2Index,
|
|
19
|
-
goCarV2Contents
|
|
20
|
-
} from './common.js';
|
|
21
|
-
import {
|
|
22
|
-
verifyRoots,
|
|
23
|
-
verifyHas,
|
|
24
|
-
verifyGet,
|
|
25
|
-
verifyBlocks,
|
|
26
|
-
verifyCids
|
|
27
|
-
} from './verify-store-reader.js';
|
|
28
|
-
import { data as fixtures } from './fixtures.js';
|
|
29
|
-
import { expectations as fixtureExpectations } from './fixtures-expectations.js';
|
|
30
|
-
describe('CarReader fromBytes()', () => {
|
|
31
|
-
it('complete', async () => {
|
|
32
|
-
const reader = await CarReader.fromBytes(carBytes);
|
|
33
|
-
await verifyRoots(reader);
|
|
34
|
-
await verifyHas(reader);
|
|
35
|
-
await verifyGet(reader);
|
|
36
|
-
await verifyBlocks(reader.blocks());
|
|
37
|
-
await verifyCids(reader.cids());
|
|
38
|
-
assert.strictEqual(reader.version, 1);
|
|
39
|
-
});
|
|
40
|
-
it('complete (get before has) switch', async () => {
|
|
41
|
-
const reader = await CarReader.fromBytes(carBytes);
|
|
42
|
-
await verifyRoots(reader);
|
|
43
|
-
await verifyGet(reader);
|
|
44
|
-
await verifyHas(reader);
|
|
45
|
-
await verifyBlocks(reader.blocks());
|
|
46
|
-
await verifyCids(reader.cids());
|
|
47
|
-
});
|
|
48
|
-
it('bad argument', async () => {
|
|
49
|
-
for (const arg of [
|
|
50
|
-
true,
|
|
51
|
-
false,
|
|
52
|
-
null,
|
|
53
|
-
undefined,
|
|
54
|
-
'string',
|
|
55
|
-
100,
|
|
56
|
-
{ obj: 'nope' }
|
|
57
|
-
]) {
|
|
58
|
-
await assert.isRejected(CarReader.fromBytes(arg));
|
|
59
|
-
}
|
|
60
|
-
});
|
|
61
|
-
it('decode error - truncated', async () => {
|
|
62
|
-
await assert.isRejected(CarReader.fromBytes(carBytes.slice(0, carBytes.length - 10)), {
|
|
63
|
-
name: 'Error',
|
|
64
|
-
message: 'Unexpected end of data'
|
|
65
|
-
});
|
|
66
|
-
});
|
|
67
|
-
it('v2 complete', async () => {
|
|
68
|
-
const reader = await CarReader.fromBytes(goCarV2Bytes);
|
|
69
|
-
const roots = await reader.getRoots();
|
|
70
|
-
assert.strictEqual(roots.length, 1);
|
|
71
|
-
assert.ok(goCarV2Roots[0].equals(roots[0]));
|
|
72
|
-
assert.strictEqual(reader.version, 2);
|
|
73
|
-
for (const {cid} of goCarV2Index) {
|
|
74
|
-
const block = await reader.get(cid);
|
|
75
|
-
assert.isDefined(block);
|
|
76
|
-
if (block) {
|
|
77
|
-
assert.ok(cid.equals(block.cid));
|
|
78
|
-
let content;
|
|
79
|
-
if (cid.code === dagPb.code) {
|
|
80
|
-
content = dagPb.decode(block.bytes);
|
|
81
|
-
} else if (cid.code === 85) {
|
|
82
|
-
content = new TextDecoder().decode(block.bytes);
|
|
83
|
-
} else {
|
|
84
|
-
assert.fail('Unexpected codec');
|
|
85
|
-
}
|
|
86
|
-
assert.deepStrictEqual(content, goCarV2Contents[cid.toString()]);
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
});
|
|
90
|
-
it('decode error - trailing null bytes', async () => {
|
|
91
|
-
const bytes = new Uint8Array(carBytes.length + 5);
|
|
92
|
-
bytes.set(carBytes);
|
|
93
|
-
try {
|
|
94
|
-
await CarReader.fromBytes(bytes);
|
|
95
|
-
} catch (err) {
|
|
96
|
-
assert.strictEqual(err.message, 'Invalid CAR section (zero length)');
|
|
97
|
-
return;
|
|
98
|
-
}
|
|
99
|
-
assert.fail('Did not throw');
|
|
100
|
-
});
|
|
101
|
-
it('decode error - bad first byte', async () => {
|
|
102
|
-
const bytes = new Uint8Array(carBytes.length + 5);
|
|
103
|
-
bytes.set(carBytes);
|
|
104
|
-
bytes[0] = 0;
|
|
105
|
-
try {
|
|
106
|
-
await CarReader.fromBytes(bytes);
|
|
107
|
-
} catch (err) {
|
|
108
|
-
assert.strictEqual(err.message, 'Invalid CAR header (zero length)');
|
|
109
|
-
return;
|
|
110
|
-
}
|
|
111
|
-
assert.fail('Did not throw');
|
|
112
|
-
});
|
|
113
|
-
});
|
|
114
|
-
describe('CarReader fromIterable()', () => {
|
|
115
|
-
it('complete (single chunk)', async () => {
|
|
116
|
-
const reader = await CarReader.fromIterable(makeIterable(carBytes, carBytes.length));
|
|
117
|
-
await verifyRoots(reader);
|
|
118
|
-
await verifyHas(reader);
|
|
119
|
-
await verifyGet(reader);
|
|
120
|
-
await verifyBlocks(reader.blocks());
|
|
121
|
-
await verifyCids(reader.cids());
|
|
122
|
-
});
|
|
123
|
-
it('complete (101-byte chunks)', async () => {
|
|
124
|
-
const reader = await CarReader.fromIterable(makeIterable(carBytes, 101));
|
|
125
|
-
await verifyRoots(reader);
|
|
126
|
-
await verifyHas(reader);
|
|
127
|
-
await verifyGet(reader);
|
|
128
|
-
await verifyBlocks(reader.blocks());
|
|
129
|
-
await verifyCids(reader.cids());
|
|
130
|
-
});
|
|
131
|
-
it('complete (64-byte chunks)', async () => {
|
|
132
|
-
const reader = await CarReader.fromIterable(makeIterable(carBytes, 64));
|
|
133
|
-
await verifyRoots(reader);
|
|
134
|
-
await verifyHas(reader);
|
|
135
|
-
await verifyGet(reader);
|
|
136
|
-
await verifyBlocks(reader.blocks());
|
|
137
|
-
await verifyCids(reader.cids());
|
|
138
|
-
});
|
|
139
|
-
it('complete (32-byte chunks)', async () => {
|
|
140
|
-
const reader = await CarReader.fromIterable(makeIterable(carBytes, 32));
|
|
141
|
-
await verifyRoots(reader);
|
|
142
|
-
await verifyHas(reader);
|
|
143
|
-
await verifyGet(reader);
|
|
144
|
-
await verifyBlocks(reader.blocks());
|
|
145
|
-
await verifyCids(reader.cids());
|
|
146
|
-
});
|
|
147
|
-
it('handle zero-byte chunks', async () => {
|
|
148
|
-
const {writer, out} = await CarWriter.create([]);
|
|
149
|
-
const b1 = await Block.encode({
|
|
150
|
-
value: Uint8Array.from([
|
|
151
|
-
0,
|
|
152
|
-
1,
|
|
153
|
-
2
|
|
154
|
-
]),
|
|
155
|
-
hasher: sha256,
|
|
156
|
-
codec: raw
|
|
157
|
-
});
|
|
158
|
-
writer.put(b1);
|
|
159
|
-
const b2 = await Block.encode({
|
|
160
|
-
value: Uint8Array.from([]),
|
|
161
|
-
hasher: sha256,
|
|
162
|
-
codec: raw
|
|
163
|
-
});
|
|
164
|
-
writer.put(b2);
|
|
165
|
-
const b3 = await Block.encode({
|
|
166
|
-
value: Uint8Array.from([
|
|
167
|
-
3,
|
|
168
|
-
4,
|
|
169
|
-
5
|
|
170
|
-
]),
|
|
171
|
-
hasher: sha256,
|
|
172
|
-
codec: raw
|
|
173
|
-
});
|
|
174
|
-
writer.put(b3);
|
|
175
|
-
const closePromise = writer.close();
|
|
176
|
-
const reader = await CarReader.fromIterable(out);
|
|
177
|
-
const b1a = await reader.get(b1.cid);
|
|
178
|
-
assert.isDefined(b1a);
|
|
179
|
-
assert.deepStrictEqual(b1a && Array.from(b1a.bytes), [
|
|
180
|
-
0,
|
|
181
|
-
1,
|
|
182
|
-
2
|
|
183
|
-
]);
|
|
184
|
-
const b2a = await reader.get(b2.cid);
|
|
185
|
-
assert.isDefined(b2a);
|
|
186
|
-
assert.deepStrictEqual(b2a && Array.from(b2a.bytes), []);
|
|
187
|
-
const b3a = await reader.get(b3.cid);
|
|
188
|
-
assert.isDefined(b3a);
|
|
189
|
-
assert.deepStrictEqual(b3a && Array.from(b3a.bytes), [
|
|
190
|
-
3,
|
|
191
|
-
4,
|
|
192
|
-
5
|
|
193
|
-
]);
|
|
194
|
-
await closePromise;
|
|
195
|
-
});
|
|
196
|
-
it('bad argument', async () => {
|
|
197
|
-
for (const arg of [
|
|
198
|
-
new Uint8Array(0),
|
|
199
|
-
true,
|
|
200
|
-
false,
|
|
201
|
-
null,
|
|
202
|
-
undefined,
|
|
203
|
-
'string',
|
|
204
|
-
100,
|
|
205
|
-
{ obj: 'nope' }
|
|
206
|
-
]) {
|
|
207
|
-
await assert.isRejected(CarReader.fromIterable(arg));
|
|
208
|
-
}
|
|
209
|
-
});
|
|
210
|
-
it('decode error - truncated', async () => {
|
|
211
|
-
await assert.isRejected(CarReader.fromIterable(makeIterable(carBytes.slice(0, carBytes.length - 10), 64)), {
|
|
212
|
-
name: 'Error',
|
|
213
|
-
message: 'Unexpected end of data'
|
|
214
|
-
});
|
|
215
|
-
});
|
|
216
|
-
it('v2 decode error - truncated', async () => {
|
|
217
|
-
const bytes = goCarV2Bytes.slice();
|
|
218
|
-
const dv = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
|
|
219
|
-
dv.setBigUint64(35, BigInt(448 - 10), true);
|
|
220
|
-
await assert.isRejected(CarReader.fromIterable(makeIterable(bytes, 64)), {
|
|
221
|
-
name: 'Error',
|
|
222
|
-
message: 'Unexpected end of data'
|
|
223
|
-
});
|
|
224
|
-
});
|
|
225
|
-
});
|
|
226
|
-
describe('Shared fixtures', () => {
|
|
227
|
-
describe('Header', () => {
|
|
228
|
-
for (const [name, {
|
|
229
|
-
version: expectedVersion,
|
|
230
|
-
err: expectedError
|
|
231
|
-
}] of Object.entries(fixtureExpectations)) {
|
|
232
|
-
it(name, async () => {
|
|
233
|
-
const data = base64.baseDecode(fixtures[name]);
|
|
234
|
-
let header;
|
|
235
|
-
try {
|
|
236
|
-
header = await readHeader(bytesReader(data));
|
|
237
|
-
} catch (err) {
|
|
238
|
-
if (expectedError != null) {
|
|
239
|
-
assert.equal(err.message, expectedError);
|
|
240
|
-
return;
|
|
241
|
-
}
|
|
242
|
-
assert.ifError(err);
|
|
243
|
-
}
|
|
244
|
-
if (expectedError != null) {
|
|
245
|
-
assert.fail(`Expected error: ${ expectedError }`);
|
|
246
|
-
}
|
|
247
|
-
assert.isDefined(header, 'did not decode header');
|
|
248
|
-
if (expectedVersion != null && header != null) {
|
|
249
|
-
assert.strictEqual(header.version, expectedVersion);
|
|
250
|
-
}
|
|
251
|
-
});
|
|
252
|
-
}
|
|
253
|
-
});
|
|
254
|
-
describe('Contents', () => {
|
|
255
|
-
for (const [name, {cids: expectedCids}] of Object.entries(fixtureExpectations)) {
|
|
256
|
-
if (expectedCids == null) {
|
|
257
|
-
continue;
|
|
258
|
-
}
|
|
259
|
-
it(name, async () => {
|
|
260
|
-
const data = base64.baseDecode(fixtures[name]);
|
|
261
|
-
const reader = await CarReader.fromBytes(data);
|
|
262
|
-
let i = 0;
|
|
263
|
-
for await (const cid of reader.cids()) {
|
|
264
|
-
assert.strictEqual(cid.toString(), expectedCids[i++]);
|
|
265
|
-
}
|
|
266
|
-
assert.strictEqual(i, expectedCids.length);
|
|
267
|
-
});
|
|
268
|
-
}
|
|
269
|
-
});
|
|
270
|
-
});
|
|
@@ -1,297 +0,0 @@
|
|
|
1
|
-
import { CarWriter } from '../lib/writer-browser.js';
|
|
2
|
-
import { CarReader } from '../lib/reader-browser.js';
|
|
3
|
-
import {
|
|
4
|
-
bytes,
|
|
5
|
-
CID
|
|
6
|
-
} from 'multiformats';
|
|
7
|
-
import {
|
|
8
|
-
carBytes,
|
|
9
|
-
makeData,
|
|
10
|
-
assert,
|
|
11
|
-
rndCid
|
|
12
|
-
} from './common.js';
|
|
13
|
-
import {
|
|
14
|
-
verifyRoots,
|
|
15
|
-
verifyHas,
|
|
16
|
-
verifyGet,
|
|
17
|
-
verifyBlocks,
|
|
18
|
-
verifyCids
|
|
19
|
-
} from './verify-store-reader.js';
|
|
20
|
-
const {toHex} = bytes;
|
|
21
|
-
function concatBytes(chunks) {
|
|
22
|
-
const length = chunks.reduce((p, c) => p + c.length, 0);
|
|
23
|
-
const bytes = new Uint8Array(length);
|
|
24
|
-
let off = 0;
|
|
25
|
-
for (const chunk of chunks) {
|
|
26
|
-
bytes.set(chunk, off);
|
|
27
|
-
off += chunk.length;
|
|
28
|
-
}
|
|
29
|
-
return bytes;
|
|
30
|
-
}
|
|
31
|
-
function collector(iterable) {
|
|
32
|
-
const chunks = [];
|
|
33
|
-
const cfn = (async () => {
|
|
34
|
-
for await (const chunk of iterable) {
|
|
35
|
-
chunks.push(chunk);
|
|
36
|
-
}
|
|
37
|
-
return concatBytes(chunks);
|
|
38
|
-
})();
|
|
39
|
-
return cfn;
|
|
40
|
-
}
|
|
41
|
-
const newRoots = [
|
|
42
|
-
CID.parse('bafkreidbxzk2ryxwwtqxem4l3xyyjvw35yu4tcct4cqeqxwo47zhxgxqwq'),
|
|
43
|
-
CID.parse('bafkreiebzrnroamgos2adnbpgw5apo3z4iishhbdx77gldnbk57d4zdio4')
|
|
44
|
-
];
|
|
45
|
-
async function verifyUpdateRoots(bytes) {
|
|
46
|
-
const reader = await CarReader.fromBytes(bytes);
|
|
47
|
-
await assert.isRejected(verifyRoots(reader));
|
|
48
|
-
assert.deepEqual(await reader.getRoots(), newRoots);
|
|
49
|
-
await verifyHas(reader);
|
|
50
|
-
await verifyGet(reader);
|
|
51
|
-
await verifyBlocks(reader.blocks(), true);
|
|
52
|
-
await verifyCids(reader.cids(), true);
|
|
53
|
-
}
|
|
54
|
-
describe('CarWriter', () => {
|
|
55
|
-
let cborBlocks;
|
|
56
|
-
let allBlocks;
|
|
57
|
-
let allBlocksFlattened;
|
|
58
|
-
let roots;
|
|
59
|
-
function assertCarData(actual) {
|
|
60
|
-
assert.strictEqual(toHex(actual), toHex(carBytes), 'got expected bytes');
|
|
61
|
-
}
|
|
62
|
-
before(async () => {
|
|
63
|
-
const data = await makeData();
|
|
64
|
-
cborBlocks = data.cborBlocks;
|
|
65
|
-
allBlocks = data.allBlocks;
|
|
66
|
-
allBlocksFlattened = data.allBlocksFlattened;
|
|
67
|
-
roots = [
|
|
68
|
-
cborBlocks[0].cid,
|
|
69
|
-
cborBlocks[1].cid
|
|
70
|
-
];
|
|
71
|
-
});
|
|
72
|
-
it('complete', async () => {
|
|
73
|
-
const {writer, out} = CarWriter.create(roots);
|
|
74
|
-
assert.strictEqual(typeof out[Symbol.asyncIterator], 'function');
|
|
75
|
-
const collection = collector(out);
|
|
76
|
-
const writeQueue = [];
|
|
77
|
-
for (const block of allBlocksFlattened) {
|
|
78
|
-
writeQueue.push(writer.put(block));
|
|
79
|
-
}
|
|
80
|
-
writeQueue.push(writer.close());
|
|
81
|
-
let collected = false;
|
|
82
|
-
collection.then(bytes => {
|
|
83
|
-
collected = true;
|
|
84
|
-
assertCarData(bytes);
|
|
85
|
-
});
|
|
86
|
-
await Promise.all(writeQueue);
|
|
87
|
-
assert.strictEqual(collected, true);
|
|
88
|
-
});
|
|
89
|
-
it('complete, deferred collection', async () => {
|
|
90
|
-
const {writer, out} = CarWriter.create(roots);
|
|
91
|
-
const writeQueue = [];
|
|
92
|
-
for (const block of allBlocksFlattened) {
|
|
93
|
-
writeQueue.push(writer.put(block));
|
|
94
|
-
}
|
|
95
|
-
writeQueue.push(writer.close());
|
|
96
|
-
let collected = false;
|
|
97
|
-
collector(out).then(bytes => {
|
|
98
|
-
collected = true;
|
|
99
|
-
assertCarData(bytes);
|
|
100
|
-
});
|
|
101
|
-
await Promise.all(writeQueue);
|
|
102
|
-
assert.strictEqual(collected, true);
|
|
103
|
-
});
|
|
104
|
-
it('complete, close after write', async () => {
|
|
105
|
-
const {writer, out} = CarWriter.create(roots);
|
|
106
|
-
assert.strictEqual(typeof out[Symbol.asyncIterator], 'function');
|
|
107
|
-
const collection = collector(out);
|
|
108
|
-
const writeQueue = [];
|
|
109
|
-
for (const block of allBlocksFlattened) {
|
|
110
|
-
writeQueue.push(writer.put(block));
|
|
111
|
-
}
|
|
112
|
-
writeQueue.push(writer.close());
|
|
113
|
-
let written = false;
|
|
114
|
-
Promise.all(writeQueue).then(() => {
|
|
115
|
-
written = true;
|
|
116
|
-
});
|
|
117
|
-
const bytes = await collection;
|
|
118
|
-
assert.strictEqual(written, false);
|
|
119
|
-
await Promise.resolve();
|
|
120
|
-
assertCarData(bytes);
|
|
121
|
-
});
|
|
122
|
-
it('complete, no queue', async () => {
|
|
123
|
-
const {writer, out} = CarWriter.create(roots);
|
|
124
|
-
const collection = collector(out);
|
|
125
|
-
for (const block of allBlocksFlattened) {
|
|
126
|
-
await writer.put(block);
|
|
127
|
-
}
|
|
128
|
-
await writer.close();
|
|
129
|
-
const bytes = await collection;
|
|
130
|
-
assertCarData(bytes);
|
|
131
|
-
});
|
|
132
|
-
it('complete, slow drip', async () => {
|
|
133
|
-
const {writer, out} = CarWriter.create(roots);
|
|
134
|
-
assert.strictEqual(typeof out[Symbol.asyncIterator], 'function');
|
|
135
|
-
const collection = collector(out);
|
|
136
|
-
for (const block of allBlocksFlattened) {
|
|
137
|
-
writer.put(block);
|
|
138
|
-
await new Promise(resolve => setTimeout(resolve, 100));
|
|
139
|
-
}
|
|
140
|
-
await writer.close();
|
|
141
|
-
await new Promise(resolve => setTimeout(resolve, 100));
|
|
142
|
-
const bytes = await collection;
|
|
143
|
-
assertCarData(bytes);
|
|
144
|
-
});
|
|
145
|
-
it('complete, no queue, deferred collection', async () => {
|
|
146
|
-
const {writer, out} = CarWriter.create(roots);
|
|
147
|
-
for (const block of allBlocksFlattened) {
|
|
148
|
-
writer.put(block);
|
|
149
|
-
}
|
|
150
|
-
writer.close();
|
|
151
|
-
const collection = collector(out);
|
|
152
|
-
const bytes = await collection;
|
|
153
|
-
assertCarData(bytes);
|
|
154
|
-
});
|
|
155
|
-
it('single root', async () => {
|
|
156
|
-
const {writer, out} = CarWriter.create(roots[0]);
|
|
157
|
-
const collection = collector(out);
|
|
158
|
-
for (const block of allBlocksFlattened) {
|
|
159
|
-
await writer.put(block);
|
|
160
|
-
}
|
|
161
|
-
await writer.close();
|
|
162
|
-
const bytes = await collection;
|
|
163
|
-
const expectedRootDef = 'a265726f6f747381d82a58250001711220f88bc853804cf294fe417e4fa83028689fcdb1b1592c5102e1474dbc200fab8b6776657273696f6e01';
|
|
164
|
-
const expectedStart = (expectedRootDef.length / 2).toString(16) + expectedRootDef + '28';
|
|
165
|
-
assert.strictEqual(toHex(bytes).substring(0, expectedStart.length), expectedStart);
|
|
166
|
-
});
|
|
167
|
-
it('no roots', async () => {
|
|
168
|
-
const {writer, out} = CarWriter.create();
|
|
169
|
-
const collection = collector(out);
|
|
170
|
-
for (const block of allBlocksFlattened) {
|
|
171
|
-
await writer.put(block);
|
|
172
|
-
}
|
|
173
|
-
await writer.close();
|
|
174
|
-
const bytes = await collection;
|
|
175
|
-
const expectedRootDef = 'a265726f6f7473806776657273696f6e01';
|
|
176
|
-
const expectedStart = (expectedRootDef.length / 2).toString(16) + expectedRootDef + '28';
|
|
177
|
-
assert.strictEqual(toHex(bytes).substring(0, expectedStart.length), expectedStart);
|
|
178
|
-
});
|
|
179
|
-
it('appender', async () => {
|
|
180
|
-
let writerOut = CarWriter.create(roots);
|
|
181
|
-
let collection = collector(writerOut.out);
|
|
182
|
-
await writerOut.writer.close();
|
|
183
|
-
const headerBytes = await collection;
|
|
184
|
-
const append = async index => {
|
|
185
|
-
writerOut = CarWriter.createAppender();
|
|
186
|
-
collection = collector(writerOut.out);
|
|
187
|
-
for (const block of allBlocks[index][1]) {
|
|
188
|
-
await writerOut.writer.put(block);
|
|
189
|
-
}
|
|
190
|
-
await writerOut.writer.close();
|
|
191
|
-
return collection;
|
|
192
|
-
};
|
|
193
|
-
const rawBytes = await append(0);
|
|
194
|
-
const pbBytes = await append(1);
|
|
195
|
-
const cborBytes = await append(2);
|
|
196
|
-
assert.ok(rawBytes.length > 0);
|
|
197
|
-
assert.ok(pbBytes.length > 0);
|
|
198
|
-
assert.ok(cborBytes.length > 0);
|
|
199
|
-
const reassembled = concatBytes([
|
|
200
|
-
headerBytes,
|
|
201
|
-
rawBytes,
|
|
202
|
-
pbBytes,
|
|
203
|
-
cborBytes
|
|
204
|
-
]);
|
|
205
|
-
assert.strictEqual(toHex(reassembled), toHex(carBytes));
|
|
206
|
-
});
|
|
207
|
-
it('bad argument for create()', () => {
|
|
208
|
-
for (const arg of [
|
|
209
|
-
new Uint8Array(0),
|
|
210
|
-
true,
|
|
211
|
-
false,
|
|
212
|
-
null,
|
|
213
|
-
'string',
|
|
214
|
-
100,
|
|
215
|
-
{ obj: 'nope' },
|
|
216
|
-
[false]
|
|
217
|
-
]) {
|
|
218
|
-
assert.throws(() => CarWriter.create(arg));
|
|
219
|
-
}
|
|
220
|
-
});
|
|
221
|
-
it('bad argument for put()', async () => {
|
|
222
|
-
const {writer} = CarWriter.create();
|
|
223
|
-
for (const arg of [
|
|
224
|
-
new Uint8Array(0),
|
|
225
|
-
true,
|
|
226
|
-
false,
|
|
227
|
-
null,
|
|
228
|
-
'string',
|
|
229
|
-
100,
|
|
230
|
-
{ obj: 'nope' },
|
|
231
|
-
[false]
|
|
232
|
-
]) {
|
|
233
|
-
await assert.isRejected(writer.put(arg));
|
|
234
|
-
}
|
|
235
|
-
for (const arg of [
|
|
236
|
-
true,
|
|
237
|
-
false,
|
|
238
|
-
null,
|
|
239
|
-
'string',
|
|
240
|
-
100,
|
|
241
|
-
{ obj: 'nope' },
|
|
242
|
-
[false]
|
|
243
|
-
]) {
|
|
244
|
-
await assert.isRejected(writer.put({
|
|
245
|
-
bytes: new Uint8Array(0),
|
|
246
|
-
cid: arg
|
|
247
|
-
}));
|
|
248
|
-
}
|
|
249
|
-
for (const arg of [
|
|
250
|
-
true,
|
|
251
|
-
false,
|
|
252
|
-
null,
|
|
253
|
-
'string',
|
|
254
|
-
100,
|
|
255
|
-
{ obj: 'nope' },
|
|
256
|
-
[false]
|
|
257
|
-
]) {
|
|
258
|
-
await assert.isRejected(writer.put({
|
|
259
|
-
cid: rndCid,
|
|
260
|
-
bytes: arg
|
|
261
|
-
}));
|
|
262
|
-
}
|
|
263
|
-
});
|
|
264
|
-
it('bad write after closed', async () => {
|
|
265
|
-
const {writer, out} = CarWriter.create();
|
|
266
|
-
const collection = collector(out);
|
|
267
|
-
await writer.put(allBlocksFlattened[0]);
|
|
268
|
-
await writer.close();
|
|
269
|
-
await assert.isRejected(writer.put(allBlocksFlattened[1]), /closed/);
|
|
270
|
-
await collection;
|
|
271
|
-
});
|
|
272
|
-
it('bad attempt to multiple iterate', async () => {
|
|
273
|
-
const {out} = CarWriter.create();
|
|
274
|
-
collector(out);
|
|
275
|
-
await assert.isRejected(collector(out), /multiple iterator/i);
|
|
276
|
-
});
|
|
277
|
-
it('bad attempt to multiple close', async () => {
|
|
278
|
-
const {writer, out} = CarWriter.create();
|
|
279
|
-
collector(out);
|
|
280
|
-
await writer.close();
|
|
281
|
-
await assert.isRejected(writer.close(), /closed/i);
|
|
282
|
-
});
|
|
283
|
-
it('update roots (fd)', async () => {
|
|
284
|
-
const bytes = carBytes.slice();
|
|
285
|
-
await CarWriter.updateRootsInBytes(bytes, newRoots);
|
|
286
|
-
await verifyUpdateRoots(bytes);
|
|
287
|
-
});
|
|
288
|
-
it('update roots error: wrong header size', async () => {
|
|
289
|
-
const bytes = carBytes.slice();
|
|
290
|
-
await assert.isRejected(CarWriter.updateRootsInBytes(bytes, [
|
|
291
|
-
...newRoots,
|
|
292
|
-
newRoots[0]
|
|
293
|
-
]), /can only overwrite a header of the same length/);
|
|
294
|
-
await assert.isRejected(CarWriter.updateRootsInBytes(bytes, [newRoots[0]]), /can only overwrite a header of the same length/);
|
|
295
|
-
await assert.isRejected(CarWriter.updateRootsInBytes(bytes, []), /can only overwrite a header of the same length/);
|
|
296
|
-
});
|
|
297
|
-
});
|
|
@@ -1,122 +0,0 @@
|
|
|
1
|
-
import { bytes } from 'multiformats';
|
|
2
|
-
import * as raw from 'multiformats/codecs/raw';
|
|
3
|
-
import {
|
|
4
|
-
toBlock,
|
|
5
|
-
assert,
|
|
6
|
-
makeData
|
|
7
|
-
} from './common.js';
|
|
8
|
-
function compareBlockData(actual, expected, id) {
|
|
9
|
-
assert.strictEqual(bytes.toHex(actual.bytes), bytes.toHex(expected.bytes), `comparing block as hex ${ id || '' }`);
|
|
10
|
-
}
|
|
11
|
-
function compareCids(actual, expected) {
|
|
12
|
-
assert.strictEqual(actual.toString(), expected.toString());
|
|
13
|
-
}
|
|
14
|
-
async function verifyRoots(reader) {
|
|
15
|
-
const {cborBlocks} = await makeData();
|
|
16
|
-
const expected = [
|
|
17
|
-
cborBlocks[0].cid.toString(),
|
|
18
|
-
cborBlocks[1].cid.toString()
|
|
19
|
-
];
|
|
20
|
-
assert.deepStrictEqual((await reader.getRoots()).map(c => c.toString()), expected);
|
|
21
|
-
}
|
|
22
|
-
async function verifyHas(reader) {
|
|
23
|
-
const {allBlocks} = await makeData();
|
|
24
|
-
const verifyHas = async (cid, name) => {
|
|
25
|
-
assert.ok(await reader.has(cid), `reader doesn't have expected key for ${ name }`);
|
|
26
|
-
};
|
|
27
|
-
const verifyHasnt = async (cid, name) => {
|
|
28
|
-
assert.ok(!await reader.has(cid), `reader has unexpected key for ${ name }`);
|
|
29
|
-
assert.strictEqual(await reader.get(cid), undefined);
|
|
30
|
-
};
|
|
31
|
-
for (const [type, blocks] of allBlocks) {
|
|
32
|
-
for (let i = 0; i < blocks.length; i++) {
|
|
33
|
-
await verifyHas(blocks[i].cid, `block #${ i } (${ type } / ${ blocks[i].cid })`);
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
await verifyHasnt((await toBlock(new TextEncoder().encode('dddd'), raw)).cid, 'dddd');
|
|
37
|
-
}
|
|
38
|
-
async function verifyGet(reader) {
|
|
39
|
-
const {allBlocks} = await makeData();
|
|
40
|
-
const verifyBlock = async (expected, index, type) => {
|
|
41
|
-
let actual;
|
|
42
|
-
try {
|
|
43
|
-
actual = await reader.get(expected.cid);
|
|
44
|
-
assert.isDefined(actual);
|
|
45
|
-
if (actual) {
|
|
46
|
-
compareBlockData(actual, expected, `#${ index } (${ type })`);
|
|
47
|
-
}
|
|
48
|
-
} catch (err) {
|
|
49
|
-
assert.ifError(err, `get block length #${ index } (${ type })`);
|
|
50
|
-
}
|
|
51
|
-
};
|
|
52
|
-
for (const [type, blocks] of allBlocks) {
|
|
53
|
-
for (let i = 0; i < blocks.length; i++) {
|
|
54
|
-
await verifyBlock(blocks[i], i, type);
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
async function verifyBlocks(iterator, unordered) {
|
|
59
|
-
const {allBlocksFlattened} = await makeData();
|
|
60
|
-
if (!unordered) {
|
|
61
|
-
const expected = allBlocksFlattened.slice();
|
|
62
|
-
for await (const actual of iterator) {
|
|
63
|
-
const next = expected.shift();
|
|
64
|
-
assert.isDefined(next);
|
|
65
|
-
if (next) {
|
|
66
|
-
compareBlockData(actual, next);
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
} else {
|
|
70
|
-
const expected = {};
|
|
71
|
-
for (const block of allBlocksFlattened) {
|
|
72
|
-
expected[block.cid.toString()] = block;
|
|
73
|
-
}
|
|
74
|
-
for await (const actual of iterator) {
|
|
75
|
-
const {cid} = actual;
|
|
76
|
-
const exp = expected[cid.toString()];
|
|
77
|
-
if (!exp) {
|
|
78
|
-
throw new Error(`Unexpected block: ${ cid.toString() }`);
|
|
79
|
-
}
|
|
80
|
-
compareBlockData(actual, exp);
|
|
81
|
-
delete expected[cid.toString()];
|
|
82
|
-
}
|
|
83
|
-
if (Object.keys(expected).length) {
|
|
84
|
-
throw new Error('Did not find all expected blocks');
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
async function verifyCids(iterator, unordered) {
|
|
89
|
-
const {allBlocksFlattened} = await makeData();
|
|
90
|
-
if (!unordered) {
|
|
91
|
-
const expected = allBlocksFlattened.slice();
|
|
92
|
-
for await (const actual of iterator) {
|
|
93
|
-
const next = expected.shift();
|
|
94
|
-
assert.isDefined(next);
|
|
95
|
-
if (next) {
|
|
96
|
-
compareCids(actual, next.cid);
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
} else {
|
|
100
|
-
const expected = {};
|
|
101
|
-
for (const block of allBlocksFlattened) {
|
|
102
|
-
expected[block.cid.toString()] = block;
|
|
103
|
-
}
|
|
104
|
-
for await (const cid of iterator) {
|
|
105
|
-
const exp = expected[cid.toString()];
|
|
106
|
-
if (!exp) {
|
|
107
|
-
throw new Error(`Unexpected cid: ${ cid.toString() }`);
|
|
108
|
-
}
|
|
109
|
-
delete expected[cid.toString()];
|
|
110
|
-
}
|
|
111
|
-
if (Object.keys(expected).length) {
|
|
112
|
-
throw new Error('Did not find all expected cids');
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
|
-
export {
|
|
117
|
-
verifyRoots,
|
|
118
|
-
verifyHas,
|
|
119
|
-
verifyGet,
|
|
120
|
-
verifyBlocks,
|
|
121
|
-
verifyCids
|
|
122
|
-
};
|
package/esm/car-browser.js
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import { CarReader } from './lib/reader-browser.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-browser.js';
|
|
8
|
-
import { CarIndexedReader } from './lib/indexed-reader-browser.js';
|
|
9
|
-
export {
|
|
10
|
-
CarReader,
|
|
11
|
-
CarIndexer,
|
|
12
|
-
CarBlockIterator,
|
|
13
|
-
CarCIDIterator,
|
|
14
|
-
CarWriter,
|
|
15
|
-
CarIndexedReader
|
|
16
|
-
};
|