Replace reflect-based subslice offset with cap arithmetic
Use cap(parent) - cap(subslice) to compute byte offsets between slices that share a backing array. This is safe pure Go: subslicing preserves the backing array and adjusts the capacity accordingly, so the difference in capacities equals the byte offset. This removes the reflect import from both errors.go and unstable/parser.go, eliminating the last reflect-based pointer arithmetic used for error position tracking. Co-authored-by: Thomas Pelletier <thomas@pelletier.dev>
This commit is contained in:
@@ -2,7 +2,6 @@ package toml
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
@@ -100,10 +99,8 @@ func (e *DecodeError) Key() Key {
|
||||
//
|
||||
//nolint:funlen
|
||||
func wrapDecodeError(document []byte, de *unstable.ParserError) *DecodeError {
|
||||
var offset int
|
||||
if o, ok := de.Offset(); ok {
|
||||
offset = o
|
||||
} else {
|
||||
offset, ok := de.Offset()
|
||||
if !ok {
|
||||
offset = subsliceOffset(document, de.Highlight)
|
||||
}
|
||||
|
||||
@@ -271,18 +268,5 @@ func positionAtEnd(b []byte) (row int, column int) {
|
||||
// subsliceOffset returns the byte offset of subslice within data.
|
||||
// subslice must share the same backing array as data.
|
||||
func subsliceOffset(data []byte, subslice []byte) int {
|
||||
if len(subslice) == 0 {
|
||||
return 0
|
||||
}
|
||||
|
||||
// Use reflect to get the data pointers of both slices.
|
||||
// This is safe because we're only reading the pointer values for comparison.
|
||||
dataPtr := reflect.ValueOf(data).Pointer()
|
||||
subPtr := reflect.ValueOf(subslice).Pointer()
|
||||
|
||||
offset := int(subPtr - dataPtr)
|
||||
if offset < 0 || offset > len(data) {
|
||||
panic("subslice is not within data")
|
||||
}
|
||||
return offset
|
||||
return cap(data) - cap(subslice)
|
||||
}
|
||||
|
||||
+1
-11
@@ -4,7 +4,6 @@ import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"unicode"
|
||||
|
||||
"github.com/pelletier/go-toml/v2/internal/characters"
|
||||
@@ -105,16 +104,7 @@ func (p *Parser) rangeOfToken(token, rest []byte) Range {
|
||||
// subsliceOffset returns the byte offset of subslice b within p.data.
|
||||
// b must share the same backing array as p.data.
|
||||
func (p *Parser) subsliceOffset(b []byte) int {
|
||||
if len(b) == 0 {
|
||||
return 0
|
||||
}
|
||||
dataPtr := reflect.ValueOf(p.data).Pointer()
|
||||
subPtr := reflect.ValueOf(b).Pointer()
|
||||
offset := int(subPtr - dataPtr)
|
||||
if offset < 0 || offset > len(p.data) {
|
||||
panic("subslice is not within parser data")
|
||||
}
|
||||
return offset
|
||||
return cap(p.data) - cap(b)
|
||||
}
|
||||
|
||||
// Raw returns the slice corresponding to the bytes in the given range.
|
||||
|
||||
Reference in New Issue
Block a user