summaryrefslogtreecommitdiffstats
path: root/vendor/github.com/pelletier/go-toml/v2/unstable/ast.go
blob: f526bf2c090fda81eb2457c3b25898b1eb6f0bed (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
package unstable

import (
	"fmt"
	"unsafe"

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

// Iterator over a sequence of nodes.
//
// Starts uninitialized, you need to call Next() first.
//
// For example:
//
//	it := n.Children()
//	for it.Next() {
//		n := it.Node()
//		// do something with n
//	}
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 calls to Next() will return false.
func (c *Iterator) IsLast() bool {
	return c.node.next == 0
}

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

// Node in a TOML expression AST.
//
// Depending on Kind, its sequence of children should be interpreted
// differently.
//
//   - Array have one child per element in the array.
//   - InlineTable have one child per key-value in the table (each of kind
//     InlineTable).
//   - KeyValue have at least two children. The first one is the value. The rest
//     make a potentially dotted key.
//   - Table and ArrayTable's children represent a dotted key (same as
//     KeyValue, but without the first node being the value).
//
// When relevant, Raw describes the range of bytes this node is referring to in
// the input document. Use Parser.Raw() to retrieve the actual bytes.
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
}

// Range of bytes in the document.
type Range struct {
	Offset uint32
	Length uint32
}

// Next returns a pointer to the next node, or nil 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 pointer to the first child node of this node. Other children
// can be accessed calling Next on the first child.  Returns an nil if this Node
// has no child.
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 children 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()}
}