freeNodeMutation.go 3.3 KB
Newer Older
1 2 3 4 5 6
package ipldfree

import (
	"github.com/ipld/go-ipld-prime"
)

7 8 9 10 11 12 13
var (
	_ ipld.MutableNode = &Node{}
)

func (n *Node) SetNull() {
	n.coerceType(ipld.ReprKind_Null)
}
14
func (n *Node) SetField(k string, v ipld.Node) {
15
	n.coerceType(ipld.ReprKind_Map)
16 17 18
	if _, exists := n._map[k]; !exists {
		n._mapOrd = append(n._mapOrd, k)
	}
19
	n._map[k] = v
20 21
}
func (n *Node) SetIndex(k int, v ipld.Node) {
22
	n.coerceType(ipld.ReprKind_List)
23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60
	// REVIEW: there are implications to serial arrays as we spec'd them.
	//  Namely, they can't be sparse.  It's just not defined.
	//  And that means we simply have to have a way to define the length.
	//  We can do implicit grows via this setter; I'm fine with that.
	//  But we'll also need, evidently, a Truncate method.
	//  (Or, a magical sentinel value for node that says EOL.)
	oldLen := len(n._arr)
	minLen := k + 1
	if minLen > oldLen {
		// Grow.
		oldCap := cap(n._arr)
		if minLen > oldCap {
			// Out of cap; do whole new backing array allocation.
			//  Growth maths are per stdlib's reflect.grow.
			// First figure out how much growth to do.
			newCap := oldCap
			if newCap == 0 {
				newCap = minLen
			} else {
				for minLen > newCap {
					if minLen < 1024 {
						newCap += newCap
					} else {
						newCap += newCap / 4
					}
				}
			}
			// Now alloc and copy over old.
			newArr := make([]ipld.Node, minLen, newCap)
			copy(newArr, n._arr)
			n._arr = newArr
		} else {
			// Still have cap, just extend the slice.
			n._arr = n._arr[0:minLen]
		}
	}
	n._arr[k] = v
	//fmt.Printf("len,cap is now %d,%d\n", len(n._arr), cap(n._arr))
61 62
}
func (n *Node) SetBool(v bool) {
63
	n.coerceType(ipld.ReprKind_Bool)
64 65 66
	n._bool = v
}
func (n *Node) SetInt(v int) {
67
	n.coerceType(ipld.ReprKind_Int)
68 69 70
	n._int = v
}
func (n *Node) SetFloat(v float64) {
71
	n.coerceType(ipld.ReprKind_Float)
72 73
	n._float = v
}
74 75 76 77 78 79 80 81
func (n *Node) SetString(v string) {
	n.coerceType(ipld.ReprKind_String)
	n._str = v
}
func (n *Node) SetBytes(v []byte) {
	n.coerceType(ipld.ReprKind_Bytes)
	n._bytes = v
}
82
func (n *Node) SetLink(v ipld.Link) {
83
	n.coerceType(ipld.ReprKind_Link)
84 85 86
	n._link = v
}

87
func (n *Node) coerceType(newKind ipld.ReprKind) {
88 89 90 91 92 93
	// If this node pointer has actually just been nil, initialize.
	//  (Our arrays sometimes initialize full of nils, so this comes up.)
	// TODO
	// REVIEW actually it's pretty dubious that we should return those.
	//  Nobody ever said our concept of array should be non-sparse and get nils in it.

94 95
	// Clear previous data, if relevant.
	//  Don't bother with zeroing finite-size scalars.
96 97
	switch n.kind {
	case ipld.ReprKind_Map:
98
		switch newKind {
99
		case ipld.ReprKind_Map:
100 101 102
			return
		default:
			n._map = nil
103
			n._mapOrd = nil
104
		}
105
	case ipld.ReprKind_List:
106
		switch newKind {
107
		case ipld.ReprKind_List:
108 109 110 111
			return
		default:
			n._arr = nil
		}
112
	case ipld.ReprKind_String:
113
		switch newKind {
114
		case ipld.ReprKind_String:
115 116 117 118
			return
		default:
			n._str = ""
		}
119
	case ipld.ReprKind_Bytes:
120
		switch newKind {
121
		case ipld.ReprKind_Bytes:
122 123 124 125
			return
		default:
			n._bytes = nil
		}
126
	case ipld.ReprKind_Link:
127
		switch newKind {
128
		case ipld.ReprKind_Link:
129 130
			return
		default:
131
			n._link = nil
132 133 134 135
		}
	}
	// Set new type union marker.
	//  Initialize empty value if necessary (maps).
136
	n.kind = newKind
137
	switch newKind {
138
	case ipld.ReprKind_Map:
139
		n._map = make(map[string]ipld.Node)
140 141 142
	}
	// You'll still want to set the value itself after this.
}