@ipld/car 5.0.2 → 5.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +125 -15
- package/dist/index.min.js +3 -3
- package/dist/src/api.d.ts +16 -0
- package/dist/src/api.d.ts.map +1 -1
- package/dist/src/buffer-decoder.d.ts +67 -0
- package/dist/src/buffer-decoder.d.ts.map +1 -0
- package/dist/src/buffer-reader-browser.d.ts +116 -0
- package/dist/src/buffer-reader-browser.d.ts.map +1 -0
- package/dist/src/buffer-reader.d.ts +31 -0
- package/dist/src/buffer-reader.d.ts.map +1 -0
- package/dist/src/coding.d.ts +10 -3
- package/dist/src/coding.d.ts.map +1 -1
- package/dist/src/decoder-common.d.ts +43 -0
- package/dist/src/decoder-common.d.ts.map +1 -0
- package/dist/src/decoder.d.ts +10 -0
- package/dist/src/decoder.d.ts.map +1 -1
- package/dist/src/index.d.ts +2 -1
- package/dist/src/reader-browser.d.ts +1 -1
- package/package.json +8 -2
- package/src/api.ts +18 -0
- package/src/buffer-decoder.js +226 -0
- package/src/buffer-reader-browser.js +150 -0
- package/src/buffer-reader.js +53 -0
- package/src/coding.ts +13 -3
- package/src/decoder-common.js +86 -0
- package/src/decoder.js +31 -93
- package/src/index.js +2 -0
- package/src/reader-browser.js +1 -1
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @typedef {import('multiformats').CID} CID
|
|
3
|
+
* @typedef {import('./api').Block} Block
|
|
4
|
+
* @typedef {import('./api').CarBufferReader} ICarBufferReader
|
|
5
|
+
* @typedef {import('./coding').CarHeader} CarHeader
|
|
6
|
+
* @typedef {import('./coding').CarV2Header} CarV2Header
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* Provides blockstore-like access to a CAR.
|
|
10
|
+
*
|
|
11
|
+
* Implements the `RootsBufferReader` interface:
|
|
12
|
+
* {@link ICarBufferReader.getRoots `getRoots()`}. And the `BlockBufferReader` interface:
|
|
13
|
+
* {@link ICarBufferReader.get `get()`}, {@link ICarBufferReader.has `has()`},
|
|
14
|
+
* {@link ICarBufferReader.blocks `blocks()`} and
|
|
15
|
+
* {@link ICarBufferReader.cids `cids()`}.
|
|
16
|
+
*
|
|
17
|
+
* Load this class with either `import { CarBufferReader } from '@ipld/car/buffer-reader'`
|
|
18
|
+
* (`const { CarBufferReader } = require('@ipld/car/buffer-reader')`). Or
|
|
19
|
+
* `import { CarBufferReader } from '@ipld/car'` (`const { CarBufferReader } = require('@ipld/car')`).
|
|
20
|
+
* The former will likely result in smaller bundle sizes where this is
|
|
21
|
+
* important.
|
|
22
|
+
*
|
|
23
|
+
* @name CarBufferReader
|
|
24
|
+
* @class
|
|
25
|
+
* @implements {ICarBufferReader}
|
|
26
|
+
* @property {number} version The version number of the CAR referenced by this
|
|
27
|
+
* reader (should be `1` or `2`).
|
|
28
|
+
*/
|
|
29
|
+
export class CarBufferReader implements ICarBufferReader {
|
|
30
|
+
/**
|
|
31
|
+
* Instantiate a {@link CarBufferReader} from a `Uint8Array` blob. This performs a
|
|
32
|
+
* decode fully in memory and maintains the decoded state in memory for full
|
|
33
|
+
* access to the data via the `CarReader` API.
|
|
34
|
+
*
|
|
35
|
+
* @static
|
|
36
|
+
* @memberof CarBufferReader
|
|
37
|
+
* @param {Uint8Array} bytes
|
|
38
|
+
* @returns {CarBufferReader}
|
|
39
|
+
*/
|
|
40
|
+
static fromBytes(bytes: Uint8Array): CarBufferReader;
|
|
41
|
+
/**
|
|
42
|
+
* @constructs CarBufferReader
|
|
43
|
+
* @param {CarHeader|CarV2Header} header
|
|
44
|
+
* @param {Block[]} blocks
|
|
45
|
+
*/
|
|
46
|
+
constructor(header: CarHeader | CarV2Header, blocks: Block[]);
|
|
47
|
+
_header: import("./coding").CarHeader | import("./coding").CarV2Header;
|
|
48
|
+
_blocks: import("./api").Block[];
|
|
49
|
+
_cids: import("multiformats").CID<unknown, number, number, import("multiformats").Version>[] | undefined;
|
|
50
|
+
/**
|
|
51
|
+
* @property version
|
|
52
|
+
* @memberof CarBufferReader
|
|
53
|
+
* @instance
|
|
54
|
+
*/
|
|
55
|
+
get version(): 1 | 2;
|
|
56
|
+
/**
|
|
57
|
+
* Get the list of roots defined by the CAR referenced by this reader. May be
|
|
58
|
+
* zero or more `CID`s.
|
|
59
|
+
*
|
|
60
|
+
* @function
|
|
61
|
+
* @memberof CarBufferReader
|
|
62
|
+
* @instance
|
|
63
|
+
* @returns {CID[]}
|
|
64
|
+
*/
|
|
65
|
+
getRoots(): CID[];
|
|
66
|
+
/**
|
|
67
|
+
* Check whether a given `CID` exists within the CAR referenced by this
|
|
68
|
+
* reader.
|
|
69
|
+
*
|
|
70
|
+
* @function
|
|
71
|
+
* @memberof CarBufferReader
|
|
72
|
+
* @instance
|
|
73
|
+
* @param {CID} key
|
|
74
|
+
* @returns {boolean}
|
|
75
|
+
*/
|
|
76
|
+
has(key: CID): boolean;
|
|
77
|
+
/**
|
|
78
|
+
* Fetch a `Block` (a `{ cid:CID, bytes:Uint8Array }` pair) from the CAR
|
|
79
|
+
* referenced by this reader matching the provided `CID`. In the case where
|
|
80
|
+
* the provided `CID` doesn't exist within the CAR, `undefined` will be
|
|
81
|
+
* returned.
|
|
82
|
+
*
|
|
83
|
+
* @function
|
|
84
|
+
* @memberof CarBufferReader
|
|
85
|
+
* @instance
|
|
86
|
+
* @param {CID} key
|
|
87
|
+
* @returns {Block | undefined}
|
|
88
|
+
*/
|
|
89
|
+
get(key: CID): Block | undefined;
|
|
90
|
+
/**
|
|
91
|
+
* Returns a `Block[]` of the `Block`s (`{ cid:CID, bytes:Uint8Array }` pairs) contained within
|
|
92
|
+
* the CAR referenced by this reader.
|
|
93
|
+
*
|
|
94
|
+
* @function
|
|
95
|
+
* @memberof CarBufferReader
|
|
96
|
+
* @instance
|
|
97
|
+
* @returns {Block[]}
|
|
98
|
+
*/
|
|
99
|
+
blocks(): Block[];
|
|
100
|
+
/**
|
|
101
|
+
* Returns a `CID[]` of the `CID`s contained within the CAR referenced by this reader.
|
|
102
|
+
*
|
|
103
|
+
* @function
|
|
104
|
+
* @memberof CarBufferReader
|
|
105
|
+
* @instance
|
|
106
|
+
* @returns {CID[]}
|
|
107
|
+
*/
|
|
108
|
+
cids(): CID[];
|
|
109
|
+
}
|
|
110
|
+
export const __browser: true;
|
|
111
|
+
export type CID = import('multiformats').CID;
|
|
112
|
+
export type Block = import('./api').Block;
|
|
113
|
+
export type ICarBufferReader = import('./api').CarBufferReader;
|
|
114
|
+
export type CarHeader = import('./coding').CarHeader;
|
|
115
|
+
export type CarV2Header = import('./coding').CarV2Header;
|
|
116
|
+
//# sourceMappingURL=buffer-reader-browser.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"buffer-reader-browser.d.ts","sourceRoot":"","sources":["../../src/buffer-reader-browser.js"],"names":[],"mappings":"AAEA;;;;;;GAMG;AAEH;;;;;;;;;;;;;;;;;;;;GAoBG;AACH;IAkGE;;;;;;;;;OASG;IACH,wBAHW,UAAU,GACR,eAAe,CAS3B;IAlHD;;;;OAIG;IACH,oBAHW,SAAS,GAAC,WAAW,UACrB,KAAK,EAAE,EAMjB;IAHC,uEAAqB;IACrB,iCAAqB;IACrB,yGAAsB;IAGxB;;;;OAIG;IACH,qBAEC;IAED;;;;;;;;OAQG;IACH,YAFa,GAAG,EAAE,CAMjB;IAED;;;;;;;;;OASG;IACH,SAHW,GAAG,GACD,OAAO,CAMnB;IAED;;;;;;;;;;;OAWG;IACH,SAHW,GAAG,GACD,KAAK,GAAG,SAAS,CAM7B;IAED;;;;;;;;OAQG;IACH,UAFa,KAAK,EAAE,CAInB;IAED;;;;;;;OAOG;IACH,QAFa,GAAG,EAAE,CAOjB;CAoBF;AAED,6BAA6B;kBAlJhB,OAAO,cAAc,EAAE,GAAG;oBAC1B,OAAO,OAAO,EAAE,KAAK;+BACrB,OAAO,OAAO,EAAE,eAAe;wBAC/B,OAAO,UAAU,EAAE,SAAS;0BAC5B,OAAO,UAAU,EAAE,WAAW"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @class
|
|
3
|
+
* @implements {ICarBufferReader}
|
|
4
|
+
*/
|
|
5
|
+
export class CarBufferReader extends BrowserCarBufferReader implements ICarBufferReader {
|
|
6
|
+
/**
|
|
7
|
+
* Reads a block directly from a file descriptor for an open CAR file. This
|
|
8
|
+
* function is **only available in Node.js** and not a browser environment.
|
|
9
|
+
*
|
|
10
|
+
* This function can be used in connection with {@link CarIndexer} which emits
|
|
11
|
+
* the `BlockIndex` objects that are required by this function.
|
|
12
|
+
*
|
|
13
|
+
* The user is responsible for opening and closing the file used in this call.
|
|
14
|
+
*
|
|
15
|
+
* @static
|
|
16
|
+
* @memberof CarBufferReader
|
|
17
|
+
* @param {number} fd - A file descriptor from the
|
|
18
|
+
* Node.js `fs` module. An integer, from `fs.open()`.
|
|
19
|
+
* @param {BlockIndex} blockIndex - An index pointing to the location of the
|
|
20
|
+
* Block required. This `BlockIndex` should take the form:
|
|
21
|
+
* `{cid:CID, blockLength:number, blockOffset:number}`.
|
|
22
|
+
* @returns {Block} A `{ cid:CID, bytes:Uint8Array }` pair.
|
|
23
|
+
*/
|
|
24
|
+
static readRaw(fd: number, blockIndex: BlockIndex): Block;
|
|
25
|
+
}
|
|
26
|
+
export const __browser: false;
|
|
27
|
+
export type Block = import('./api').Block;
|
|
28
|
+
export type BlockIndex = import('./api').BlockIndex;
|
|
29
|
+
export type ICarBufferReader = import('./api').CarBufferReader;
|
|
30
|
+
import { CarBufferReader as BrowserCarBufferReader } from "./buffer-reader-browser.js";
|
|
31
|
+
//# sourceMappingURL=buffer-reader.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"buffer-reader.d.ts","sourceRoot":"","sources":["../../src/buffer-reader.js"],"names":[],"mappings":"AAWA;;;GAGG;AACH;IACE;;;;;;;;;;;;;;;;;OAiBG;IACH,mBAPW,MAAM,cAEN,UAAU,GAGR,KAAK,CAiBjB;CACF;AAED,8BAA8B;oBAhDjB,OAAO,OAAO,EAAE,KAAK;yBACrB,OAAO,OAAO,EAAE,UAAU;+BAC1B,OAAO,OAAO,EAAE,eAAe"}
|
package/dist/src/coding.d.ts
CHANGED
|
@@ -32,10 +32,17 @@ export interface CarDecoder {
|
|
|
32
32
|
blocks: () => AsyncGenerator<Block>;
|
|
33
33
|
blocksIndex: () => AsyncGenerator<BlockIndex>;
|
|
34
34
|
}
|
|
35
|
-
export interface
|
|
36
|
-
upTo: (length: number) => Promise<Uint8Array>;
|
|
37
|
-
exactly: (length: number) => Promise<Uint8Array>;
|
|
35
|
+
export interface Seekable {
|
|
38
36
|
seek: (length: number) => void;
|
|
37
|
+
}
|
|
38
|
+
export interface BytesReader extends Seekable {
|
|
39
|
+
upTo: (length: number) => Promise<Uint8Array>;
|
|
40
|
+
exactly: (length: number, seek?: boolean) => Promise<Uint8Array>;
|
|
41
|
+
pos: number;
|
|
42
|
+
}
|
|
43
|
+
export interface BytesBufferReader extends Seekable {
|
|
44
|
+
upTo: (length: number) => Uint8Array;
|
|
45
|
+
exactly: (length: number, seek?: boolean) => Uint8Array;
|
|
39
46
|
pos: number;
|
|
40
47
|
}
|
|
41
48
|
//# sourceMappingURL=coding.d.ts.map
|
package/dist/src/coding.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"coding.d.ts","sourceRoot":"","sources":["../../src/coding.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,kBAAkB,CAAA;AAC3C,OAAO,KAAK,EAAE,KAAK,EAAE,UAAU,EAAE,MAAM,UAAU,CAAA;AAEjD,MAAM,WAAW,UAAU;IACzB,QAAQ,EAAE,CAAC,KAAK,EAAE,GAAG,EAAE,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IAEzC,UAAU,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IAE3C,KAAK,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;CAC3B;AAED,MAAM,WAAW,sBAAsB,CAAC,CAAC;IACvC,KAAK,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IAClC,GAAG,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;CACzB;AAED,MAAM,WAAW,eAAe,CAAC,CAAC;IAChC,MAAM,EAAE,sBAAsB,CAAC,CAAC,CAAC,CAAA;IAEjC,QAAQ,EAAE,aAAa,CAAC,CAAC,CAAC,CAAA;CAC3B;AAED,MAAM,WAAW,SAAS;IACxB,OAAO,EAAE,CAAC,CAAA;IACV,KAAK,EAAE,GAAG,EAAE,CAAA;CACb;AAED,MAAM,WAAW,gBAAgB;IAC/B,eAAe,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IACjC,UAAU,EAAE,MAAM,CAAA;IAClB,QAAQ,EAAE,MAAM,CAAA;IAChB,WAAW,EAAE,MAAM,CAAA;CACpB;AAED,MAAM,WAAW,WAAY,SAAQ,gBAAgB;IACnD,OAAO,EAAE,CAAC,CAAA;IACV,KAAK,EAAE,GAAG,EAAE,CAAA;CACb;AAED,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,MAAM,OAAO,CAAC,SAAS,GAAC,WAAW,CAAC,CAAA;IAE5C,MAAM,EAAE,MAAM,cAAc,CAAC,KAAK,CAAC,CAAA;IAEnC,WAAW,EAAE,MAAM,cAAc,CAAC,UAAU,CAAC,CAAA;CAC9C;AAED,MAAM,WAAW,WAAW;
|
|
1
|
+
{"version":3,"file":"coding.d.ts","sourceRoot":"","sources":["../../src/coding.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,kBAAkB,CAAA;AAC3C,OAAO,KAAK,EAAE,KAAK,EAAE,UAAU,EAAE,MAAM,UAAU,CAAA;AAEjD,MAAM,WAAW,UAAU;IACzB,QAAQ,EAAE,CAAC,KAAK,EAAE,GAAG,EAAE,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IAEzC,UAAU,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IAE3C,KAAK,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;CAC3B;AAED,MAAM,WAAW,sBAAsB,CAAC,CAAC;IACvC,KAAK,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IAClC,GAAG,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;CACzB;AAED,MAAM,WAAW,eAAe,CAAC,CAAC;IAChC,MAAM,EAAE,sBAAsB,CAAC,CAAC,CAAC,CAAA;IAEjC,QAAQ,EAAE,aAAa,CAAC,CAAC,CAAC,CAAA;CAC3B;AAED,MAAM,WAAW,SAAS;IACxB,OAAO,EAAE,CAAC,CAAA;IACV,KAAK,EAAE,GAAG,EAAE,CAAA;CACb;AAED,MAAM,WAAW,gBAAgB;IAC/B,eAAe,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IACjC,UAAU,EAAE,MAAM,CAAA;IAClB,QAAQ,EAAE,MAAM,CAAA;IAChB,WAAW,EAAE,MAAM,CAAA;CACpB;AAED,MAAM,WAAW,WAAY,SAAQ,gBAAgB;IACnD,OAAO,EAAE,CAAC,CAAA;IACV,KAAK,EAAE,GAAG,EAAE,CAAA;CACb;AAED,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,MAAM,OAAO,CAAC,SAAS,GAAC,WAAW,CAAC,CAAA;IAE5C,MAAM,EAAE,MAAM,cAAc,CAAC,KAAK,CAAC,CAAA;IAEnC,WAAW,EAAE,MAAM,cAAc,CAAC,UAAU,CAAC,CAAA;CAC9C;AAED,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAA;CAC/B;AAED,MAAM,WAAW,WAAY,SAAQ,QAAQ;IAC3C,IAAI,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC,UAAU,CAAC,CAAA;IAE7C,OAAO,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,KAAK,OAAO,CAAC,UAAU,CAAC,CAAA;IAEhE,GAAG,EAAE,MAAM,CAAA;CACZ;AAED,MAAM,WAAW,iBAAkB,SAAQ,QAAQ;IACjD,IAAI,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,UAAU,CAAA;IAEpC,OAAO,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,KAAK,UAAU,CAAA;IAEvD,GAAG,EAAE,MAAM,CAAA;CACZ"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Decodes varint and seeks the buffer
|
|
3
|
+
*
|
|
4
|
+
* ```js
|
|
5
|
+
* // needs bytes to be read first
|
|
6
|
+
* const bytes = reader.upTo(8) // maybe async
|
|
7
|
+
* ```
|
|
8
|
+
*
|
|
9
|
+
* @param {Uint8Array} bytes
|
|
10
|
+
* @param {import('./coding').Seekable} seeker
|
|
11
|
+
* @returns {number}
|
|
12
|
+
*/
|
|
13
|
+
export function decodeVarint(bytes: Uint8Array, seeker: import('./coding').Seekable): number;
|
|
14
|
+
/**
|
|
15
|
+
* Decode v2 header
|
|
16
|
+
*
|
|
17
|
+
* ```js
|
|
18
|
+
* // needs bytes to be read first
|
|
19
|
+
* const bytes = reader.exactly(V2_HEADER_LENGTH, true) // maybe async
|
|
20
|
+
* ```
|
|
21
|
+
*
|
|
22
|
+
* @param {Uint8Array} bytes
|
|
23
|
+
* @returns {import('./coding').CarV2FixedHeader}
|
|
24
|
+
*/
|
|
25
|
+
export function decodeV2Header(bytes: Uint8Array): import('./coding').CarV2FixedHeader;
|
|
26
|
+
/**
|
|
27
|
+
* Checks the length of the multihash to be read afterwards
|
|
28
|
+
*
|
|
29
|
+
* ```js
|
|
30
|
+
* // needs bytes to be read first
|
|
31
|
+
* const bytes = reader.upTo(8) // maybe async
|
|
32
|
+
* ```
|
|
33
|
+
*
|
|
34
|
+
* @param {Uint8Array} bytes
|
|
35
|
+
*/
|
|
36
|
+
export function getMultihashLength(bytes: Uint8Array): number;
|
|
37
|
+
export namespace CIDV0_BYTES {
|
|
38
|
+
const SHA2_256: number;
|
|
39
|
+
const LENGTH: number;
|
|
40
|
+
const DAG_PB: number;
|
|
41
|
+
}
|
|
42
|
+
export const V2_HEADER_LENGTH: number;
|
|
43
|
+
//# sourceMappingURL=decoder-common.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"decoder-common.d.ts","sourceRoot":"","sources":["../../src/decoder-common.js"],"names":[],"mappings":"AAUA;;;;;;;;;;;GAWG;AACH,oCAJW,UAAU,UACV,OAAO,UAAU,EAAE,QAAQ,GACzB,MAAM,CAWlB;AAED;;;;;;;;;;GAUG;AACH,sCAHW,UAAU,GACR,OAAO,UAAU,EAAE,gBAAgB,CAmB/C;AAED;;;;;;;;;GASG;AACH,0CAFW,UAAU,UAcpB;;;;;;AA7ED,sCAAqH"}
|
package/dist/src/decoder.d.ts
CHANGED
|
@@ -1,3 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @typedef {import('./api').Block} Block
|
|
3
|
+
* @typedef {import('./api').BlockHeader} BlockHeader
|
|
4
|
+
* @typedef {import('./api').BlockIndex} BlockIndex
|
|
5
|
+
* @typedef {import('./coding').BytesReader} BytesReader
|
|
6
|
+
* @typedef {import('./coding').CarHeader} CarHeader
|
|
7
|
+
* @typedef {import('./coding').CarV2Header} CarV2Header
|
|
8
|
+
* @typedef {import('./coding').CarV2FixedHeader} CarV2FixedHeader
|
|
9
|
+
* @typedef {import('./coding').CarDecoder} CarDecoder
|
|
10
|
+
*/
|
|
1
11
|
/**
|
|
2
12
|
* Reads header data from a `BytesReader`. The header may either be in the form
|
|
3
13
|
* of a `CarHeader` or `CarV2Header` depending on the CAR being read.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"decoder.d.ts","sourceRoot":"","sources":["../../src/decoder.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"decoder.d.ts","sourceRoot":"","sources":["../../src/decoder.js"],"names":[],"mappings":"AAMA;;;;;;;;;GASG;AAEH;;;;;;;;GAQG;AACH,mCAJW,WAAW,uCAET,QAAQ,SAAS,GAAC,WAAW,CAAC,CA+B1C;AA2BD;;;;;;;;;GASG;AACH,sCAHW,WAAW,GACT,QAAQ,WAAW,CAAC,CAiBhC;AA4BD;;;;;;;;GAQG;AACH,sCAHW,WAAW,GACT,UAAU,CA+BtB;AAED;;;;;;GAMG;AACH,mCAHW,UAAU,GACR,WAAW,CAmCvB;AAED;;;;;;;GAOG;AACH,uCAHW,MAAM,QAAQ,UAAU,GAAC,IAAI,CAAC,GAC5B,WAAW,CA2EvB;AAED;;;;;;;GAOG;AACH,mDAHW,cAAc,UAAU,CAAC,GACvB,WAAW,CAgBvB;AAED;;;;;;;;;GASG;AACH,oCAJW,WAAW,aACX,MAAM,GACJ,WAAW,CAuCvB;oBA5WY,OAAO,OAAO,EAAE,KAAK;0BACrB,OAAO,OAAO,EAAE,WAAW;yBAC3B,OAAO,OAAO,EAAE,UAAU;0BAC1B,OAAO,UAAU,EAAE,WAAW;wBAC9B,OAAO,UAAU,EAAE,SAAS;0BAC5B,OAAO,UAAU,EAAE,WAAW;+BAC9B,OAAO,UAAU,EAAE,gBAAgB;yBACnC,OAAO,UAAU,EAAE,UAAU"}
|
package/dist/src/index.d.ts
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { CarReader } from "./reader.js";
|
|
2
|
+
import { CarBufferReader } from "./buffer-reader.js";
|
|
2
3
|
import { CarIndexer } from "./indexer.js";
|
|
3
4
|
import { CarBlockIterator } from "./iterator.js";
|
|
4
5
|
import { CarCIDIterator } from "./iterator.js";
|
|
5
6
|
import { CarWriter } from "./writer.js";
|
|
6
7
|
import { CarIndexedReader } from "./indexed-reader.js";
|
|
7
8
|
import * as CarBufferWriter from "./buffer-writer.js";
|
|
8
|
-
export { CarReader, CarIndexer, CarBlockIterator, CarCIDIterator, CarWriter, CarIndexedReader, CarBufferWriter };
|
|
9
|
+
export { CarReader, CarBufferReader, CarIndexer, CarBlockIterator, CarCIDIterator, CarWriter, CarIndexedReader, CarBufferWriter };
|
|
9
10
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -43,7 +43,7 @@ export class CarReader implements CarReaderIface {
|
|
|
43
43
|
* @static
|
|
44
44
|
* @memberof CarReader
|
|
45
45
|
* @param {Uint8Array} bytes
|
|
46
|
-
* @returns {Promise<CarReader>}
|
|
46
|
+
* @returns {Promise<CarReader>}
|
|
47
47
|
*/
|
|
48
48
|
static fromBytes(bytes: Uint8Array): Promise<CarReader>;
|
|
49
49
|
/**
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ipld/car",
|
|
3
|
-
"version": "5.0
|
|
3
|
+
"version": "5.1.0",
|
|
4
4
|
"description": "Content Addressable aRchive format reader and writer",
|
|
5
5
|
"author": "Rod <rod@vagg.org> (http://r.va.gg/)",
|
|
6
6
|
"license": "Apache-2.0 OR MIT",
|
|
@@ -78,6 +78,11 @@
|
|
|
78
78
|
"browser": "./src/reader-browser.js",
|
|
79
79
|
"import": "./src/reader.js"
|
|
80
80
|
},
|
|
81
|
+
"./buffer-reader": {
|
|
82
|
+
"types": "./dist/src/buffer-reader-browser.d.ts",
|
|
83
|
+
"browser": "./src/buffer-reader-browser.js",
|
|
84
|
+
"import": "./src/buffer-reader.js"
|
|
85
|
+
},
|
|
81
86
|
"./writer": {
|
|
82
87
|
"types": "./dist/src/writer.d.ts",
|
|
83
88
|
"browser": "./src/writer-browser.js",
|
|
@@ -190,7 +195,7 @@
|
|
|
190
195
|
"test:examples": "npm run test --prefix examples/",
|
|
191
196
|
"dep-check": "aegir dep-check",
|
|
192
197
|
"coverage": "c8 --reporter=html --reporter=text mocha test/test-*.js && npx st -d coverage -p 8888",
|
|
193
|
-
"docs": "jsdoc4readme --readme --description-only src/reader*.js src/indexed-reader.js src/iterator.js src/indexer.js src/writer*.js src/buffer-writer.js src/decoder.js"
|
|
198
|
+
"docs": "jsdoc4readme --readme --description-only src/reader*.js src/indexed-reader.js src/iterator.js src/indexer.js src/writer*.js src/buffer-writer.js src/decoder.js src/buffer-reader*.js"
|
|
194
199
|
},
|
|
195
200
|
"dependencies": {
|
|
196
201
|
"@ipld/dag-cbor": "^9.0.0",
|
|
@@ -212,6 +217,7 @@
|
|
|
212
217
|
"./src/index.js": "./src/index-browser.js",
|
|
213
218
|
"./src/index-reader.js": "./src/index-reader-browser.js",
|
|
214
219
|
"./src/reader.js": "./src/reader-browser.js",
|
|
220
|
+
"./src/buffer-reader.js": "./src/buffer-reader-browser.js",
|
|
215
221
|
"./src/writer.js": "./src/writer-browser.js",
|
|
216
222
|
"fs": false,
|
|
217
223
|
"util": false,
|
package/src/api.ts
CHANGED
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
import type { CID } from 'multiformats/cid'
|
|
2
2
|
|
|
3
|
+
/**
|
|
4
|
+
* Literally any `Iterable` (async or regular).
|
|
5
|
+
*/
|
|
6
|
+
export type AwaitIterable<T> = Iterable<T> | AsyncIterable<T>
|
|
7
|
+
|
|
3
8
|
export type { CID }
|
|
4
9
|
/* Generic types for interfacing with block storage */
|
|
5
10
|
|
|
@@ -24,6 +29,11 @@ export interface RootsReader {
|
|
|
24
29
|
getRoots: () => Promise<CID[]>
|
|
25
30
|
}
|
|
26
31
|
|
|
32
|
+
export interface RootsBufferReader {
|
|
33
|
+
version: number
|
|
34
|
+
getRoots: () => CID[]
|
|
35
|
+
}
|
|
36
|
+
|
|
27
37
|
export interface BlockIterator extends AsyncIterable<Block> {}
|
|
28
38
|
|
|
29
39
|
export interface CIDIterator extends AsyncIterable<CID> {}
|
|
@@ -35,6 +45,13 @@ export interface BlockReader {
|
|
|
35
45
|
cids: () => CIDIterator
|
|
36
46
|
}
|
|
37
47
|
|
|
48
|
+
export interface BlockBufferReader {
|
|
49
|
+
has: (key: CID) => boolean
|
|
50
|
+
get: (key: CID) => Block | undefined
|
|
51
|
+
blocks: () => Iterable<Block>
|
|
52
|
+
cids: () => Iterable<CID>
|
|
53
|
+
}
|
|
54
|
+
|
|
38
55
|
export interface BlockWriter {
|
|
39
56
|
put: (block: Block) => Promise<void>
|
|
40
57
|
close: () => Promise<void>
|
|
@@ -60,6 +77,7 @@ export interface WriterChannel {
|
|
|
60
77
|
}
|
|
61
78
|
|
|
62
79
|
export interface CarReader extends BlockReader, RootsReader {}
|
|
80
|
+
export interface CarBufferReader extends BlockBufferReader, RootsBufferReader {}
|
|
63
81
|
|
|
64
82
|
/* Specific implementations for CAR block storage */
|
|
65
83
|
|
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
import { CID } from 'multiformats/cid'
|
|
2
|
+
import * as Digest from 'multiformats/hashes/digest'
|
|
3
|
+
import { decode as decodeDagCbor } from '@ipld/dag-cbor'
|
|
4
|
+
import { CarHeader as headerValidator } from './header-validator.js'
|
|
5
|
+
import { CIDV0_BYTES, decodeV2Header, decodeVarint, getMultihashLength, V2_HEADER_LENGTH } from './decoder-common.js'
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* @typedef {import('./api').Block} Block
|
|
9
|
+
* @typedef {import('./api').BlockHeader} BlockHeader
|
|
10
|
+
* @typedef {import('./api').BlockIndex} BlockIndex
|
|
11
|
+
* @typedef {import('./coding').BytesBufferReader} BytesBufferReader
|
|
12
|
+
* @typedef {import('./coding').CarHeader} CarHeader
|
|
13
|
+
* @typedef {import('./coding').CarV2Header} CarV2Header
|
|
14
|
+
* @typedef {import('./coding').CarV2FixedHeader} CarV2FixedHeader
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Reads header data from a `BytesReader`. The header may either be in the form
|
|
19
|
+
* of a `CarHeader` or `CarV2Header` depending on the CAR being read.
|
|
20
|
+
*
|
|
21
|
+
* @name decoder.readHeader(reader)
|
|
22
|
+
* @param {BytesBufferReader} reader
|
|
23
|
+
* @param {number} [strictVersion]
|
|
24
|
+
* @returns {CarHeader | CarV2Header}
|
|
25
|
+
*/
|
|
26
|
+
export function readHeader (reader, strictVersion) {
|
|
27
|
+
const length = decodeVarint(reader.upTo(8), reader)
|
|
28
|
+
if (length === 0) {
|
|
29
|
+
throw new Error('Invalid CAR header (zero length)')
|
|
30
|
+
}
|
|
31
|
+
const header = reader.exactly(length, true)
|
|
32
|
+
const block = decodeDagCbor(header)
|
|
33
|
+
if (!headerValidator(block)) {
|
|
34
|
+
throw new Error('Invalid CAR header format')
|
|
35
|
+
}
|
|
36
|
+
if ((block.version !== 1 && block.version !== 2) || (strictVersion !== undefined && block.version !== strictVersion)) {
|
|
37
|
+
throw new Error(`Invalid CAR version: ${block.version}${strictVersion !== undefined ? ` (expected ${strictVersion})` : ''}`)
|
|
38
|
+
}
|
|
39
|
+
// we've made 'roots' optional in the schema so we can do the version check
|
|
40
|
+
// before rejecting the block as invalid if there is no version
|
|
41
|
+
const hasRoots = Array.isArray(block.roots)
|
|
42
|
+
if ((block.version === 1 && !hasRoots) || (block.version === 2 && hasRoots)) {
|
|
43
|
+
throw new Error('Invalid CAR header format')
|
|
44
|
+
}
|
|
45
|
+
if (block.version === 1) {
|
|
46
|
+
return block
|
|
47
|
+
}
|
|
48
|
+
// version 2
|
|
49
|
+
const v2Header = decodeV2Header(reader.exactly(V2_HEADER_LENGTH, true))
|
|
50
|
+
reader.seek(v2Header.dataOffset - reader.pos)
|
|
51
|
+
const v1Header = readHeader(reader, 1)
|
|
52
|
+
return Object.assign(v1Header, v2Header)
|
|
53
|
+
/* c8 ignore next 2 */
|
|
54
|
+
// Node.js 12 c8 bug
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Reads CID sync
|
|
59
|
+
*
|
|
60
|
+
* @param {BytesBufferReader} reader
|
|
61
|
+
* @returns {CID}
|
|
62
|
+
*/
|
|
63
|
+
function readCid (reader) {
|
|
64
|
+
const first = reader.exactly(2, false)
|
|
65
|
+
if (first[0] === CIDV0_BYTES.SHA2_256 && first[1] === CIDV0_BYTES.LENGTH) {
|
|
66
|
+
// cidv0 32-byte sha2-256
|
|
67
|
+
const bytes = reader.exactly(34, true)
|
|
68
|
+
const multihash = Digest.decode(bytes)
|
|
69
|
+
return CID.create(0, CIDV0_BYTES.DAG_PB, multihash)
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
const version = decodeVarint(reader.upTo(8), reader)
|
|
73
|
+
if (version !== 1) {
|
|
74
|
+
throw new Error(`Unexpected CID version (${version})`)
|
|
75
|
+
}
|
|
76
|
+
const codec = decodeVarint(reader.upTo(8), reader)
|
|
77
|
+
const bytes = reader.exactly(getMultihashLength(reader.upTo(8)), true)
|
|
78
|
+
const multihash = Digest.decode(bytes)
|
|
79
|
+
return CID.create(version, codec, multihash)
|
|
80
|
+
/* c8 ignore next 2 */
|
|
81
|
+
// Node.js 12 c8 bug
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Reads the leading data of an individual block from CAR data from a
|
|
86
|
+
* `BytesBufferReader`. Returns a `BlockHeader` object which contains
|
|
87
|
+
* `{ cid, length, blockLength }` which can be used to either index the block
|
|
88
|
+
* or read the block binary data.
|
|
89
|
+
*
|
|
90
|
+
* @name async decoder.readBlockHead(reader)
|
|
91
|
+
* @param {BytesBufferReader} reader
|
|
92
|
+
* @returns {BlockHeader}
|
|
93
|
+
*/
|
|
94
|
+
export function readBlockHead (reader) {
|
|
95
|
+
// length includes a CID + Binary, where CID has a variable length
|
|
96
|
+
// we have to deal with
|
|
97
|
+
const start = reader.pos
|
|
98
|
+
let length = decodeVarint(reader.upTo(8), reader)
|
|
99
|
+
if (length === 0) {
|
|
100
|
+
throw new Error('Invalid CAR section (zero length)')
|
|
101
|
+
}
|
|
102
|
+
length += (reader.pos - start)
|
|
103
|
+
const cid = readCid(reader)
|
|
104
|
+
const blockLength = length - Number(reader.pos - start) // subtract CID length
|
|
105
|
+
|
|
106
|
+
return { cid, length, blockLength }
|
|
107
|
+
/* c8 ignore next 2 */
|
|
108
|
+
// Node.js 12 c8 bug
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Returns Car header and blocks from a Uint8Array
|
|
113
|
+
*
|
|
114
|
+
* @param {Uint8Array} bytes
|
|
115
|
+
* @returns {{ header : CarHeader | CarV2Header , blocks: Block[]}}
|
|
116
|
+
*/
|
|
117
|
+
export function fromBytes (bytes) {
|
|
118
|
+
let reader = bytesReader(bytes)
|
|
119
|
+
const header = readHeader(reader)
|
|
120
|
+
if (header.version === 2) {
|
|
121
|
+
const v1length = reader.pos - header.dataOffset
|
|
122
|
+
reader = limitReader(reader, header.dataSize - v1length)
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
const blocks = []
|
|
126
|
+
while (reader.upTo(8).length > 0) {
|
|
127
|
+
const { cid, blockLength } = readBlockHead(reader)
|
|
128
|
+
|
|
129
|
+
blocks.push({ cid, bytes: reader.exactly(blockLength, true) })
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
return {
|
|
133
|
+
header, blocks
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* Creates a `BytesBufferReader` from a `Uint8Array`.
|
|
139
|
+
*
|
|
140
|
+
* @name decoder.bytesReader(bytes)
|
|
141
|
+
* @param {Uint8Array} bytes
|
|
142
|
+
* @returns {BytesBufferReader}
|
|
143
|
+
*/
|
|
144
|
+
export function bytesReader (bytes) {
|
|
145
|
+
let pos = 0
|
|
146
|
+
|
|
147
|
+
/** @type {BytesBufferReader} */
|
|
148
|
+
return {
|
|
149
|
+
upTo (length) {
|
|
150
|
+
return bytes.subarray(pos, pos + Math.min(length, bytes.length - pos))
|
|
151
|
+
/* c8 ignore next 2 */
|
|
152
|
+
// Node.js 12 c8 bug
|
|
153
|
+
},
|
|
154
|
+
|
|
155
|
+
exactly (length, seek = false) {
|
|
156
|
+
if (length > bytes.length - pos) {
|
|
157
|
+
throw new Error('Unexpected end of data')
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
const out = bytes.subarray(pos, pos + length)
|
|
161
|
+
if (seek) {
|
|
162
|
+
pos += length
|
|
163
|
+
}
|
|
164
|
+
return out
|
|
165
|
+
/* c8 ignore next 2 */
|
|
166
|
+
// Node.js 12 c8 bug
|
|
167
|
+
},
|
|
168
|
+
|
|
169
|
+
seek (length) {
|
|
170
|
+
pos += length
|
|
171
|
+
},
|
|
172
|
+
|
|
173
|
+
get pos () {
|
|
174
|
+
return pos
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
/**
|
|
180
|
+
* Wraps a `BytesBufferReader` in a limiting `BytesBufferReader` which limits maximum read
|
|
181
|
+
* to `byteLimit` bytes. It _does not_ update `pos` of the original
|
|
182
|
+
* `BytesBufferReader`.
|
|
183
|
+
*
|
|
184
|
+
* @name decoder.limitReader(reader, byteLimit)
|
|
185
|
+
* @param {BytesBufferReader} reader
|
|
186
|
+
* @param {number} byteLimit
|
|
187
|
+
* @returns {BytesBufferReader}
|
|
188
|
+
*/
|
|
189
|
+
export function limitReader (reader, byteLimit) {
|
|
190
|
+
let bytesRead = 0
|
|
191
|
+
|
|
192
|
+
/** @type {BytesBufferReader} */
|
|
193
|
+
return {
|
|
194
|
+
upTo (length) {
|
|
195
|
+
let bytes = reader.upTo(length)
|
|
196
|
+
if (bytes.length + bytesRead > byteLimit) {
|
|
197
|
+
bytes = bytes.subarray(0, byteLimit - bytesRead)
|
|
198
|
+
}
|
|
199
|
+
return bytes
|
|
200
|
+
/* c8 ignore next 2 */
|
|
201
|
+
// Node.js 12 c8 bug
|
|
202
|
+
},
|
|
203
|
+
|
|
204
|
+
exactly (length, seek = false) {
|
|
205
|
+
const bytes = reader.exactly(length, seek)
|
|
206
|
+
if (bytes.length + bytesRead > byteLimit) {
|
|
207
|
+
throw new Error('Unexpected end of data')
|
|
208
|
+
}
|
|
209
|
+
if (seek) {
|
|
210
|
+
bytesRead += length
|
|
211
|
+
}
|
|
212
|
+
return bytes
|
|
213
|
+
/* c8 ignore next 2 */
|
|
214
|
+
// Node.js 12 c8 bug
|
|
215
|
+
},
|
|
216
|
+
|
|
217
|
+
seek (length) {
|
|
218
|
+
bytesRead += length
|
|
219
|
+
reader.seek(length)
|
|
220
|
+
},
|
|
221
|
+
|
|
222
|
+
get pos () {
|
|
223
|
+
return reader.pos
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
}
|