Skip to content
This repository has been archived by the owner on Aug 9, 2018. It is now read-only.

Commit

Permalink
Add NodeReaderAt type (read a node from a subpath)
Browse files Browse the repository at this point in the history
  • Loading branch information
mildred committed Dec 31, 2015
1 parent 8ec2a9b commit 102908c
Showing 1 changed file with 57 additions and 0 deletions.
57 changes: 57 additions & 0 deletions reader.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
package ipld

import(
"fmt"
"errors"
"strings"
"reflect"
)

type nodeReadErrors struct { error }
var NodeReadAbort error = &nodeReadErrors{errors.New("abort")}
var NodeReadSkip error = &nodeReadErrors{errors.New("skip")}
Expand Down Expand Up @@ -73,3 +80,53 @@ type NodeReader interface {
Read(f ReadFun) error;
}

// Convert a []interface{} path to a []string path
// This should only convert array indices to strings, and such are not ambiguous
// because array indices and object keys cannot be mixed for the same prefix.
func ToStringPath(anyPath []interface{}) []string {
var res []string
for _, e := range anyPath {
if str, ok := e.(string); ok {
res = append(res, str)
} else if i, ok := e.(int); ok {
res = append(res, fmt.Sprintf("%d", i))
} else {
res = append(res, fmt.Sprintf("%v", e))
}
}
return res
}

// A NodeReader that only read elements from a path prefix
type NodeReaderAt struct {
parent NodeReader
prefix []string
}

func (n *NodeReaderAt) Read(f ReadFun) error {
found := false
return n.parent.Read(func(path []interface{}, tokenType ReaderToken, value interface{}) error {
if isPathPrefix(n.prefix, ToStringPath(path)) {
found = true
return f(path[len(n.prefix):], tokenType, value)
} else if found {
// Finished, stop early
return NodeReadAbort
} else {
// Not yet here, continue
return nil
}
})
}

// Return true if path has prefix
func isPathPrefix(prefix, path []string) bool {
return len(prefix) <= len(path) && reflect.DeepEqual(prefix, path[0:len(prefix)])
}

// Return an instance of NodeReaderAt that read root only starting at the given
// prefix.
func GetReaderAt(root NodeReader, path string) *NodeReaderAt {
return &NodeReaderAt{root, strings.Split(path, "/")}
}

0 comments on commit 102908c

Please sign in to comment.