diff options
Diffstat (limited to 'vendor/github.com/authzed/spicedb/pkg/schemadsl/input/inputsource.go')
| -rw-r--r-- | vendor/github.com/authzed/spicedb/pkg/schemadsl/input/inputsource.go | 224 |
1 files changed, 224 insertions, 0 deletions
diff --git a/vendor/github.com/authzed/spicedb/pkg/schemadsl/input/inputsource.go b/vendor/github.com/authzed/spicedb/pkg/schemadsl/input/inputsource.go new file mode 100644 index 0000000..3bd0437 --- /dev/null +++ b/vendor/github.com/authzed/spicedb/pkg/schemadsl/input/inputsource.go @@ -0,0 +1,224 @@ +package input + +import ( + "fmt" +) + +// BytePosition represents the byte position in a piece of code. +type BytePosition int + +// Position represents a position in an arbitrary source file. +type Position struct { + // LineNumber is the 0-indexed line number. + LineNumber int + + // ColumnPosition is the 0-indexed column position on the line. + ColumnPosition int +} + +// Source represents the path of a source file. +type Source string + +// RangeForRunePosition returns a source range over this source file. +func (is Source) RangeForRunePosition(runePosition int, mapper PositionMapper) SourceRange { + return is.RangeForRunePositions(runePosition, runePosition, mapper) +} + +// PositionForRunePosition returns a source position over this source file. +func (is Source) PositionForRunePosition(runePosition int, mapper PositionMapper) SourcePosition { + return runeIndexedPosition{is, mapper, runePosition} +} + +// PositionFromLineAndColumn returns a source position at the given line and column in this source file. +func (is Source) PositionFromLineAndColumn(lineNumber int, columnPosition int, mapper PositionMapper) SourcePosition { + return lcIndexedPosition{is, mapper, Position{lineNumber, columnPosition}} +} + +// RangeForRunePositions returns a source range over this source file. +func (is Source) RangeForRunePositions(startRune int, endRune int, mapper PositionMapper) SourceRange { + return sourceRange{is, runeIndexedPosition{is, mapper, startRune}, runeIndexedPosition{is, mapper, endRune}} +} + +// RangeForLineAndColPositions returns a source range over this source file. +func (is Source) RangeForLineAndColPositions(start Position, end Position, mapper PositionMapper) SourceRange { + return sourceRange{is, lcIndexedPosition{is, mapper, start}, lcIndexedPosition{is, mapper, end}} +} + +// PositionMapper defines an interface for converting rune position <-> line+col position +// under source files. +type PositionMapper interface { + // RunePositionToLineAndCol converts the given 0-indexed rune position under the given source file + // into a 0-indexed line number and column position. + RunePositionToLineAndCol(runePosition int, path Source) (int, int, error) + + // LineAndColToRunePosition converts the given 0-indexed line number and column position under the + // given source file into a 0-indexed rune position. + LineAndColToRunePosition(lineNumber int, colPosition int, path Source) (int, error) + + // TextForLine returns the text for the specified line number. + TextForLine(lineNumber int, path Source) (string, error) +} + +// SourceRange represents a range inside a source file. +type SourceRange interface { + // Source is the input source for this range. + Source() Source + + // Start is the starting position of the source range. + Start() SourcePosition + + // End is the ending position (inclusive) of the source range. If the same as the Start, + // this range represents a single position. + End() SourcePosition + + // ContainsPosition returns true if the given range contains the given position. + ContainsPosition(position SourcePosition) (bool, error) + + // AtStartPosition returns a SourceRange located only at the starting position of this range. + AtStartPosition() SourceRange + + // String returns a (somewhat) human-readable form of the range. + String() string +} + +// SourcePosition represents a single position in a source file. +type SourcePosition interface { + // Source is the input source for this position. + Source() Source + + // RunePosition returns the 0-indexed rune position in the source file. + RunePosition() (int, error) + + // LineAndColumn returns the 0-indexed line number and column position in the source file. + LineAndColumn() (int, int, error) + + // LineText returns the text of the line for this position. + LineText() (string, error) + + // String returns a (somewhat) human-readable form of the position. + String() string +} + +// sourceRange implements the SourceRange interface. +type sourceRange struct { + source Source + start SourcePosition + end SourcePosition +} + +func (sr sourceRange) Source() Source { + return sr.source +} + +func (sr sourceRange) Start() SourcePosition { + return sr.start +} + +func (sr sourceRange) End() SourcePosition { + return sr.end +} + +func (sr sourceRange) AtStartPosition() SourceRange { + return sourceRange{sr.source, sr.start, sr.end} +} + +func (sr sourceRange) ContainsPosition(position SourcePosition) (bool, error) { + if position.Source() != sr.source { + return false, nil + } + + startRune, err := sr.start.RunePosition() + if err != nil { + return false, err + } + + endRune, err := sr.end.RunePosition() + if err != nil { + return false, err + } + + positionRune, err := position.RunePosition() + if err != nil { + return false, err + } + + return positionRune >= startRune && positionRune <= endRune, nil +} + +func (sr sourceRange) String() string { + return fmt.Sprintf("%v -> %v", sr.start, sr.end) +} + +// runeIndexedPosition implements the SourcePosition interface over a rune position. +type runeIndexedPosition struct { + source Source + mapper PositionMapper + runePosition int +} + +func (ris runeIndexedPosition) Source() Source { + return ris.source +} + +func (ris runeIndexedPosition) RunePosition() (int, error) { + return ris.runePosition, nil +} + +func (ris runeIndexedPosition) LineAndColumn() (int, int, error) { + if ris.runePosition == 0 { + return 0, 0, nil + } + if ris.mapper == nil { + return -1, -1, fmt.Errorf("nil mapper") + } + return ris.mapper.RunePositionToLineAndCol(ris.runePosition, ris.source) +} + +func (ris runeIndexedPosition) String() string { + return fmt.Sprintf("%s@%v (rune)", ris.source, ris.runePosition) +} + +func (ris runeIndexedPosition) LineText() (string, error) { + lineNumber, _, err := ris.LineAndColumn() + if err != nil { + return "", err + } + + return ris.mapper.TextForLine(lineNumber, ris.source) +} + +// lcIndexedPosition implements the SourcePosition interface over a line and colu,n position. +type lcIndexedPosition struct { + source Source + mapper PositionMapper + lcPosition Position +} + +func (lcip lcIndexedPosition) Source() Source { + return lcip.source +} + +func (lcip lcIndexedPosition) String() string { + return fmt.Sprintf("%s@%v:%v (line/col)", lcip.source, lcip.lcPosition.LineNumber, lcip.lcPosition.ColumnPosition) +} + +func (lcip lcIndexedPosition) RunePosition() (int, error) { + if lcip.lcPosition.LineNumber == 0 && lcip.lcPosition.ColumnPosition == 0 { + return 0, nil + } + if lcip.mapper == nil { + return -1, fmt.Errorf("nil mapper") + } + return lcip.mapper.LineAndColToRunePosition(lcip.lcPosition.LineNumber, lcip.lcPosition.ColumnPosition, lcip.source) +} + +func (lcip lcIndexedPosition) LineAndColumn() (int, int, error) { + return lcip.lcPosition.LineNumber, lcip.lcPosition.ColumnPosition, nil +} + +func (lcip lcIndexedPosition) LineText() (string, error) { + if lcip.mapper == nil { + return "", fmt.Errorf("nil mapper") + } + return lcip.mapper.TextForLine(lcip.lcPosition.LineNumber, lcip.source) +} |
