Skip to content

Commit d6733f6

Browse files
committed
fix(unixfsnode): have reifier add path selection to normal nodes
have reifier add path selection to all protobuf nodes, even ones that are not unixfs
1 parent 67a7e38 commit d6733f6

File tree

4 files changed

+172
-21
lines changed

4 files changed

+172
-21
lines changed

directory/basicdir.go

Lines changed: 3 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55

66
"github.com/ipfs/go-unixfsnode/data"
77
"github.com/ipfs/go-unixfsnode/iter"
8+
"github.com/ipfs/go-unixfsnode/utils"
89
dagpb "github.com/ipld/go-codec-dagpb"
910
"github.com/ipld/go-ipld-prime"
1011
"github.com/ipld/go-ipld-prime/schema"
@@ -33,7 +34,7 @@ func (n UnixFSBasicDir) Kind() ipld.Kind {
3334
// LookupByString looks for the key in the list of links with a matching name
3435
func (n UnixFSBasicDir) LookupByString(key string) (ipld.Node, error) {
3536
links := n._substrate.FieldLinks()
36-
link := lookup(links, key)
37+
link := utils.Lookup(links, key)
3738
if link == nil {
3839
return nil, schema.ErrNoSuchField{Type: nil /*TODO*/, Field: ipld.PathSegmentOfString(key)}
3940
}
@@ -132,7 +133,7 @@ func (n UnixFSBasicDir) Iterator() *iter.UnixFSDir__Itr {
132133
}
133134

134135
func (n UnixFSBasicDir) Lookup(key dagpb.String) dagpb.Link {
135-
return lookup(n._substrate.FieldLinks(), key.String())
136+
return utils.Lookup(n._substrate.FieldLinks(), key.String())
136137
}
137138

138139
// direct access to the links and data
@@ -145,23 +146,6 @@ func (n UnixFSBasicDir) FieldData() dagpb.MaybeBytes {
145146
return n._substrate.FieldData()
146147
}
147148

148-
// we need to lookup by key in a list of dag pb links a fair amount, so just have
149-
// a shortcut method
150-
func lookup(links dagpb.PBLinks, key string) dagpb.Link {
151-
li := links.Iterator()
152-
for !li.Done() {
153-
_, next := li.Next()
154-
name := ""
155-
if next.FieldName().Exists() {
156-
name = next.FieldName().Must().String()
157-
}
158-
if key == name {
159-
return next.FieldHash()
160-
}
161-
}
162-
return nil
163-
}
164-
165149
// Substrate returns the underlying PBNode -- note: only the substrate will encode successfully to protobuf if writing
166150
func (n UnixFSBasicDir) Substrate() ipld.Node {
167151
return n._substrate

pathpbnode.go

Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
package unixfsnode
2+
3+
import (
4+
"github.com/ipfs/go-unixfsnode/iter"
5+
"github.com/ipfs/go-unixfsnode/utils"
6+
dagpb "github.com/ipld/go-codec-dagpb"
7+
"github.com/ipld/go-ipld-prime"
8+
"github.com/ipld/go-ipld-prime/schema"
9+
)
10+
11+
var _ ipld.Node = PathedPBNode(nil)
12+
var _ schema.TypedNode = PathedPBNode(nil)
13+
14+
type PathedPBNode = *_PathedPBNode
15+
16+
type _PathedPBNode struct {
17+
_substrate dagpb.PBNode
18+
}
19+
20+
func (n PathedPBNode) Kind() ipld.Kind {
21+
return n._substrate.Kind()
22+
}
23+
24+
// LookupByString looks for the key in the list of links with a matching name
25+
func (n PathedPBNode) LookupByString(key string) (ipld.Node, error) {
26+
links := n._substrate.FieldLinks()
27+
link := utils.Lookup(links, key)
28+
if link == nil {
29+
return nil, schema.ErrNoSuchField{Type: nil /*TODO*/, Field: ipld.PathSegmentOfString(key)}
30+
}
31+
return link, nil
32+
}
33+
34+
func (n PathedPBNode) LookupByNode(key ipld.Node) (ipld.Node, error) {
35+
ks, err := key.AsString()
36+
if err != nil {
37+
return nil, err
38+
}
39+
return n.LookupByString(ks)
40+
}
41+
42+
func (n PathedPBNode) LookupByIndex(idx int64) (ipld.Node, error) {
43+
return n._substrate.LookupByIndex(idx)
44+
}
45+
46+
func (n PathedPBNode) LookupBySegment(seg ipld.PathSegment) (ipld.Node, error) {
47+
return n.LookupByString(seg.String())
48+
}
49+
50+
func (n PathedPBNode) MapIterator() ipld.MapIterator {
51+
return iter.NewUnixFSDirMapIterator(n._substrate.Links.Iterator(), nil)
52+
}
53+
54+
// ListIterator returns an iterator which yields key-value pairs
55+
// traversing the node.
56+
// If the node kind is anything other than a list, nil will be returned.
57+
//
58+
// The iterator will yield every entry in the list; that is, it
59+
// can be expected that itr.Next will be called node.Length times
60+
// before itr.Done becomes true.
61+
func (n PathedPBNode) ListIterator() ipld.ListIterator {
62+
return nil
63+
}
64+
65+
// Length returns the length of a list, or the number of entries in a map,
66+
// or -1 if the node is not of list nor map kind.
67+
func (n PathedPBNode) Length() int64 {
68+
return n._substrate.FieldLinks().Length()
69+
}
70+
71+
func (n PathedPBNode) IsAbsent() bool {
72+
return false
73+
}
74+
75+
func (n PathedPBNode) IsNull() bool {
76+
return false
77+
}
78+
79+
func (n PathedPBNode) AsBool() (bool, error) {
80+
return n._substrate.AsBool()
81+
}
82+
83+
func (n PathedPBNode) AsInt() (int64, error) {
84+
return n._substrate.AsInt()
85+
}
86+
87+
func (n PathedPBNode) AsFloat() (float64, error) {
88+
return n._substrate.AsFloat()
89+
}
90+
91+
func (n PathedPBNode) AsString() (string, error) {
92+
return n._substrate.AsString()
93+
}
94+
95+
func (n PathedPBNode) AsBytes() ([]byte, error) {
96+
return n._substrate.AsBytes()
97+
}
98+
99+
func (n PathedPBNode) AsLink() (ipld.Link, error) {
100+
return n._substrate.AsLink()
101+
}
102+
103+
func (n PathedPBNode) Prototype() ipld.NodePrototype {
104+
// TODO: should this return something?
105+
// probobly not until we write the write interfaces
106+
return nil
107+
}
108+
109+
// satisfy schema.TypedNode
110+
func (PathedPBNode) Type() schema.Type {
111+
return nil /*TODO:typelit*/
112+
}
113+
114+
func (n PathedPBNode) Representation() ipld.Node {
115+
return n._substrate.Representation()
116+
}
117+
118+
// Native map accessors
119+
120+
func (n PathedPBNode) Iterator() *iter.UnixFSDir__Itr {
121+
122+
return iter.NewUnixFSDirIterator(n._substrate.Links.Iterator(), nil)
123+
}
124+
125+
func (n PathedPBNode) Lookup(key dagpb.String) dagpb.Link {
126+
return utils.Lookup(n._substrate.FieldLinks(), key.String())
127+
}
128+
129+
// direct access to the links and data
130+
131+
func (n PathedPBNode) FieldLinks() dagpb.PBLinks {
132+
return n._substrate.FieldLinks()
133+
}
134+
135+
func (n PathedPBNode) FieldData() dagpb.MaybeBytes {
136+
return n._substrate.FieldData()
137+
}
138+
139+
// Substrate returns the underlying PBNode -- note: only the substrate will encode successfully to protobuf if writing
140+
func (n PathedPBNode) Substrate() ipld.Node {
141+
return n._substrate
142+
}

reification.go

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,12 +34,12 @@ func Reify(ctx context.Context, maybePBNodeRoot ipld.Node, lsys *ipld.LinkSystem
3434
}
3535
if !pbNode.FieldData().Exists() {
3636
// no data field, therefore, not UnixFS
37-
return pbNode, nil
37+
return defaultReifier(ctx, pbNode, lsys)
3838
}
3939
data, err := data.DecodeUnixFSData(pbNode.Data.Must().Bytes())
4040
if err != nil {
4141
// we could not decode the UnixFS data, therefore, not UnixFS
42-
return pbNode, nil
42+
return defaultReifier(ctx, pbNode, lsys)
4343
}
4444
builder, ok := reifyFuncs[data.FieldDataType().Int()]
4545
if !ok {
@@ -54,3 +54,9 @@ var reifyFuncs = map[int64]reifyTypeFunc{
5454
data.Data_Directory: directory.NewUnixFSBasicDir,
5555
data.Data_HAMTShard: hamt.NewUnixFSHAMTShard,
5656
}
57+
58+
// treat non-unixFS nodes like directories -- allow them to lookup by link
59+
// TODO: Make this a separate node as directors gain more functionality
60+
func defaultReifier(_ context.Context, substrate dagpb.PBNode, _ *ipld.LinkSystem) (ipld.Node, error) {
61+
return &_PathedPBNode{_substrate: substrate}, nil
62+
}

utils/utils.go

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
package utils
2+
3+
import dagpb "github.com/ipld/go-codec-dagpb"
4+
5+
// Lookup finds a name key in a list of dag pb links
6+
func Lookup(links dagpb.PBLinks, key string) dagpb.Link {
7+
li := links.Iterator()
8+
for !li.Done() {
9+
_, next := li.Next()
10+
name := ""
11+
if next.FieldName().Exists() {
12+
name = next.FieldName().Must().String()
13+
}
14+
if key == name {
15+
return next.FieldHash()
16+
}
17+
}
18+
return nil
19+
}

0 commit comments

Comments
 (0)