Skip to content

Commit 40acaac

Browse files
authored
feat: implement sync car decode (#253)
* feat: implement sync car decode * fix: reverse root encoding * revert to block order but retain root order
1 parent 6e48019 commit 40acaac

File tree

11 files changed

+430
-409
lines changed

11 files changed

+430
-409
lines changed

package.json

+2-2
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,8 @@
2222
},
2323
"devDependencies": {
2424
"mocha": "^10.1.0",
25-
"prettier": "2.7.1",
26-
"typescript": "^4.9.4"
25+
"prettier": "2.8.4",
26+
"typescript": "^4.9.5"
2727
},
2828
"prettier": {
2929
"trailingComma": "es5",

packages/client/package.json

+4-4
Original file line numberDiff line numberDiff line change
@@ -34,18 +34,18 @@
3434
},
3535
"devDependencies": {
3636
"@types/chai": "^4.3.3",
37-
"@types/mocha": "^9.1.0",
37+
"@types/mocha": "^10.0.1",
3838
"@ucanto/core": "workspace:^",
3939
"@ucanto/principal": "workspace:^",
4040
"@ucanto/transport": "workspace:^",
4141
"@web-std/fetch": "^4.1.0",
4242
"@web-std/file": "^3.0.2",
43-
"c8": "^7.11.0",
43+
"c8": "^7.13.0",
4444
"chai": "^4.3.6",
4545
"mocha": "^10.1.0",
4646
"nyc": "^15.1.0",
47-
"playwright-test": "^8.1.1",
48-
"typescript": "^4.9.4"
47+
"playwright-test": "^8.2.0",
48+
"typescript": "^4.9.5"
4949
},
5050
"type": "module",
5151
"main": "src/lib.js",

packages/core/package.json

+5-5
Original file line numberDiff line numberDiff line change
@@ -29,22 +29,22 @@
2929
"build": "tsc --build"
3030
},
3131
"dependencies": {
32-
"@ipld/car": "^5.0.3",
32+
"@ipld/car": "^5.1.0",
3333
"@ipld/dag-cbor": "^9.0.0",
3434
"@ipld/dag-ucan": "^3.2.0",
3535
"@ucanto/interface": "workspace:^",
3636
"multiformats": "^11.0.0"
3737
},
3838
"devDependencies": {
3939
"@types/chai": "^4.3.3",
40-
"@types/mocha": "^9.1.0",
40+
"@types/mocha": "^10.0.1",
4141
"@ucanto/principal": "workspace:^",
42-
"c8": "^7.11.0",
42+
"c8": "^7.13.0",
4343
"chai": "^4.3.6",
4444
"mocha": "^10.1.0",
4545
"nyc": "^15.1.0",
46-
"playwright-test": "^8.1.1",
47-
"typescript": "^4.9.4"
46+
"playwright-test": "^8.2.0",
47+
"typescript": "^4.9.5"
4848
},
4949
"type": "module",
5050
"main": "src/lib.js",

