Unverified Commit 04afddfb authored by Eric Myhre's avatar Eric Myhre Committed by GitHub

Merge pull request #110 from ipld/traversal-select-links

Introduce traversal function that selects links out of a tree.
parents 4155593e a6364804
package traversal
import (
"github.com/ipld/go-ipld-prime"
)
// SelectLinks walks a Node tree and returns a slice of all Links encountered.
// SelectLinks will recurse down into any maps and lists,
// but does not attempt to load any of the links it encounters nor recurse further through them
// (in other words, it's confined to one "block").
//
// SelectLinks only returns the list of links; it does not return any other information
// about them such as position in the tree, etc.
//
// An error may be returned if any of the nodes returns errors during iteration;
// this is generally only possible if one of the Nodes is an ADL,
// and unable to be fully walked because of the inability to load or process some data inside the ADL.
// Nodes already fully in memory should not encounter such errors,
// and it should be safe to ignore errors from this method when used in that situation.
// In case of an error, a partial list will still be returned.
//
// If an identical link is found several times during the walk,
// it is reported several times in the resulting list;
// no deduplication is performed by this method.
func SelectLinks(n ipld.Node) ([]ipld.Link, error) {
var answer []ipld.Link
err := accumulateLinks(&answer, n)
return answer, err
}
func accumulateLinks(a *[]ipld.Link, n ipld.Node) error {
switch n.ReprKind() {
case ipld.ReprKind_Map:
for itr := n.MapIterator(); !itr.Done(); {
_, v, err := itr.Next()
if err != nil {
return err
}
accumulateLinks(a, v)
}
case ipld.ReprKind_List:
for itr := n.ListIterator(); !itr.Done(); {
_, v, err := itr.Next()
if err != nil {
return err
}
accumulateLinks(a, v)
}
case ipld.ReprKind_Link:
lnk, _ := n.AsLink()
*a = append(*a, lnk)
}
return nil
}
package traversal_test
import (
"testing"
. "github.com/warpfork/go-wish"
"github.com/ipld/go-ipld-prime"
"github.com/ipld/go-ipld-prime/traversal"
)
func TestSelectLinks(t *testing.T) {
t.Run("Scalar", func(t *testing.T) {
lnks, _ := traversal.SelectLinks(leafAlpha)
Wish(t, lnks, ShouldEqual, []ipld.Link(nil))
})
t.Run("DeepMap", func(t *testing.T) {
lnks, _ := traversal.SelectLinks(middleMapNode)
Wish(t, lnks, ShouldEqual, []ipld.Link{leafAlphaLnk})
})
t.Run("List", func(t *testing.T) {
lnks, _ := traversal.SelectLinks(rootNode)
Wish(t, lnks, ShouldEqual, []ipld.Link{leafAlphaLnk, middleMapNodeLnk, middleListNodeLnk})
})
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment