Skip to content

Commit 234debc

Browse files
committed
unixfs: Add support for byte slices backed CIDs for zero allocations
``` $ benchstat /mnt/ramdisk/{old,new} name old time/op new time/op delta PB-12 730ns ± 5% 255ns ± 2% -65.04% (p=0.000 n=9+10) name old alloc/op new alloc/op delta PB-12 224B ± 0% 0B -100.00% (p=0.000 n=10+10) name old allocs/op new allocs/op delta PB-12 4.00 ± 0% 0.00 -100.00% (p=0.000 n=10+10) ``` Depends on ipfs/go-cid#159.
1 parent d47c419 commit 234debc

File tree

8 files changed

+82
-72
lines changed

8 files changed

+82
-72
lines changed

examples/go.mod

+3-3
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ require (
66
github.com/gogo/protobuf v1.3.2
77
github.com/ipfs/boxo v0.7.1-0.20230323075409-f4a8dd6614df
88
github.com/ipfs/go-block-format v0.1.2
9-
github.com/ipfs/go-cid v0.4.0
9+
github.com/ipfs/go-cid v0.4.2-0.20230612091241-80d1e915f662
1010
github.com/ipfs/go-datastore v0.6.0
1111
github.com/ipld/go-ipld-prime v0.20.0
1212
github.com/libp2p/go-libp2p v0.26.3
@@ -102,8 +102,8 @@ require (
102102
github.com/multiformats/go-base36 v0.2.0 // indirect
103103
github.com/multiformats/go-multiaddr-dns v0.3.1 // indirect
104104
github.com/multiformats/go-multiaddr-fmt v0.1.0 // indirect
105-
github.com/multiformats/go-multibase v0.1.1 // indirect
106-
github.com/multiformats/go-multihash v0.2.1 // indirect
105+
github.com/multiformats/go-multibase v0.2.0 // indirect
106+
github.com/multiformats/go-multihash v0.2.3 // indirect
107107
github.com/multiformats/go-multistream v0.4.1 // indirect
108108
github.com/multiformats/go-varint v0.0.7 // indirect
109109
github.com/onsi/ginkgo/v2 v2.5.1 // indirect

examples/go.sum

+6-6
Original file line numberDiff line numberDiff line change
@@ -284,8 +284,8 @@ github.com/ipfs/go-blockservice v0.5.0 h1:B2mwhhhVQl2ntW2EIpaWPwSCxSuqr5fFA93Ms4
284284
github.com/ipfs/go-cid v0.0.1/go.mod h1:GHWU/WuQdMPmIosc4Yn1bcCT7dSeX4lBafM7iqUPQvM=
285285
github.com/ipfs/go-cid v0.0.3/go.mod h1:GHWU/WuQdMPmIosc4Yn1bcCT7dSeX4lBafM7iqUPQvM=
286286
github.com/ipfs/go-cid v0.0.6/go.mod h1:6Ux9z5e+HpkQdckYoX1PG/6xqKspzlEIR5SDmgqgC/I=
287-
github.com/ipfs/go-cid v0.4.0 h1:a4pdZq0sx6ZSxbCizebnKiMCx/xI/aBBFlB73IgH4rA=
288-
github.com/ipfs/go-cid v0.4.0/go.mod h1:uQHwDeX4c6CtyrFwdqyhpNcxVewur1M7l7fNU7LKwZk=
287+
github.com/ipfs/go-cid v0.4.2-0.20230612091241-80d1e915f662 h1:jWQ5yOEmR1Fvv6Rj8mEye4QTeGQoKKECMieju9z5kgA=
288+
github.com/ipfs/go-cid v0.4.2-0.20230612091241-80d1e915f662/go.mod h1:4rtyA9XdBeZBapaRNJuTY9H+/6bG4URx/cVwjAzK6fw=
289289
github.com/ipfs/go-datastore v0.6.0 h1:JKyz+Gvz1QEZw0LsX1IBn+JFCJQH4SJVFtM4uWU0Myk=
290290
github.com/ipfs/go-datastore v0.6.0/go.mod h1:rt5M3nNbSO/8q1t4LNkLyUwRs8HupMeN/8O4Vn9YAT8=
291291
github.com/ipfs/go-detect-race v0.0.1 h1:qX/xay2W3E4Q1U7d9lNs1sU9nvguX0a7319XbyQ6cOk=
@@ -469,16 +469,16 @@ github.com/multiformats/go-multiaddr-fmt v0.1.0 h1:WLEFClPycPkp4fnIzoFoV9FVd49/e
469469
github.com/multiformats/go-multiaddr-fmt v0.1.0/go.mod h1:hGtDIW4PU4BqJ50gW2quDuPVjyWNZxToGUh/HwTZYJo=
470470
github.com/multiformats/go-multibase v0.0.1/go.mod h1:bja2MqRZ3ggyXtZSEDKpl0uO/gviWFaSteVbWT51qgs=
471471
github.com/multiformats/go-multibase v0.0.3/go.mod h1:5+1R4eQrT3PkYZ24C3W2Ue2tPwIdYQD509ZjSb5y9Oc=
472-
github.com/multiformats/go-multibase v0.1.1 h1:3ASCDsuLX8+j4kx58qnJ4YFq/JWTJpCyDW27ztsVTOI=
473-
github.com/multiformats/go-multibase v0.1.1/go.mod h1:ZEjHE+IsUrgp5mhlEAYjMtZwK1k4haNkcaPg9aoe1a8=
472+
github.com/multiformats/go-multibase v0.2.0 h1:isdYCVLvksgWlMW9OZRYJEa9pZETFivncJHmHnnd87g=
473+
github.com/multiformats/go-multibase v0.2.0/go.mod h1:bFBZX4lKCA/2lyOFSAoKH5SS6oPyjtnzK/XTFDPkNuk=
474474
github.com/multiformats/go-multicodec v0.8.1 h1:ycepHwavHafh3grIbR1jIXnKCsFm0fqsfEOsJ8NtKE8=
475475
github.com/multiformats/go-multicodec v0.8.1/go.mod h1:L3QTQvMIaVBkXOXXtVmYE+LI16i14xuaojr/H7Ai54k=
476476
github.com/multiformats/go-multihash v0.0.1/go.mod h1:w/5tugSrLEbWqlcgJabL3oHFKTwfvkofsjW2Qa1ct4U=
477477
github.com/multiformats/go-multihash v0.0.8/go.mod h1:YSLudS+Pi8NHE7o6tb3D8vrpKa63epEDmG8nTduyAew=
478478
github.com/multiformats/go-multihash v0.0.10/go.mod h1:YSLudS+Pi8NHE7o6tb3D8vrpKa63epEDmG8nTduyAew=
479479
github.com/multiformats/go-multihash v0.0.13/go.mod h1:VdAWLKTwram9oKAatUcLxBNUjdtcVwxObEQBtRfuyjc=
480-
github.com/multiformats/go-multihash v0.2.1 h1:aem8ZT0VA2nCHHk7bPJ1BjUbHNciqZC/d16Vve9l108=
481-
github.com/multiformats/go-multihash v0.2.1/go.mod h1:WxoMcYG85AZVQUyRyo9s4wULvW5qrI9vb2Lt6evduFc=
480+
github.com/multiformats/go-multihash v0.2.3 h1:7Lyc8XfX/IY2jWb/gI7JP+o7JEq9hOa7BFvVU9RSh+U=
481+
github.com/multiformats/go-multihash v0.2.3/go.mod h1:dXgKXCXjBzdscBLk9JkjINiEsCKRVch90MdaGiKsvSM=
482482
github.com/multiformats/go-multistream v0.4.1 h1:rFy0Iiyn3YT0asivDUIR05leAdwZq3de4741sbiSdfo=
483483
github.com/multiformats/go-multistream v0.4.1/go.mod h1:Mz5eykRVAjJWckE2U78c6xqdtyNUEhKSM0Lwar2p77Q=
484484
github.com/multiformats/go-varint v0.0.1/go.mod h1:3Ls8CIEsrijN6+B7PbrXRPxHRPuXSrVKRY101jdMZYE=

go.mod

+3-3
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ require (
1717
github.com/ipfs/bbloom v0.0.4
1818
github.com/ipfs/go-bitfield v1.1.0
1919
github.com/ipfs/go-block-format v0.1.2
20-
github.com/ipfs/go-cid v0.4.0
20+
github.com/ipfs/go-cid v0.4.2-0.20230612091241-80d1e915f662
2121
github.com/ipfs/go-cidutil v0.1.0
2222
github.com/ipfs/go-datastore v0.6.0
2323
github.com/ipfs/go-detect-race v0.0.1
@@ -48,9 +48,9 @@ require (
4848
github.com/multiformats/go-base32 v0.1.0
4949
github.com/multiformats/go-multiaddr v0.8.0
5050
github.com/multiformats/go-multiaddr-dns v0.3.1
51-
github.com/multiformats/go-multibase v0.1.1
51+
github.com/multiformats/go-multibase v0.2.0
5252
github.com/multiformats/go-multicodec v0.8.1
53-
github.com/multiformats/go-multihash v0.2.1
53+
github.com/multiformats/go-multihash v0.2.3
5454
github.com/multiformats/go-multistream v0.4.1
5555
github.com/multiformats/go-varint v0.0.7
5656
github.com/petar/GoLLRB v0.0.0-20210522233825-ae3b015fd3e9

go.sum

+6-6
Original file line numberDiff line numberDiff line change
@@ -289,8 +289,8 @@ github.com/ipfs/go-cid v0.0.1/go.mod h1:GHWU/WuQdMPmIosc4Yn1bcCT7dSeX4lBafM7iqUP
289289
github.com/ipfs/go-cid v0.0.3/go.mod h1:GHWU/WuQdMPmIosc4Yn1bcCT7dSeX4lBafM7iqUPQvM=
290290
github.com/ipfs/go-cid v0.0.5/go.mod h1:plgt+Y5MnOey4vO4UlUazGqdbEXuFYitED67FexhXog=
291291
github.com/ipfs/go-cid v0.0.6/go.mod h1:6Ux9z5e+HpkQdckYoX1PG/6xqKspzlEIR5SDmgqgC/I=
292-
github.com/ipfs/go-cid v0.4.0 h1:a4pdZq0sx6ZSxbCizebnKiMCx/xI/aBBFlB73IgH4rA=
293-
github.com/ipfs/go-cid v0.4.0/go.mod h1:uQHwDeX4c6CtyrFwdqyhpNcxVewur1M7l7fNU7LKwZk=
292+
github.com/ipfs/go-cid v0.4.2-0.20230612091241-80d1e915f662 h1:jWQ5yOEmR1Fvv6Rj8mEye4QTeGQoKKECMieju9z5kgA=
293+
github.com/ipfs/go-cid v0.4.2-0.20230612091241-80d1e915f662/go.mod h1:4rtyA9XdBeZBapaRNJuTY9H+/6bG4URx/cVwjAzK6fw=
294294
github.com/ipfs/go-cidutil v0.1.0 h1:RW5hO7Vcf16dplUU60Hs0AKDkQAVPVplr7lk97CFL+Q=
295295
github.com/ipfs/go-cidutil v0.1.0/go.mod h1:e7OEVBMIv9JaOxt9zaGEmAoSlXW9jdFZ5lP/0PwcfpA=
296296
github.com/ipfs/go-datastore v0.5.0/go.mod h1:9zhEApYMTl17C8YDp7JmU7sQZi2/wqiYh73hakZ90Bk=
@@ -492,16 +492,16 @@ github.com/multiformats/go-multiaddr-fmt v0.1.0 h1:WLEFClPycPkp4fnIzoFoV9FVd49/e
492492
github.com/multiformats/go-multiaddr-fmt v0.1.0/go.mod h1:hGtDIW4PU4BqJ50gW2quDuPVjyWNZxToGUh/HwTZYJo=
493493
github.com/multiformats/go-multibase v0.0.1/go.mod h1:bja2MqRZ3ggyXtZSEDKpl0uO/gviWFaSteVbWT51qgs=
494494
github.com/multiformats/go-multibase v0.0.3/go.mod h1:5+1R4eQrT3PkYZ24C3W2Ue2tPwIdYQD509ZjSb5y9Oc=
495-
github.com/multiformats/go-multibase v0.1.1 h1:3ASCDsuLX8+j4kx58qnJ4YFq/JWTJpCyDW27ztsVTOI=
496-
github.com/multiformats/go-multibase v0.1.1/go.mod h1:ZEjHE+IsUrgp5mhlEAYjMtZwK1k4haNkcaPg9aoe1a8=
495+
github.com/multiformats/go-multibase v0.2.0 h1:isdYCVLvksgWlMW9OZRYJEa9pZETFivncJHmHnnd87g=
496+
github.com/multiformats/go-multibase v0.2.0/go.mod h1:bFBZX4lKCA/2lyOFSAoKH5SS6oPyjtnzK/XTFDPkNuk=
497497
github.com/multiformats/go-multicodec v0.8.1 h1:ycepHwavHafh3grIbR1jIXnKCsFm0fqsfEOsJ8NtKE8=
498498
github.com/multiformats/go-multicodec v0.8.1/go.mod h1:L3QTQvMIaVBkXOXXtVmYE+LI16i14xuaojr/H7Ai54k=
499499
github.com/multiformats/go-multihash v0.0.1/go.mod h1:w/5tugSrLEbWqlcgJabL3oHFKTwfvkofsjW2Qa1ct4U=
500500
github.com/multiformats/go-multihash v0.0.8/go.mod h1:YSLudS+Pi8NHE7o6tb3D8vrpKa63epEDmG8nTduyAew=
501501
github.com/multiformats/go-multihash v0.0.10/go.mod h1:YSLudS+Pi8NHE7o6tb3D8vrpKa63epEDmG8nTduyAew=
502502
github.com/multiformats/go-multihash v0.0.13/go.mod h1:VdAWLKTwram9oKAatUcLxBNUjdtcVwxObEQBtRfuyjc=
503-
github.com/multiformats/go-multihash v0.2.1 h1:aem8ZT0VA2nCHHk7bPJ1BjUbHNciqZC/d16Vve9l108=
504-
github.com/multiformats/go-multihash v0.2.1/go.mod h1:WxoMcYG85AZVQUyRyo9s4wULvW5qrI9vb2Lt6evduFc=
503+
github.com/multiformats/go-multihash v0.2.3 h1:7Lyc8XfX/IY2jWb/gI7JP+o7JEq9hOa7BFvVU9RSh+U=
504+
github.com/multiformats/go-multihash v0.2.3/go.mod h1:dXgKXCXjBzdscBLk9JkjINiEsCKRVch90MdaGiKsvSM=
505505
github.com/multiformats/go-multistream v0.4.1 h1:rFy0Iiyn3YT0asivDUIR05leAdwZq3de4741sbiSdfo=
506506
github.com/multiformats/go-multistream v0.4.1/go.mod h1:Mz5eykRVAjJWckE2U78c6xqdtyNUEhKSM0Lwar2p77Q=
507507
github.com/multiformats/go-varint v0.0.1/go.mod h1:3Ls8CIEsrijN6+B7PbrXRPxHRPuXSrVKRY101jdMZYE=

unixfs/pb.go

+16-12
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,11 @@ const (
6969
// optional Data Data = 1;
7070
// }
7171

72-
func parsePB(fileChildrens []FileEntry, directoryChildrens []DirectoryEntry, inCid cid.Cid, origData []byte) (typ Type, file File, dir Directory, sym Symlink, err error) {
72+
func parsePB[Self, Children cid.Storage](
73+
fileChildrens []FileEntry[Children],
74+
directoryChildrens []DirectoryEntry[Children],
75+
inCid cid.GenericCid[Self], origData []byte,
76+
) (typ Type, file File[Self, Children], dir Directory[Self, Children], sym Symlink[Self], err error) {
7377
var dataType uint64
7478
var fileLinks, blocksizes uint
7579
var content []byte
@@ -81,8 +85,8 @@ func parsePB(fileChildrens []FileEntry, directoryChildrens []DirectoryEntry, inC
8185
// FIXME: is an empty name a valid file name in a directory ?
8286
directoryChildrens = slices.Grow(directoryChildrens, len(fileChildrens)+extra)
8387
for _, v := range fileChildrens {
84-
directoryChildrens = append(directoryChildrens, DirectoryEntry{
85-
Entry: Entry{Cid: v.Cid, tSize: v.tSize},
88+
directoryChildrens = append(directoryChildrens, DirectoryEntry[Children]{
89+
Entry: Entry[Children]{Cid: v.Cid, tSize: v.tSize},
8690
Name: AliasableString{},
8791
})
8892
}
@@ -126,7 +130,7 @@ func parsePB(fileChildrens []FileEntry, directoryChildrens []DirectoryEntry, inC
126130
}
127131

128132
// FIXME: add support aliased CIDs in github.com/ipfs/go-cid
129-
var c cid.Cid
133+
var c cid.GenericCid[Children]
130134
var name []byte
131135
var tSize uint64 // will be offset by +1, zero means not found
132136

@@ -182,7 +186,7 @@ func parsePB(fileChildrens []FileEntry, directoryChildrens []DirectoryEntry, inC
182186
fileChildrens[blocksizes].FileSize = blocksize
183187
} else {
184188
// we have discovered more blocksizes than links at this point, add new entries
185-
fileChildrens = append(fileChildrens, FileEntry{FileSize: blocksize})
189+
fileChildrens = append(fileChildrens, FileEntry[Children]{FileSize: blocksize})
186190
}
187191
blocksizes++
188192
return nil
@@ -244,7 +248,7 @@ func parsePB(fileChildrens []FileEntry, directoryChildrens []DirectoryEntry, inC
244248
}
245249
mData = mData[l:]
246250

247-
c, err = cid.Cast(cBytes)
251+
c, err = cid.CastGeneric[Children](cBytes)
248252
if err != nil {
249253
err = fmt.Errorf("failed to decode cid: %w", err)
250254
return
@@ -289,7 +293,7 @@ func parsePB(fileChildrens []FileEntry, directoryChildrens []DirectoryEntry, inC
289293

290294
if outerNumber == 2 {
291295
// repeated PBLink Links = 2;
292-
if c == cid.Undef {
296+
if !c.Defined() {
293297
err = errors.New("link is missing CID")
294298
}
295299

@@ -306,8 +310,8 @@ func parsePB(fileChildrens []FileEntry, directoryChildrens []DirectoryEntry, inC
306310
moveZeroNamedDirectoryEntriesToDirectoryChildrens(1)
307311
}
308312

309-
directoryChildrens = append(directoryChildrens, DirectoryEntry{
310-
Entry: Entry{Cid: c, tSize: tSize},
313+
directoryChildrens = append(directoryChildrens, DirectoryEntry[Children]{
314+
Entry: Entry[Children]{Cid: c, tSize: tSize},
311315
Name: AliasableString(name),
312316
})
313317
} else {
@@ -318,7 +322,7 @@ func parsePB(fileChildrens []FileEntry, directoryChildrens []DirectoryEntry, inC
318322
fileChildrens[fileLinks].tSize = tSize
319323
} else {
320324
// we have discovered more links than blocksizes at this point, add new entries
321-
fileChildrens = append(fileChildrens, FileEntry{Entry: Entry{Cid: c, tSize: tSize}})
325+
fileChildrens = append(fileChildrens, FileEntry[Children]{Entry: Entry[Children]{Cid: c, tSize: tSize}})
322326
}
323327
fileLinks++
324328
}
@@ -350,8 +354,8 @@ func parsePB(fileChildrens []FileEntry, directoryChildrens []DirectoryEntry, inC
350354
}
351355

352356
typ = TFile
353-
file = File{
354-
Entry: Entry{Cid: inCid, tSize: selfTSize + uint64(len(origData))},
357+
file = File[Self, Children]{
358+
Entry: Entry[Self]{Cid: inCid, tSize: selfTSize + uint64(len(origData))},
355359
Data: content,
356360
Childrens: fileChildrens,
357361
}

unixfs/pb_test.go

+4-3
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,10 @@ func BenchmarkPB(b *testing.B) {
1919
if err != nil {
2020
b.Fatal()
2121
}
22-
c := cid.NewCidV0(mh)
22+
c := cid.NewCidV0Generic[[]byte](mh)
2323

2424
b.ResetTimer()
25-
var out []FileEntry
25+
var out []FileEntry[[]byte]
2626
for i := b.N; i != 0; i-- {
2727
_, f, _, _, _ := parsePB(out[:0], nil, c, data)
2828
out = f.Childrens
@@ -40,6 +40,7 @@ func FuzzPB(f *testing.F) {
4040
// Assume a block limit is inplace.
4141
return
4242
}
43-
parsePB(nil, nil, cid.Undef, b)
43+
var zero cid.GenericCid[[]byte]
44+
parsePB[[]byte, []byte](nil, nil, zero, b)
4445
})
4546
}

unixfs/unixfs.go

+33-29
Original file line numberDiff line numberDiff line change
@@ -17,62 +17,62 @@ import (
1717
)
1818

1919
// Entry is a basic unit block.
20-
type Entry struct {
21-
Cid cid.Cid
20+
type Entry[S cid.Storage] struct {
21+
Cid cid.GenericCid[S]
2222
// tSize encode the comulative size of the DAG.
2323
// the zero value indicates tsize is missing.
2424
tSize uint64
2525
}
2626

27-
func (e Entry) TSize() (tsize uint64, ok bool) {
27+
func (e Entry[S]) TSize() (tsize uint64, ok bool) {
2828
if e.tSize == 0 {
2929
return 0, false
3030
}
3131

3232
return e.tSize - 1, true
3333
}
3434

35-
func (e Entry) Untyped() Entry {
35+
func (e Entry[S]) Untyped() Entry[S] {
3636
return e
3737
}
3838

39-
var _ Node = File{}
39+
var _ Node[string] = File[string, string]{}
4040

41-
type File struct {
41+
type File[Self, Children cid.Storage] struct {
4242
badge
43-
Entry
43+
Entry[Self]
4444
Data []byte
45-
Childrens []FileEntry
45+
Childrens []FileEntry[Children]
4646
}
4747

48-
func FileEntryWithTSize(c cid.Cid, fileSize, tSize uint64) FileEntry {
49-
return FileEntry{Entry: Entry{Cid: c, tSize: tSize + 1}, FileSize: fileSize}
48+
func FileEntryWithTSize[S cid.Storage](c cid.GenericCid[S], fileSize, tSize uint64) FileEntry[S] {
49+
return FileEntry[S]{Entry: Entry[S]{Cid: c, tSize: tSize + 1}, FileSize: fileSize}
5050
}
5151

52-
type FileEntry struct {
53-
Entry
52+
type FileEntry[S cid.Storage] struct {
53+
Entry[S]
5454
// FileSize is the logical size of the file at this location once decoded.
5555
FileSize uint64
5656
}
5757

58-
var _ Node = Directory{}
58+
var _ Node[string] = Directory[string, string]{}
5959

60-
type Directory struct {
60+
type Directory[Self, Children cid.Storage] struct {
6161
badge
62-
Entry
63-
Childrens []DirectoryEntry
62+
Entry[Self]
63+
Childrens []DirectoryEntry[Children]
6464
}
6565

66-
type DirectoryEntry struct {
67-
Entry
66+
type DirectoryEntry[S cid.Storage] struct {
67+
Entry[S]
6868
Name AliasableString
6969
}
7070

71-
var _ Node = Symlink{}
71+
var _ Node[string] = Symlink[string]{}
7272

73-
type Symlink struct {
73+
type Symlink[S cid.Storage] struct {
7474
badge
75-
Entry
75+
Entry[S]
7676
Value []byte
7777
}
7878

@@ -86,9 +86,9 @@ func (badge) nodeBadge() {
8686

8787
// Node is an interface that can exclusively be a [File], [Directory] or [Symlink]. We might add more in the future.
8888
// You MUST NOT embed this interface, it's only purpose is to provide type safe enums.
89-
type Node interface {
89+
type Node[S cid.Storage] interface {
9090
// Untyped returns the untyped [Entry] for that value stripped of all type related information.
91-
Untyped() Entry
91+
Untyped() Entry[S]
9292
// nodeBadge must never be called it's just here to trick the type checker.
9393
nodeBadge()
9494
}
@@ -97,8 +97,8 @@ type Node interface {
9797
// [File.Data], [DirectoryEntry.Name] and [Symlink.Value] values are aliased to b.RawData().
9898
// The data argument MUST hash to cid, this wont check the validaty of the hash.
9999
// It assumes the size of the block is limited and reasonable.
100-
func Parse(b blocks.Block) (Node, error) {
101-
switch t, f, d, s, err := ParseAppend(nil, nil, b.Cid(), b.RawData()); t {
100+
func Parse[Children cid.Storage](b blocks.Block) (Node[string], error) {
101+
switch t, f, d, s, err := ParseAppend[string, Children](nil, nil, b.Cid(), b.RawData()); t {
102102
case TError:
103103
return nil, err
104104
case TFile:
@@ -121,7 +121,11 @@ func Parse(b blocks.Block) (Node, error) {
121121
// It only ever clobber extra capacity within the slices, it may do so in the case of an error.
122122
// The data argument MUST hash to cid, this wont check the validaty of the hash.
123123
// It assumes the size of the block is limited and reasonable.
124-
func ParseAppend(fileChildrens []FileEntry, directoryChildrens []DirectoryEntry, inCid cid.Cid, data []byte) (t Type, f File, d Directory, s Symlink, err error) {
124+
func ParseAppend[Self, Children cid.Storage](
125+
fileChildrens []FileEntry[Children],
126+
directoryChildrens []DirectoryEntry[Children],
127+
inCid cid.GenericCid[Self], data []byte,
128+
) (t Type, f File[Self, Children], d Directory[Self, Children], s Symlink[Self], err error) {
125129
// Avoid clobbering the used part of the slice.
126130
fileChildrens = fileChildrens[len(fileChildrens):]
127131
directoryChildrens = directoryChildrens[len(directoryChildrens):]
@@ -130,8 +134,8 @@ func ParseAppend(fileChildrens []FileEntry, directoryChildrens []DirectoryEntry,
130134
switch c := multicodec.Code(pref.Codec); c {
131135
case multicodec.Raw:
132136
t = TFile
133-
f = File{
134-
Entry: Entry{
137+
f = File[Self, Children]{
138+
Entry: Entry[Self]{
135139
Cid: inCid,
136140
tSize: uint64(len(data)) + 1,
137141
},
@@ -140,7 +144,7 @@ func ParseAppend(fileChildrens []FileEntry, directoryChildrens []DirectoryEntry,
140144
}
141145
return
142146
case multicodec.DagPb:
143-
return parsePB(fileChildrens, directoryChildrens, inCid, data)
147+
return parsePB[Self, Children](fileChildrens, directoryChildrens, inCid, data)
144148
default:
145149
err = errors.New("unsupported codec: " + c.String())
146150
return

0 commit comments

Comments
 (0)