ipld_impl.go 2.74 KB
Newer Older
1 2 3 4 5 6 7
package ipldbridge

import (
	"bytes"
	"context"
	"errors"

8 9
	"github.com/ipld/go-ipld-prime/fluent"

10
	ipld "github.com/ipld/go-ipld-prime"
11 12
	"github.com/ipld/go-ipld-prime/encoding/dagcbor"
	free "github.com/ipld/go-ipld-prime/impl/free"
13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
	ipldtraversal "github.com/ipld/go-ipld-prime/traversal"
	ipldselector "github.com/ipld/go-ipld-prime/traversal/selector"
	ipldtypesystem "github.com/ipld/go-ipld-prime/typed/system"
)

// not sure how these will come into being or from where
var cidRootedSelectorType ipldtypesystem.Type
var universe ipldtypesystem.Universe

// TraversalConfig is an alias from ipld, in case it's renamed/moved.
type TraversalConfig = ipldtraversal.TraversalConfig

type ipldBridge struct {
}

// NewIPLDBridge returns an IPLD Bridge.
29 30
func NewIPLDBridge() IPLDBridge {
	return &ipldBridge{}
31 32
}

33 34 35 36 37 38 39 40 41 42 43 44
func (rb *ipldBridge) ExtractData(node ipld.Node, buildFn func(SimpleNode) interface{}) (interface{}, error) {
	var value interface{}
	err := fluent.Recover(func() {
		simpleNode := fluent.WrapNode(node)
		value = buildFn(simpleNode)
	})
	if err != nil {
		return nil, err
	}
	return value, nil
}

45 46 47 48 49 50 51 52 53 54 55 56
func (rb *ipldBridge) BuildNode(buildFn func(NodeBuilder) ipld.Node) (ipld.Node, error) {
	var node ipld.Node
	err := fluent.Recover(func() {
		nb := fluent.WrapNodeBuilder(free.NodeBuilder())
		node = buildFn(nb)
	})
	if err != nil {
		return nil, err
	}
	return node, nil
}

57
func (rb *ipldBridge) Traverse(ctx context.Context, loader Loader, root ipld.Node, s Selector, fn AdvVisitFn) error {
58 59 60 61 62 63 64 65 66 67
	config := &TraversalConfig{Ctx: ctx, LinkLoader: loader}
	return TraversalProgress{TraversalConfig: config}.TraverseInformatively(root, s, fn)
}

func (rb *ipldBridge) ValidateSelectorSpec(cidRootedSelector ipld.Node) []error {
	return ipldtypesystem.Validate(universe, cidRootedSelectorType, cidRootedSelector)
}

func (rb *ipldBridge) EncodeNode(node ipld.Node) ([]byte, error) {
	var buffer bytes.Buffer
68
	err := dagcbor.Encoder(node, &buffer)
69 70 71 72 73 74 75 76
	if err != nil {
		return nil, err
	}
	return buffer.Bytes(), nil
}

func (rb *ipldBridge) DecodeNode(encoded []byte) (ipld.Node, error) {
	reader := bytes.NewReader(encoded)
77
	return dagcbor.Decoder(free.NodeBuilder(), reader)
78 79
}

80
func (rb *ipldBridge) DecodeSelectorSpec(rootedSelector ipld.Node) (ipld.Node, Selector, error) {
81

82
	errs := rb.ValidateSelectorSpec(rootedSelector)
83 84 85 86
	if len(errs) != 0 {
		return nil, nil, errors.New("Node does not validate as selector spec")
	}

87 88 89 90 91
	var node ipld.Node
	err := fluent.Recover(func() {
		link := fluent.WrapNode(rootedSelector).TraverseField("root").AsLink()
		node = fluent.WrapNodeBuilder(free.NodeBuilder()).CreateLink(link)
	})
92 93 94 95
	if err != nil {
		return nil, nil, err
	}

96
	selector, err := ipldselector.ReifySelector(rootedSelector)
97 98 99 100 101 102
	if err != nil {
		return nil, nil, err
	}

	return node, selector, nil
}