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 (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"reflect"
|
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
@@ -100,10 +99,8 @@ func (e *DecodeError) Key() Key {
|
|||||||
//
|
//
|
||||||
//nolint:funlen
|
//nolint:funlen
|
||||||
func wrapDecodeError(document []byte, de *unstable.ParserError) *DecodeError {
|
func wrapDecodeError(document []byte, de *unstable.ParserError) *DecodeError {
|
||||||
var offset int
|
offset, ok := de.Offset()
|
||||||
if o, ok := de.Offset(); ok {
|
if !ok {
|
||||||
offset = o
|
|
||||||
} else {
|
|
||||||
offset = subsliceOffset(document, de.Highlight)
|
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.
|
// subsliceOffset returns the byte offset of subslice within data.
|
||||||
// subslice must share the same backing array as data.
|
// subslice must share the same backing array as data.
|
||||||
func subsliceOffset(data []byte, subslice []byte) int {
|
func subsliceOffset(data []byte, subslice []byte) int {
|
||||||
if len(subslice) == 0 {
|
return cap(data) - cap(subslice)
|
||||||
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
|
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-11
@@ -4,7 +4,6 @@ import (
|
|||||||
"bytes"
|
"bytes"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"reflect"
|
|
||||||
"unicode"
|
"unicode"
|
||||||
|
|
||||||
"github.com/pelletier/go-toml/v2/internal/characters"
|
"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.
|
// subsliceOffset returns the byte offset of subslice b within p.data.
|
||||||
// b must share the same backing array as p.data.
|
// b must share the same backing array as p.data.
|
||||||
func (p *Parser) subsliceOffset(b []byte) int {
|
func (p *Parser) subsliceOffset(b []byte) int {
|
||||||
if len(b) == 0 {
|
return cap(p.data) - cap(b)
|
||||||
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
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Raw returns the slice corresponding to the bytes in the given range.
|
// Raw returns the slice corresponding to the bytes in the given range.
|
||||||
|
|||||||
Reference in New Issue
Block a user