package ipldbridge import ( "bytes" "context" "errors" "github.com/ipld/go-ipld-prime/fluent" ipld "github.com/ipld/go-ipld-prime" "github.com/ipld/go-ipld-prime/encoding/dagcbor" free "github.com/ipld/go-ipld-prime/impl/free" 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. func NewIPLDBridge() IPLDBridge { return &ipldBridge{} } 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 } 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 } func (rb *ipldBridge) Traverse(ctx context.Context, loader Loader, root ipld.Node, s Selector, fn AdvVisitFn) error { 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 err := dagcbor.Encoder(node, &buffer) if err != nil { return nil, err } return buffer.Bytes(), nil } func (rb *ipldBridge) DecodeNode(encoded []byte) (ipld.Node, error) { reader := bytes.NewReader(encoded) return dagcbor.Decoder(free.NodeBuilder(), reader) } func (rb *ipldBridge) DecodeSelectorSpec(rootedSelector ipld.Node) (ipld.Node, Selector, error) { errs := rb.ValidateSelectorSpec(rootedSelector) if len(errs) != 0 { return nil, nil, errors.New("Node does not validate as selector spec") } var node ipld.Node err := fluent.Recover(func() { link := fluent.WrapNode(rootedSelector).TraverseField("root").AsLink() node = fluent.WrapNodeBuilder(free.NodeBuilder()).CreateLink(link) }) if err != nil { return nil, nil, err } selector, err := ipldselector.ReifySelector(rootedSelector) if err != nil { return nil, nil, err } return node, selector, nil }