summaryrefslogtreecommitdiffstats
path: root/vendor/github.com/pelletier/go-toml/v2/internal/ast/ast.go
blob: 33c7f915550c4ee27572f834d3d403222594b6e6 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
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
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
package ast

import (
	"fmt"
	"unsafe"

	"github.com/pelletier/go-toml/v2/internal/danger"
)

// Iterator starts uninitialized, you need to call Next() first.
//
// For example:
//
// it := n.Children()
// for it.Next() {
// 		it.Node()
// }
type Iterator struct {
	started bool
	node    *Node
}

// Next moves the iterator forward and returns true if points to a
// node, false otherwise.
func (c *Iterator) Next() bool {
	if !c.started {
		c.started = true
	} else if c.node.Valid() {
		c.node = c.node.Next()
	}
	return c.node.Valid()
}

// IsLast returns true if the current node of the iterator is the last
// one.  Subsequent call to Next() will return false.
func (c *Iterator) IsLast() bool {
	return c.node.next == 0
}

// Node returns a copy of the node pointed at by the iterator.
func (c *Iterator) Node() *Node {
	return c.node
}

// Root contains a full AST.
//
// It is immutable once constructed with Builder.
type Root struct {
	nodes []Node
}

// Iterator over the top level nodes.
func (r *Root) Iterator() Iterator {
	it := Iterator{}
	if len(r.nodes) > 0 {
		it.node = &r.nodes[0]
	}
	return it
}

func (r *Root) at(idx Reference) *Node {
	return &r.nodes[idx]
}

// Arrays have one child per element in the array.  InlineTables have
// one child per key-value pair in the table.  KeyValues have at least
// two children. The first one is the value. The rest make a
// potentially dotted key.  Table and Array table have one child per
// element of the key they represent (same as KeyValue, but without
// the last node being the value).
type Node struct {
	Kind Kind
	Raw  Range  // Raw bytes from the input.
	Data []byte // Node value (either allocated or referencing the input).

	// References to other nodes, as offsets in the backing array
	// from this node. References can go backward, so those can be
	// negative.
	next  int // 0 if last element
	child int // 0 if no child
}

type Range struct {
	Offset uint32
	Length uint32
}

// Next returns a copy of the next node, or an invalid Node if there
// is no next node.
func (n *Node) Next() *Node {
	if n.next == 0 {
		return nil
	}
	ptr := unsafe.Pointer(n)
	size := unsafe.Sizeof(Node{})
	return (*Node)(danger.Stride(ptr, size, n.next))
}

// Child returns a copy of the first child node of this node. Other
// children can be accessed calling Next on the first child.  Returns
// an invalid Node if there is none.
func (n *Node) Child() *Node {
	if n.child == 0 {
		return nil
	}
	ptr := unsafe.Pointer(n)
	size := unsafe.Sizeof(Node{})
	return (*Node)(danger.Stride(ptr, size, n.child))
}

// Valid returns true if the node's kind is set (not to Invalid).
func (n *Node) Valid() bool {
	return n != nil
}

// Key returns the child nodes making the Key on a supported
// node. Panics otherwise.  They are guaranteed to be all be of the
// Kind Key. A simple key would return just one element.
func (n *Node) Key() Iterator {
	switch n.Kind {
	case KeyValue:
		value := n.Child()
		if !value.Valid() {
			panic(fmt.Errorf("KeyValue should have at least two children"))
		}
		return Iterator{node: value.Next()}
	case Table, ArrayTable:
		return Iterator{node: n.Child()}
	default:
		panic(fmt.Errorf("Key() is not supported on a %s", n.Kind))
	}
}

// Value returns a pointer to the value node of a KeyValue.
// Guaranteed to be non-nil.  Panics if not called on a KeyValue node,
// or if the Children are malformed.
func (n *Node) Value() *Node {
	return n.Child()
}

// Children returns an iterator over a node's children.
func (n *Node) Children() Iterator {
	return Iterator{node: n.Child()}
}