package ipldutil import ( "bytes" "context" "errors" ipld "github.com/ipld/go-ipld-prime" dagpb "github.com/ipld/go-ipld-prime-proto" "github.com/ipld/go-ipld-prime/codec/dagcbor" basicnode "github.com/ipld/go-ipld-prime/node/basic" "github.com/ipld/go-ipld-prime/traversal" ipldtraversal "github.com/ipld/go-ipld-prime/traversal" "github.com/ipld/go-ipld-prime/traversal/selector" ipldselector "github.com/ipld/go-ipld-prime/traversal/selector" ) var errDoNotFollow = errors.New("Dont Follow Me") // ErrDoNotFollow is just a wrapper for whatever IPLD's ErrDoNotFollow ends up looking like func ErrDoNotFollow() error { return errDoNotFollow } var ( defaultChooser traversal.LinkTargetNodeStyleChooser = dagpb.AddDagPBSupportToChooser(func(ipld.Link, ipld.LinkContext) (ipld.NodeStyle, error) { return basicnode.Style.Any, nil }) ) func Traverse(ctx context.Context, loader ipld.Loader, chooser traversal.LinkTargetNodeStyleChooser, root ipld.Link, s selector.Selector, fn traversal.AdvVisitFn) error { if chooser == nil { chooser = defaultChooser } ns, err := chooser(root, ipld.LinkContext{}) if err != nil { return err } nb := ns.NewBuilder() err = root.Load(ctx, ipld.LinkContext{}, nb, loader) if err != nil { return err } node := nb.Build() return traversal.Progress{ Cfg: &traversal.Config{ Ctx: ctx, LinkLoader: loader, LinkTargetNodeStyleChooser: chooser, }, }.WalkAdv(node, s, fn) } func WalkMatching(node ipld.Node, s selector.Selector, fn traversal.VisitFn) error { return ipldtraversal.WalkMatching(node, s, fn) } func EncodeNode(node ipld.Node) ([]byte, error) { var buffer bytes.Buffer err := dagcbor.Encoder(node, &buffer) if err != nil { return nil, err } return buffer.Bytes(), nil } func DecodeNode(encoded []byte) (ipld.Node, error) { nb := basicnode.Style.Any.NewBuilder() if err := dagcbor.Decoder(nb, bytes.NewReader(encoded)); err != nil { return nil, err } return nb.Build(), nil } func ParseSelector(selector ipld.Node) (selector.Selector, error) { return ipldselector.ParseSelector(selector) }