Skip to content

Commit 0eca32d

Browse files
committed
feat: improve Ipld types and methods
1 parent 07a7d31 commit 0eca32d

File tree

5 files changed

+68
-75
lines changed

5 files changed

+68
-75
lines changed

src/graphsync.ts

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,18 @@ import {
2020
decodeMessage,
2121
newRequest,
2222
} from "./messages.js";
23+
import {
24+
BasicNode,
25+
walkBlocks,
26+
parseContext,
27+
unixfsReifier,
28+
} from "./traversal.js";
2329
import type {
30+
NodeReifier,
31+
KnownReifiers,
2432
SelectorNode,
2533
Blockstore,
26-
KnownReifiers,
27-
NodeReifier,
2834
} from "./traversal.js";
29-
import {Node, walkBlocks, parseContext, unixfsReifier} from "./traversal.js";
3035
import {responseBuilder} from "./response-builder.js";
3136

3237
export class GraphSync extends EventEmitter {
@@ -183,7 +188,7 @@ export class Request extends EventEmitter {
183188
async drain() {
184189
await drain(
185190
walkBlocks(
186-
new Node(this.root),
191+
new BasicNode(this.root),
187192
parseContext().parseSelector(this.selector),
188193
this
189194
)
@@ -194,6 +199,10 @@ export class Request extends EventEmitter {
194199
return this.reifiers[name];
195200
}
196201

202+
addReifier(name: string, reifier: NodeReifier) {
203+
this.reifiers[name] = reifier;
204+
}
205+
197206
// TODO
198207
close() {}
199208

src/resolver.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import {multiaddr, Multiaddr} from "@multiformats/multiaddr";
55
import type {PeerId} from "@libp2p/interface-peer-id";
66
import {
77
allSelector,
8-
Node,
8+
BasicNode,
99
Kind,
1010
LinkLoader,
1111
parseContext,
@@ -82,7 +82,7 @@ export async function* resolve(
8282
loader: LinkLoader
8383
): AsyncIterable<Uint8Array> {
8484
for await (const blk of walkBlocks(
85-
new Node(root),
85+
new BasicNode(root),
8686
parseContext().parseSelector(selector),
8787
loader
8888
)) {

src/response-builder.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import {
1414
walkBlocks,
1515
LinkSystem,
1616
unixfsReifier,
17-
Node,
17+
BasicNode,
1818
parseContext,
1919
} from "./traversal.js";
2020

@@ -54,7 +54,7 @@ export async function* responseBuilder(
5454
let meta: GraphSyncMetadata = [];
5555
let size = 0;
5656
for await (const block of walkBlocks(
57-
new Node(req.root),
57+
new BasicNode(req.root),
5858
parseContext().parseSelector(req.sel),
5959
ls
6060
)) {

src/traversal.ts

Lines changed: 47 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,14 @@ export const selToBlock = (function () {
138138
return encodeSelToBlock;
139139
})();
140140

141-
export class Node {
141+
export interface Node {
142+
kind: Kind;
143+
value: any;
144+
lookupBySegment(seg: PathSegment): Node | null;
145+
entries(): Generator<{pathSegment: PathSegment; value: Node}, any, any>;
146+
}
147+
148+
export class BasicNode implements Node {
142149
kind: Kind;
143150
value: any;
144151
constructor(value: any) {
@@ -152,6 +159,15 @@ export class Node {
152159
}
153160
return null;
154161
}
162+
entries(): Generator<{pathSegment: PathSegment; value: BasicNode}, any, any> {
163+
if (this.kind === Kind.List) {
164+
return arrayEntries(this.value);
165+
}
166+
if (this.kind === Kind.Map) {
167+
return mapEntries(this.value);
168+
}
169+
throw new Error(`Cannot call entries on ${this.kind} kind`);
170+
}
155171
}
156172

157173
export type SelectorNode = {
@@ -235,14 +251,21 @@ export const entriesSelector: SelectorNode = {
235251
},
236252
};
237253

238-
class PathSegment {
254+
export class PathSegment {
239255
value: string | number;
240256
constructor(value: string | number) {
241257
this.value = value;
242258
}
243259
toString(): string {
244260
return this.value + "";
245261
}
262+
toIndex(): number {
263+
if (typeof this.value === "number") {
264+
return this.value;
265+
} else {
266+
return parseInt(this.value);
267+
}
268+
}
246269
}
247270

248271
export interface Selector {
@@ -521,61 +544,26 @@ function parseLimit(node: LimitNode): RecursionLimit {
521544
}
522545
}
523546

524-
type IteratorState = {
525-
pathSegment: PathSegment | null;
526-
value: any;
527-
};
528-
529-
function segmentIterator(node: any) {
530-
if (Array.isArray(node)) {
531-
return arrayIterator(node);
547+
function* arrayEntries(
548+
node: Array<any>
549+
): Generator<{pathSegment: PathSegment; value: BasicNode}, any, any> {
550+
for (let i = 0; i < node.length; i++) {
551+
yield {
552+
pathSegment: new PathSegment(i),
553+
value: new BasicNode(node[i]),
554+
};
532555
}
533-
return mapIterator(node);
534556
}
535557

536-
function arrayIterator(node: Array<any>) {
537-
let i = 0;
538-
return {
539-
next(): IteratorState {
540-
if (i === node.length) {
541-
return {
542-
pathSegment: null,
543-
value: null,
544-
};
545-
}
546-
const index = i++;
547-
return {
548-
pathSegment: new PathSegment(index),
549-
value: node[index],
550-
};
551-
},
552-
done(): boolean {
553-
return i === node.length;
554-
},
555-
};
556-
}
557-
558-
function mapIterator(node: {[key: string]: any}) {
559-
const keys = Object.keys(node);
560-
let i = 0;
561-
return {
562-
next(): IteratorState {
563-
if (i === keys.length) {
564-
return {
565-
pathSegment: null,
566-
value: null,
567-
};
568-
}
569-
const index = i++;
570-
return {
571-
pathSegment: new PathSegment(keys[index]),
572-
value: node[keys[index]],
573-
};
574-
},
575-
done(): boolean {
576-
return i === keys.length;
577-
},
578-
};
558+
function* mapEntries(node: {
559+
[key: string]: any;
560+
}): Generator<{pathSegment: PathSegment; value: BasicNode}, any, any> {
561+
for (const [k, v] of Object.entries(node)) {
562+
yield {
563+
pathSegment: new PathSegment(k),
564+
value: new BasicNode(v),
565+
};
566+
}
579567
}
580568

581569
export type NodeReifier = (node: Node, loader: LinkLoader) => Node;
@@ -593,9 +581,9 @@ export function unixfsReifier(node: Node, loader: LinkLoader): Node {
593581
if (unixfs.isDirectory()) {
594582
const dir: {[key: string]: Node} = {};
595583
for (const link of node.value.Links) {
596-
dir[link.Name] = new Node(link.Hash);
584+
dir[link.Name] = new BasicNode(link.Hash);
597585
}
598-
return new Node(dir);
586+
return new BasicNode(dir);
599587
}
600588
} catch (e) {
601589
return node;
@@ -621,7 +609,7 @@ export async function* walkBlocks(
621609
const blk = await source.load(nd.value);
622610
yield blk;
623611

624-
nd = new Node(blk.value);
612+
nd = new BasicNode(blk.value);
625613
}
626614

627615
if (sel instanceof ExploreInterpretAs) {
@@ -660,14 +648,10 @@ export async function* walkBlocks(
660648
}
661649
} else {
662650
// visit everything
663-
for (const itr = segmentIterator(nd.value); !itr.done(); ) {
664-
let {pathSegment, value} = itr.next();
665-
if (!pathSegment) {
666-
continue;
667-
}
651+
for (const {pathSegment, value} of nd.entries()) {
668652
const sNext = sel.explore(nd.value, pathSegment);
669653
if (sNext !== null) {
670-
yield* walkBlocks(new Node(value), sNext, source);
654+
yield* walkBlocks(value, sNext, source);
671655
}
672656
}
673657
}

test/traversal.spec.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import {MemoryBlockstore} from "blockstore-core/memory";
55
import {sha256} from "multiformats/hashes/sha2";
66
import {importer} from "ipfs-unixfs-importer";
77
import {
8-
Node,
8+
BasicNode,
99
allSelector,
1010
parseContext,
1111
LinkSystem,
@@ -70,7 +70,7 @@ describe("traversal", () => {
7070
let i = 0;
7171

7272
for await (const blk of walkBlocks(
73-
new Node(grandparent.cid),
73+
new BasicNode(grandparent.cid),
7474
sel,
7575
source
7676
)) {
@@ -162,7 +162,7 @@ describe("traversal", () => {
162162

163163
let i = 0;
164164

165-
for await (const blk of walkBlocks(new Node(root), sel, source)) {
165+
for await (const blk of walkBlocks(new BasicNode(root), sel, source)) {
166166
expect(blk.cid.toString()).to.equal(expected[i]);
167167
i++;
168168
}
@@ -184,7 +184,7 @@ describe("traversal", () => {
184184

185185
i = 0;
186186

187-
for await (const blk of walkBlocks(new Node(root2), sel, source)) {
187+
for await (const blk of walkBlocks(new BasicNode(root2), sel, source)) {
188188
expect(blk.cid.toString()).to.equal(expected[i]);
189189
i++;
190190
}

0 commit comments

Comments
 (0)