packages/interface/package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727
"multiformats": "^11.0.0"
2828
},
2929
"devDependencies": {
30-
"typescript": "^4.9.4"
30+
"typescript": "^4.9.5"
3131
},
3232
"exports": {
3333
".": {

packages/principal/package.json

+5-5
Original file line numberDiff line numberDiff line change
@@ -28,20 +28,20 @@
2828
},
2929
"dependencies": {
3030
"@ipld/dag-ucan": "^3.2.0",
31-
"@noble/ed25519": "^1.7.1",
31+
"@noble/ed25519": "^1.7.3",
3232
"@ucanto/interface": "workspace:^",
3333
"multiformats": "^11.0.0",
3434
"one-webcrypto": "^1.0.3"
3535
},
3636
"devDependencies": {
3737
"@types/chai": "^4.3.3",
38-
"@types/mocha": "^9.1.0",
39-
"c8": "^7.11.0",
38+
"@types/mocha": "^10.0.1",
39+
"c8": "^7.13.0",
4040
"chai": "^4.3.6",
4141
"mocha": "^10.1.0",
4242
"nyc": "^15.1.0",
43-
"playwright-test": "^8.1.1",
44-
"typescript": "^4.9.4"
43+
"playwright-test": "^8.2.0",
44+
"typescript": "^4.9.5"
4545
},
4646
"type": "module",
4747
"main": "src/lib.js",

packages/server/package.json

+4-4
Original file line numberDiff line numberDiff line change
@@ -35,20 +35,20 @@
3535
"devDependencies": {
3636
"@types/chai": "^4.3.3",
3737
"@types/chai-subset": "^1.3.3",
38-
"@types/mocha": "^9.1.0",
38+
"@types/mocha": "^10.0.1",
3939
"@ucanto/client": "workspace:^",
4040
"@ucanto/principal": "workspace:^",
4141
"@ucanto/transport": "workspace:^",
4242
"@web-std/fetch": "^4.1.0",
4343
"@web-std/file": "^3.0.2",
44-
"c8": "^7.11.0",
44+
"c8": "^7.13.0",
4545
"chai": "^4.3.6",
4646
"chai-subset": "^1.6.0",
4747
"mocha": "^10.1.0",
4848
"multiformats": "^11.0.0",
4949
"nyc": "^15.1.0",
50-
"playwright-test": "^8.1.1",
51-
"typescript": "^4.9.4"
50+
"playwright-test": "^8.2.0",
51+
"typescript": "^4.9.5"
5252
},
5353
"exports": {
5454
".": {

packages/transport/package.json

+5-5
Original file line numberDiff line numberDiff line change
@@ -29,23 +29,23 @@
2929
"build": "tsc --build"
3030
},
3131
"dependencies": {
32-
"@ipld/car": "^5.0.3",
32+
"@ipld/car": "^5.1.0",
3333
"@ipld/dag-cbor": "^9.0.0",
3434
"@ucanto/core": "workspace:^",
3535
"@ucanto/interface": "workspace:^",
3636
"multiformats": "^11.0.0"
3737
},
3838
"devDependencies": {
3939
"@types/chai": "^4.3.3",
40-
"@types/mocha": "^9.1.0",
40+
"@types/mocha": "^10.0.1",
4141
"@ucanto/principal": "workspace:^",
4242
"@web-std/fetch": "^4.1.0",
43-
"c8": "^7.11.0",
43+
"c8": "^7.13.0",
4444
"chai": "^4.3.6",
4545
"mocha": "^10.1.0",
4646
"nyc": "^15.1.0",
47-
"playwright-test": "^8.1.1",
48-
"typescript": "^4.9.4"
47+
"playwright-test": "^8.2.0",
48+
"typescript": "^4.9.5"
4949
},
5050
"type": "module",
5151
"typesVersions": {

packages/transport/src/car.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ export const decode = async ({ headers, body }) => {
5050
)
5151
}
5252

53-
const { roots, blocks } = await CAR.decode(body)
53+
const { roots, blocks } = CAR.decode(body)
5454

5555
const invocations = []
5656

packages/transport/src/car/codec.js

+24-20
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import * as API from '@ucanto/interface'
2-
import * as CARWriter from '@ipld/car/buffer-writer'
3-
import { CarReader } from '@ipld/car/reader'
2+
import { CarBufferReader, CarBufferWriter } from '@ipld/car'
43
import { base32 } from 'multiformats/bases/base32'
54
import { UCAN, createLink } from '@ucanto/core'
65
import { sha256 } from 'multiformats/hashes/sha2'
@@ -33,8 +32,8 @@ class Writer {
3332
const id = block.cid.toString(base32)
3433
if (!this.written.has(id)) {
3534
this.blocks.push(block)
36-
this.byteLength += CARWriter.blockLength(
37-
/** @type {CARWriter.Block} */ (block)
35+
this.byteLength += CarBufferWriter.blockLength(
36+
/** @type {CarBufferWriter.Block} */ (block)
3837
)
3938
this.written.add(id)
4039
}
@@ -46,25 +45,28 @@ class Writer {
4645
*/
4746
flush(...rootBlocks) {
4847
const roots = []
48+
// We reverse the roots so that the first root is the last block in the CAR
4949
for (const block of rootBlocks.reverse()) {
5050
const id = block.cid.toString(base32)
5151
if (!this.written.has(id)) {
5252
this.blocks.unshift(block)
53-
this.byteLength += CARWriter.blockLength({
54-
cid: /** @type {CARWriter.CID} */ (block.cid),
53+
this.byteLength += CarBufferWriter.blockLength({
54+
cid: /** @type {CarBufferWriter.CID} */ (block.cid),
5555
bytes: block.bytes,
5656
})
5757
this.written.add(id)
5858
}
59-
roots.push(/** @type {CARWriter.CID} */ (block.cid))
59+
60+
// We unshift here because we want to preserve the order of the roots
61+
roots.unshift(/** @type {CarBufferWriter.CID} */ (block.cid))
6062
}
6163

62-
this.byteLength += CARWriter.headerLength({ roots })
64+
this.byteLength += CarBufferWriter.headerLength({ roots })
6365

6466
const buffer = new ArrayBuffer(this.byteLength)
65-
const writer = CARWriter.createWriter(buffer, { roots })
67+
const writer = CarBufferWriter.createWriter(buffer, { roots })
6668

67-
for (const block of /** @type {CARWriter.Block[]} */ (this.blocks)) {
69+
for (const block of /** @type {CarBufferWriter.Block[]} */ (this.blocks)) {
6870
writer.write(block)
6971
}
7072

@@ -89,20 +91,22 @@ export const encode = ({ roots = [], blocks }) => {
8991

9092
/**
9193
* @param {API.ByteView<Partial<Model>>} bytes
92-
* @returns {Promise<Model>}
94+
* @returns {Model}
9395
*/
94-
export const decode = async bytes => {
95-
const reader = await /** @type {any} */ (CarReader.fromBytes(bytes))
96-
/** @type {{_header: { roots: CARWriter.CID[] }, _keys: string[], _blocks: UCAN.Block[] }} */
97-
const { _header, _blocks, _keys } = reader
96+
export const decode = bytes => {
97+
const reader = CarBufferReader.fromBytes(bytes)
9898
const roots = []
9999
const blocks = new Map()
100-
const index = _header.roots.map(cid => _keys.indexOf(String(cid)))
101100

102-
for (const [n, block] of _blocks.entries()) {
103-
if (index.includes(n)) {
104-
roots.push(/** @type {Block} */ (block))
105-
} else {
101+
for (const root of reader.getRoots()) {
102+
const block = reader.get(root)
103+
if (block) {
104+
roots.push(block)
105+
}
106+
}
107+
108+
for (const block of reader.blocks()) {
109+
if (!roots.includes(block)) {
106110
blocks.set(block.cid.toString(), block)
107111
}
108112
}

packages/validator/package.json

+6-6
Original file line numberDiff line numberDiff line change
@@ -27,25 +27,25 @@
2727
"build": "tsc --build"
2828
},
2929
"dependencies": {
30-
"@ipld/car": "^5.0.3",
31-
"@ipld/dag-cbor": "^8.0.0",
30+
"@ipld/car": "^5.1.0",
31+
"@ipld/dag-cbor": "^9.0.0",
3232
"@ucanto/core": "workspace:^",
3333
"@ucanto/interface": "workspace:^",
3434
"multiformats": "^11.0.0"
3535
},
3636
"devDependencies": {
3737
"@types/chai": "^4.3.3",
3838
"@types/chai-subset": "^1.3.3",
39-
"@types/mocha": "^9.1.0",
39+
"@types/mocha": "^10.0.1",
4040
"@ucanto/client": "workspace:^",
4141
"@ucanto/principal": "workspace:^",
42-
"c8": "^7.11.0",
42+
"c8": "^7.13.0",
4343
"chai": "^4.3.6",
4444
"chai-subset": "^1.6.0",
4545
"mocha": "^10.1.0",
4646
"nyc": "^15.1.0",
47-
"playwright-test": "^8.1.1",
48-
"typescript": "^4.9.4"
47+
"playwright-test": "^8.2.0",
48+
"typescript": "^4.9.5"
4949
},
5050
"type": "module",
5151
"main": "src/lib.js",

0 commit comments

Comments
 (0)