freeNode.go 5.79 KB
Newer Older
Eric Myhre's avatar
Eric Myhre committed
1 2 3
package ipldfree

import (
Eric Myhre's avatar
Eric Myhre committed
4 5 6
	"fmt"
	"strconv"

Eric Myhre's avatar
Eric Myhre committed
7 8 9 10 11 12 13 14
	"github.com/ipld/go-ipld-prime"
)

var (
	_ ipld.Node = &Node{}
)

/*
15
	Node is an implementatin of `ipld.Node` that can contain any content.
Eric Myhre's avatar
Eric Myhre committed
16

17 18
	This implementation is extremely simple; it is general-purpose,
	but not optimized for any particular purpose.
Eric Myhre's avatar
Eric Myhre committed
19

20
	The "zero" value of this struct has a kind of ReprKind_Invalid.
21
	NodeBuilder must be used to produce valid instances of Node.
Eric Myhre's avatar
Eric Myhre committed
22 23
*/
type Node struct {
24
	kind ipld.ReprKind
Eric Myhre's avatar
Eric Myhre committed
25

26 27 28 29 30 31 32 33
	_map    map[string]ipld.Node // Value union.  Only one of these has meaning, depending on the value of 'Type'.
	_mapOrd []string             // Conjugate to _map, only has meaning depending on the value of 'Type'.
	_arr    []ipld.Node          // Value union.  Only one of these has meaning, depending on the value of 'Type'.
	_bool   bool                 // Value union.  Only one of these has meaning, depending on the value of 'Type'.
	_int    int                  // Value union.  Only one of these has meaning, depending on the value of 'Type'.
	_float  float64              // Value union.  Only one of these has meaning, depending on the value of 'Type'.
	_str    string               // Value union.  Only one of these has meaning, depending on the value of 'Type'.
	_bytes  []byte               // Value union.  Only one of these has meaning, depending on the value of 'Type'.
34
	_link   ipld.Link            // Value union.  Only one of these has meaning, depending on the value of 'Type'.
Eric Myhre's avatar
Eric Myhre committed
35 36
}

Eric Myhre's avatar
Eric Myhre committed
37
func (n *Node) ReprKind() ipld.ReprKind {
38 39
	return n.kind
}
Eric Myhre's avatar
Eric Myhre committed
40

41 42 43
func (Node) IsUndefined() bool {
	return false
}
Eric Myhre's avatar
Eric Myhre committed
44 45 46
func (n *Node) IsNull() bool {
	return n.kind == ipld.ReprKind_Null
}
Eric Myhre's avatar
Eric Myhre committed
47
func (n *Node) AsBool() (v bool, _ error) {
48 49 50 51
	if n.kind != ipld.ReprKind_Bool {
		return false, ipld.ErrWrongKind{MethodName: "AsBool", AppropriateKind: ipld.ReprKindSet_JustBool, ActualKind: n.kind}
	}
	return n._bool, nil
Eric Myhre's avatar
Eric Myhre committed
52
}
53
func (n *Node) AsInt() (v int, _ error) {
54 55 56 57
	if n.kind != ipld.ReprKind_Int {
		return 0, ipld.ErrWrongKind{MethodName: "AsInt", AppropriateKind: ipld.ReprKindSet_JustInt, ActualKind: n.kind}
	}
	return n._int, nil
58 59
}
func (n *Node) AsFloat() (v float64, _ error) {
60 61 62 63
	if n.kind != ipld.ReprKind_Float {
		return 0, ipld.ErrWrongKind{MethodName: "AsFloat", AppropriateKind: ipld.ReprKindSet_JustFloat, ActualKind: n.kind}
	}
	return n._float, nil
64
}
Eric Myhre's avatar
Eric Myhre committed
65
func (n *Node) AsString() (v string, _ error) {
66 67 68 69
	if n.kind != ipld.ReprKind_String {
		return "", ipld.ErrWrongKind{MethodName: "AsString", AppropriateKind: ipld.ReprKindSet_JustString, ActualKind: n.kind}
	}
	return n._str, nil
Eric Myhre's avatar
Eric Myhre committed
70
}
71
func (n *Node) AsBytes() (v []byte, _ error) {
72 73 74 75
	if n.kind != ipld.ReprKind_Bytes {
		return nil, ipld.ErrWrongKind{MethodName: "AsBytes", AppropriateKind: ipld.ReprKindSet_JustBytes, ActualKind: n.kind}
	}
	return n._bytes, nil
Eric Myhre's avatar
Eric Myhre committed
76
}
77
func (n *Node) AsLink() (v ipld.Link, _ error) {
78 79 80 81
	if n.kind != ipld.ReprKind_Link {
		return nil, ipld.ErrWrongKind{MethodName: "AsLink", AppropriateKind: ipld.ReprKindSet_JustLink, ActualKind: n.kind}
	}
	return n._link, nil
82 83
}

