diff options
| author | mo khan <mo@mokhan.ca> | 2025-07-22 17:35:49 -0600 |
|---|---|---|
| committer | mo khan <mo@mokhan.ca> | 2025-07-22 17:35:49 -0600 |
| commit | 20ef0d92694465ac86b550df139e8366a0a2b4fa (patch) | |
| tree | 3f14589e1ce6eb9306a3af31c3a1f9e1af5ed637 /vendor/github.com/authzed/spicedb/pkg/composableschemadsl/input/sourcepositionmapper.go | |
| parent | 44e0d272c040cdc53a98b9f1dc58ae7da67752e6 (diff) | |
feat: connect to spicedb
Diffstat (limited to 'vendor/github.com/authzed/spicedb/pkg/composableschemadsl/input/sourcepositionmapper.go')
| -rw-r--r-- | vendor/github.com/authzed/spicedb/pkg/composableschemadsl/input/sourcepositionmapper.go | 95 |
1 files changed, 95 insertions, 0 deletions
diff --git a/vendor/github.com/authzed/spicedb/pkg/composableschemadsl/input/sourcepositionmapper.go b/vendor/github.com/authzed/spicedb/pkg/composableschemadsl/input/sourcepositionmapper.go new file mode 100644 index 0000000..1bca03c --- /dev/null +++ b/vendor/github.com/authzed/spicedb/pkg/composableschemadsl/input/sourcepositionmapper.go @@ -0,0 +1,95 @@ +package input + +import ( + "fmt" + "strings" + + "github.com/emirpasic/gods/trees/redblacktree" +) + +// SourcePositionMapper defines a helper struct for cached, faster lookup of rune position <-> +// (line, column) for a specific source file. +type SourcePositionMapper struct { + // rangeTree holds a tree that maps from rune position to a line and start position. + rangeTree *redblacktree.Tree + + // lineMap holds a map from line number to rune positions for that line. + lineMap map[int]inclusiveRange +} + +// EmptySourcePositionMapper returns an empty source position mapper. +func EmptySourcePositionMapper() SourcePositionMapper { + rangeTree := redblacktree.NewWith(inclusiveComparator) + return SourcePositionMapper{rangeTree, map[int]inclusiveRange{}} +} + +// CreateSourcePositionMapper returns a source position mapper for the contents of a source file. +func CreateSourcePositionMapper(contents []byte) SourcePositionMapper { + lines := strings.Split(string(contents), "\n") + rangeTree := redblacktree.NewWith(inclusiveComparator) + lineMap := map[int]inclusiveRange{} + + currentStart := int(0) + for index, line := range lines { + lineEnd := currentStart + len(line) + rangeTree.Put(inclusiveRange{currentStart, lineEnd}, lineAndStart{index, currentStart}) + lineMap[index] = inclusiveRange{currentStart, lineEnd} + currentStart = lineEnd + 1 + } + + return SourcePositionMapper{rangeTree, lineMap} +} + +type inclusiveRange struct { + start int + end int +} + +type lineAndStart struct { + lineNumber int + startPosition int +} + +func inclusiveComparator(a, b interface{}) int { + i1 := a.(inclusiveRange) + i2 := b.(inclusiveRange) + + if i1.start >= i2.start && i1.end <= i2.end { + return 0 + } + + diff := int64(i1.start) - int64(i2.start) + + if diff < 0 { + return -1 + } + if diff > 0 { + return 1 + } + return 0 +} + +// RunePositionToLineAndCol returns the line number and column position of the rune position in source. +func (spm SourcePositionMapper) RunePositionToLineAndCol(runePosition int) (int, int, error) { + ls, found := spm.rangeTree.Get(inclusiveRange{runePosition, runePosition}) + if !found { + return 0, 0, fmt.Errorf("unknown rune position %v in source file", runePosition) + } + + las := ls.(lineAndStart) + return las.lineNumber, runePosition - las.startPosition, nil +} + +// LineAndColToRunePosition returns the rune position of the line number and column position in source. +func (spm SourcePositionMapper) LineAndColToRunePosition(lineNumber int, colPosition int) (int, error) { + lineRuneInfo, hasLine := spm.lineMap[lineNumber] + if !hasLine { + return 0, fmt.Errorf("unknown line %v in source file", lineNumber) + } + + if colPosition > lineRuneInfo.end-lineRuneInfo.start { + return 0, fmt.Errorf("column position %v not found on line %v in source file", colPosition, lineNumber) + } + + return lineRuneInfo.start + colPosition, nil +} |
