Add private canonical path prefix index

This commit is contained in:
2026-10-09 03:30:01 +00:00
parent d34a98d34b
commit db2d8ed217
3 changed files with 220 additions and 1 deletions

View File

@@ -177,7 +177,7 @@ document comparison, and diagnostics.
Validate: `go test ./internal/engine -run 'Resolution|Override|Overlay|Diagnostic|CompareDocument|Provenance'` Validate: `go test ./internal/engine -run 'Resolution|Override|Overlay|Diagnostic|CompareDocument|Provenance'`
and the everyday check. Expected benefit is reduced formatting, not measured CPU. and the everyday check. Expected benefit is reduced formatting, not measured CPU.
## Stage 6: Add a private canonical-pointer prefix index ## Stage 6: Add a private canonical-pointer prefix index — Complete
Scope: one helper plus tests, no caller migration yet. Scope: one helper plus tests, no caller migration yet.

View File

@@ -0,0 +1,138 @@
package engine
type pathPrefixIndex struct {
root pathPrefixNode
}
type pathPrefixNode struct {
children map[string]*pathPrefixNode
ids []int
minimumID int
hasMinimum bool
}
func (node *pathPrefixNode) includeID(id int) {
if !node.hasMinimum || id < node.minimumID {
node.minimumID = id
node.hasMinimum = true
}
}
func (index *pathPrefixIndex) insert(pointer string, id int) {
node := &index.root
node.includeID(id)
visitCanonicalPointerTokens(pointer, func(token string) bool {
if node.children == nil {
node.children = make(map[string]*pathPrefixNode)
}
child := node.children[token]
if child == nil {
child = &pathPrefixNode{}
node.children[token] = child
}
node = child
node.includeID(id)
return true
})
node.ids = append(node.ids, id)
}
func (index *pathPrefixIndex) visitAncestors(pointer string, visit func(int)) {
node := &index.root
for _, id := range node.ids {
visit(id)
}
visitCanonicalPointerTokens(pointer, func(token string) bool {
child := node.children[token]
if child == nil {
return false
}
node = child
for _, id := range node.ids {
visit(id)
}
return true
})
}
func (index *pathPrefixIndex) visitDescendants(pointer string, visit func(int)) {
root := index.nodeAt(pointer)
if root == nil {
return
}
var walk func(*pathPrefixNode)
walk = func(node *pathPrefixNode) {
for _, id := range node.ids {
visit(id)
}
for _, child := range node.children {
walk(child)
}
}
walk(root)
}
func (index *pathPrefixIndex) earliestIntersectingID(pointer string) (int, bool) {
bestID, found := 0, false
consider := func(id int) {
if !found || id < bestID {
bestID = id
found = true
}
}
node := &index.root
for _, id := range node.ids {
consider(id)
}
complete := visitCanonicalPointerTokens(pointer, func(token string) bool {
child := node.children[token]
if child == nil {
return false
}
node = child
for _, id := range node.ids {
consider(id)
}
return true
})
if complete && node.hasMinimum {
consider(node.minimumID)
}
return bestID, found
}
func (index *pathPrefixIndex) nodeAt(pointer string) *pathPrefixNode {
node := &index.root
complete := visitCanonicalPointerTokens(pointer, func(token string) bool {
child := node.children[token]
if child == nil {
return false
}
node = child
return true
})
if !complete {
return nil
}
return node
}
func visitCanonicalPointerTokens(pointer string, visit func(string) bool) bool {
if pointer == "" {
return true
}
start := 1
for {
end := start
for end < len(pointer) && pointer[end] != '/' {
end++
}
if !visit(pointer[start:end]) {
return false
}
if end == len(pointer) {
return true
}
start = end + 1
}
}

View File

@@ -0,0 +1,81 @@
package engine
import (
"slices"
"strings"
"testing"
)
func TestPathPrefixIndexMatchesPointerScans(t *testing.T) {
entries := []struct {
pointer string
id int
}{
{pointer: "", id: 12},
{pointer: "/", id: 9},
{pointer: "/a", id: 6},
{pointer: "/a", id: 2},
{pointer: "/a/b", id: 4},
{pointer: "/a/b/c", id: 0},
{pointer: "/a/bc", id: 10},
{pointer: "/a~1b", id: 3},
{pointer: "/a~0b", id: 1},
{pointer: "/a~01b", id: 5},
{pointer: "/items/0", id: 8},
{pointer: "/items/01", id: 7},
{pointer: "/items/+1", id: 11},
}
var index pathPrefixIndex
for _, entry := range entries {
index.insert(entry.pointer, entry.id)
}
queries := []string{
"", "/", "/a", "/a/b", "/a/b/c", "/a/b/c/d", "/a/bc", "/a/bc/d",
"/a~1b", "/a~0b", "/a~01b", "/items", "/items/0", "/items/01", "/items/1", "/missing",
}
for _, query := range queries {
gotAncestors := make([]int, 0)
index.visitAncestors(query, func(id int) { gotAncestors = append(gotAncestors, id) })
wantAncestors := make([]int, 0)
gotDescendants := make([]int, 0)
wantDescendants := make([]int, 0)
wantEarliest, foundEarliest := 0, false
for _, entry := range entries {
if pointerContainsByString(entry.pointer, query) {
wantAncestors = append(wantAncestors, entry.id)
}
if pointerContainsByString(query, entry.pointer) {
wantDescendants = append(wantDescendants, entry.id)
}
if pointerContainsByString(entry.pointer, query) || pointerContainsByString(query, entry.pointer) {
if !foundEarliest || entry.id < wantEarliest {
wantEarliest, foundEarliest = entry.id, true
}
}
}
index.visitDescendants(query, func(id int) { gotDescendants = append(gotDescendants, id) })
if !slices.Equal(sortedPrefixIDs(gotAncestors), sortedPrefixIDs(wantAncestors)) {
t.Errorf("ancestors(%q) = %v, want %v", query, sortedPrefixIDs(gotAncestors), sortedPrefixIDs(wantAncestors))
}
if !slices.Equal(sortedPrefixIDs(gotDescendants), sortedPrefixIDs(wantDescendants)) {
t.Errorf("descendants(%q) = %v, want %v", query, sortedPrefixIDs(gotDescendants), sortedPrefixIDs(wantDescendants))
}
gotEarliest, gotFound := index.earliestIntersectingID(query)
if gotEarliest != wantEarliest || gotFound != foundEarliest {
t.Errorf("earliestIntersectingID(%q) = %d, %v, want %d, %v", query, gotEarliest, gotFound, wantEarliest, foundEarliest)
}
}
}
func pointerContainsByString(container, descendant string) bool {
if container == "" {
return true
}
return descendant == container || strings.HasPrefix(descendant, container+"/")
}
func sortedPrefixIDs(ids []int) []int {
result := slices.Clone(ids)
slices.Sort(result)
return result
}