84 85 86 87
func (n *Node) NodeBuilder() ipld.NodeBuilder {
	return nodeBuilder{n}
}

88
func (n *Node) MapIterator() ipld.MapIterator {
89 90 91 92
	if n.kind != ipld.ReprKind_Map {
		return &mapIterator{n, 0, ipld.ErrWrongKind{MethodName: "MapIterator", AppropriateKind: ipld.ReprKindSet_JustMap, ActualKind: n.kind}}
	}
	return &mapIterator{n, 0, nil}
93 94
}

95
type mapIterator struct {
96 97
	node *Node
	idx  int
98
	err  error
99 100
}

101 102 103 104 105 106 107 108 109 110 111 112 113 114
func (itr *mapIterator) Next() (ipld.Node, ipld.Node, error) {
	if itr.err != nil {
		return nil, nil, itr.err
	}
	k := itr.node._mapOrd[itr.idx]
	v := itr.node._map[k]
	itr.idx++
	return &Node{kind: ipld.ReprKind_String, _str: k}, v, nil
}
func (itr *mapIterator) Done() bool {
	if itr.err != nil {
		return false
	}
	return itr.idx >= len(itr.node._mapOrd)
115
}
116 117

func (n *Node) ListIterator() ipld.ListIterator {
118 119 120 121
	if n.kind != ipld.ReprKind_List {
		return &listIterator{n, 0, ipld.ErrWrongKind{MethodName: "ListIterator", AppropriateKind: ipld.ReprKindSet_JustList, ActualKind: n.kind}}
	}
	return &listIterator{n, 0, nil}
122 123
}

124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143
type listIterator struct {
	node *Node
	idx  int
	err  error
}

func (itr *listIterator) Next() (int, ipld.Node, error) {
	if itr.err != nil {
		return -1, nil, itr.err
	}
	v := itr.node._arr[itr.idx]
	idx := itr.idx
	itr.idx++
	return idx, v, nil
}
func (itr *listIterator) Done() bool {
	if itr.err != nil {
		return false
	}
	return itr.idx >= len(itr.node._arr)
144 145 146
}

func (n *Node) Length() int {
Eric Myhre's avatar
Eric Myhre committed
147
	switch n.ReprKind() {
148 149 150 151 152 153 154
	case ipld.ReprKind_Map:
		return len(n._mapOrd)
	case ipld.ReprKind_List:
		return len(n._arr)
	default:
		return -1
	}
Eric Myhre's avatar
Eric Myhre committed
155 156 157
}

func (n *Node) TraverseField(pth string) (ipld.Node, error) {
158 159
	switch n.kind {
	case ipld.ReprKind_Map:
160 161 162
		v, exists := n._map[pth]
		if !exists {
			return nil, fmt.Errorf("404")
Eric Myhre's avatar
Eric Myhre committed
163
		}
164
		return v, nil
165
	case ipld.ReprKind_List:
Eric Myhre's avatar
Eric Myhre committed
166 167 168 169 170 171 172
		i, err := strconv.Atoi(pth)
		if err != nil {
			return nil, fmt.Errorf("404")
		}
		if i >= len(n._arr) {
			return nil, fmt.Errorf("404")
		}
173
		return n._arr[i], nil
174 175
	case ipld.ReprKind_Invalid,
		ipld.ReprKind_Null,
176 177 178 179 180
		ipld.ReprKind_String,
		ipld.ReprKind_Bytes,
		ipld.ReprKind_Int,
		ipld.ReprKind_Float,
		ipld.ReprKind_Link:
181
		return nil, ipld.ErrWrongKind{MethodName: "TraverseField", AppropriateKind: ipld.ReprKindSet_JustMap, ActualKind: n.kind}
Eric Myhre's avatar
Eric Myhre committed
182 183 184 185 186 187
	default:
		panic("unreachable")
	}
}

func (n *Node) TraverseIndex(idx int) (ipld.Node, error) {
188 189
	switch n.kind {
	case ipld.ReprKind_List:
190 191 192 193 194 195 196
		if idx >= len(n._arr) {
			return nil, fmt.Errorf("404")
		}
		if n._arr[idx] == nil {
			return nil, fmt.Errorf("404")
		}
		return n._arr[idx], nil
197 198 199 200
	case ipld.ReprKind_Invalid,
		ipld.ReprKind_Null,
		ipld.ReprKind_Map,
		ipld.ReprKind_Bool,
201 202 203 204 205
		ipld.ReprKind_String,
		ipld.ReprKind_Bytes,
		ipld.ReprKind_Int,
		ipld.ReprKind_Float,
		ipld.ReprKind_Link:
206
		return nil, ipld.ErrWrongKind{MethodName: "TraverseIndex", AppropriateKind: ipld.ReprKindSet_JustList, ActualKind: n.kind}
207 208 209
	default:
		panic("unreachable")
	}
Eric Myhre's avatar
Eric Myhre committed
210
}