Skip to content

Commit

Permalink
Add NodeReader interface
Browse files Browse the repository at this point in the history
See issue ipld#17
  • Loading branch information
mildred committed Jan 15, 2016
1 parent d68f39d commit ea0deeb
Showing 1 changed file with 101 additions and 0 deletions.
101 changes: 101 additions & 0 deletions reader/reader.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
package reader

import (
"errors"
)

type nodeReadErrors struct{ error }

var NodeReadAbort error = &nodeReadErrors{errors.New("abort")}
var NodeReadSkip error = &nodeReadErrors{errors.New("skip")}

type ReaderToken int

const (
TokenNode ReaderToken = iota
TokenKey
TokenArray
TokenIndex
TokenValue
)

func TokenName(tok ReaderToken) string {
switch tok {
case TokenNode:
return "TokenNode"
case TokenKey:
return "TokenKey"
case TokenArray:
return "TokenArray"
case TokenIndex:
return "TokenIndex"
case TokenValue:
return "TokenValue"
case TokenEndNode:
return "TokenEndNode"
case TokenEndArray:
return "TokenEndArray"
default:
return ""
}
}

// Callback function to be called when reading a Node. The path represents the
// location in the hierarchy, tokenType is the type of token being read, and
// value is the corresponding value. The function can return SkipNode to skip
// recursing, or an error to stop the reading at any time.
type ReadFun func(path []interface{}, tokenType ReaderToken, value interface{}) error

// Represents a Node that can be read using the special Read function
type NodeReader interface {

// Read the node from the beginning. Return any errors found during the
// process. The function f is called for every value found in the node stream,
// on the following events:
//
// - Once for each node (TokenNode) with a nil value
// - Once for each key of each node (TokenKey) with the key name as value
// - Once for each array / slice (TokenArray) with a nil value
// - Once for each slice item (TokenIndex) with the index as value
// - Once for each other value (TokenValue) with the actual value given
//
// For example, the node that can be represented using the following JSON
// construct:
//
// {
// "key": "value",
// "items": ["a", "b", "c"],
// "count": 3
// }
//
// Will result in the function called in this way:
//
// f({}, TokenNode, nil)
// f({}, TokenKey, "key")
// f({"key"}, TokenValue, "value")
// f({}, TokenKey, "items")
// f({"items"}, TokenArray, nil)
// f({"items"}, TokenIndex, 0)
// f({"items", 0}, TokenValue, "a")
// f({"items"}, TokenIndex, 1)
// f({"items", 1}, TokenValue, "b")
// f({"items"}, TokenIndex, 2)
// f({"items", 2}, TokenValue, "c")
// f({}, TokenKey, "count")
// f({"count"}, TokenValue, 3)
//
// Iteration order for maps is fixed by the order of the pairs in memory.
//
// Returning NodeReadSkip from the callback function will skip the sub elements:
//
// - for TokenNode or TokenArray, the complete node or array will be skipped
// - for TokenKey or TokenIndex, the corresponding value will be skipped
//
// Returning NodeReadAbort will cancel the reading process without returning
// an error to the caller.
//
// Returning any other error will abort the read process and the error will be
// passed as a return value of the Read() function.
//
Read(f ReadFun) error
}

0 comments on commit ea0deeb

Please sign in to comment.