node.go 3.79 KB
Newer Older
Eric Myhre's avatar
Eric Myhre committed
1 2
package ipld

Eric Myhre's avatar
Eric Myhre committed
3 4 5 6 7
import (
	"github.com/polydawn/refmt/shared"

	"github.com/ipfs/go-cid"
)
8

Eric Myhre's avatar
Eric Myhre committed
9
type Node interface {
10 11 12 13 14
	// Kind returns a value from the ReprKind enum describing what the
	// essential serializable kind of this node is (map, list, int, etc).
	// Most other handling of a node requires first switching upon the kind.
	Kind() ReprKind

15
	// GetField resolves a path in the the object and returns
16 17
	// either a primitive (e.g. string, int, etc), a link (type CID),
	// or another Node.
Eric Myhre's avatar
Eric Myhre committed
18
	TraverseField(path string) (Node, error)
19 20 21 22 23

	// GetIndex is the equivalent of GetField but for indexing into an array
	// (or a numerically-keyed map).  Like GetField, it returns
	// either a primitive (e.g. string, int, etc), a link (type CID),
	// or another Node.
Eric Myhre's avatar
Eric Myhre committed
24
	TraverseIndex(idx int) (Node, error)
Eric Myhre's avatar
Eric Myhre committed
25

26 27 28 29 30 31 32
	// Keys returns instructions for traversing the node.
	// If the node kind is a map, the keys slice has content;
	// if it's a list, the length int will be positive
	// (and if it's a zero length list, there's not to traverse, right?);
	// and if it's a primitive type the returned values are nil and zero.
	Keys() ([]string, int)

Eric Myhre's avatar
Eric Myhre committed
33 34 35 36 37 38
	// Undefined nodes are returned when traversing a struct field that is
	// defined by a schema but unset in the data.  (Undefined nodes are not
	// possible otherwise; you'll only see them from `typed.Node`.)
	//
	// REVIEW: unsure if this should use ReprKind_Invalid or another enum.
	// Since ReprKind_Invalid is returned for UnionStyle_Kinded, confusing.
39 40
	// (But since this is only relevant for `typed.Node`, we can make that
	// choice locally to that package.)
Eric Myhre's avatar
Eric Myhre committed
41 42
	//IsUndefined() bool

Eric Myhre's avatar
Eric Myhre committed
43
	IsNull() bool
Eric Myhre's avatar
Eric Myhre committed
44 45
	AsBool() (bool, error)
	AsInt() (int, error)
46 47 48
	AsFloat() (float64, error)
	AsString() (string, error)
	AsBytes() ([]byte, error)
Eric Myhre's avatar
Eric Myhre committed
49
	AsLink() (cid.Cid, error)
Eric Myhre's avatar
Eric Myhre committed
50 51 52 53 54 55 56

	// PushTokens converts this node and its children into a stream of refmt Tokens
	// and push them sequentially into the given TokenSink.
	// This is useful for serializing, or hashing, or feeding to any other
	// TokenSink (for example, converting to other ipld.Node implementations
	// which can construct themselves from a token stream).
	PushTokens(sink shared.TokenSink) error
Eric Myhre's avatar
Eric Myhre committed
57
}
58 59

type SerializableNode interface {
60
	CID() cid.Cid
61 62
}

63 64 65 66 67 68 69 70
// MutableNode is an interface which allows setting its value.
// MutableNode can be all the same kinds as Node can, and can also
// be freely coerced between kinds.
//
// Using a method which coerces a Mutable node to a new kind can
// discard data; the SetField and SetIndex methods are concatenative,
// but using any of the Set{Scalar} methods will result in any map or
// array content being discarded(!).
71
type MutableNode interface {
72 73 74
	Node
	SetField(k string, v Node) // SetField coerces the node to a map kind and sets a key:val pair.
	SetIndex(k int, v Node)    // SetIndex coerces the node to an array kind and sets an index:val pair.  (It will implicitly increase the size to include the index.)
75
	SetNull()
76 77
	SetBool(v bool)
	SetInt(v int)
78 79 80
	SetFloat(v float64)
	SetString(v string)
	SetBytes(v []byte)
81
	SetLink(v cid.Cid)
82
}
83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98

// REVIEW: having a an immediate-mode Keys() method rather than iterator
// might actually be a bad idea.  We're aiming to reuse this interface
// for *advanced layouts as well*, and those can be *large*.
//
// Similar goes for AsBytes().
//
// Probable solution is having both immediate and iterator return methods.
// Returning a reader for bytes when you know you want a slice already
// is going to be high friction without purpose in many common uses.
//
// Unclear what SetByteStream() would look like for advanced layouts.
// One could try to encapsulate the chunking entirely within the advlay
// node impl... but would it be graceful?  Not sure.  Maybe.  Hopefully!
// Yes?  The advlay impl would still tend to use SetBytes for the raw
// data model layer nodes its composing, so overall, it shakes out nicely.