Share semantic document traversal helpers
This commit is contained in:
66
document_walk.go
Normal file
66
document_walk.go
Normal file
@@ -0,0 +1,66 @@
|
||||
package configkit
|
||||
|
||||
import "gitea.maximumdirect.net/eric/ConfigKit/internal/document"
|
||||
|
||||
// walkDocument visits value nodes in preorder, preserving stored mapping order
|
||||
// and sequence index order. Mapping keys are not separate nodes in this walk.
|
||||
// The callback borrows paths and nodes; clone any mutable state it retains.
|
||||
// Specialized origin, pruning, and budget traversals retain their own semantics.
|
||||
func walkDocument(node *document.Node, path Path, visit func(Path, *document.Node)) {
|
||||
if node == nil {
|
||||
return
|
||||
}
|
||||
visit(path, node)
|
||||
switch node.Kind {
|
||||
case document.Mapping:
|
||||
for _, entry := range node.Mapping {
|
||||
walkDocument(entry.Value, path.Key(entry.Key), visit)
|
||||
}
|
||||
case document.Sequence:
|
||||
for index, child := range node.Sequence {
|
||||
walkDocument(child, path.Index(index), visit)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// indexDocument borrows nodes from its caller-owned tree.
|
||||
func indexDocument(node *document.Node, path Path, index map[string]*document.Node) {
|
||||
walkDocument(node, path, func(path Path, node *document.Node) {
|
||||
index[path.String()] = node
|
||||
})
|
||||
}
|
||||
|
||||
func documentAtPath(root *document.Node, path Path) (*document.Node, bool) {
|
||||
if root == nil || !path.valid() {
|
||||
return nil, false
|
||||
}
|
||||
current := root
|
||||
for _, segment := range path.segments {
|
||||
switch current.Kind {
|
||||
case document.Mapping:
|
||||
if segment.kind == pathSegmentIndex {
|
||||
return nil, false
|
||||
}
|
||||
found := false
|
||||
for _, entry := range current.Mapping {
|
||||
if entry.Key == segment.key {
|
||||
current = entry.Value
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
return nil, false
|
||||
}
|
||||
case document.Sequence:
|
||||
index, ok := schemaIndex(segment)
|
||||
if !ok || index >= len(current.Sequence) {
|
||||
return nil, false
|
||||
}
|
||||
current = current.Sequence[index]
|
||||
default:
|
||||
return nil, false
|
||||
}
|
||||
}
|
||||
return current, true
|
||||
}
|
||||
Reference in New Issue
Block a user