diff --git a/errors.go b/errors.go index fdd8d36..718f8d9 100644 --- a/errors.go +++ b/errors.go @@ -99,7 +99,7 @@ func (e *DecodeError) Key() Key { // //nolint:funlen func wrapDecodeError(document []byte, de *unstable.ParserError) *DecodeError { - offset := subsliceOffset(document, de.Highlight) + offset := unstable.SubsliceOffset(document, de.Highlight) errMessage := de.Error() errLine, errColumn := positionAtEnd(document[:offset]) @@ -261,17 +261,3 @@ func positionAtEnd(b []byte) (row int, column int) { return row, column } - -// subsliceOffset finds the byte offset of subslice within data by -// scanning for the matching element address. -func subsliceOffset(data []byte, subslice []byte) int { - if len(subslice) == 0 { - return len(data) - } - for i := range data { - if &data[i] == &subslice[0] { - return i - } - } - panic("subslice is not within data") -} diff --git a/unstable/ast.go b/unstable/ast.go index 6b21592..fc3226a 100644 --- a/unstable/ast.go +++ b/unstable/ast.go @@ -90,6 +90,21 @@ type Range struct { Length uint32 } +// SubsliceOffset returns the byte offset of subslice within data. +// Subslice must be a subslice of data, meaning it must point into the +// same backing array. Panics if subslice is not within data. +func SubsliceOffset(data []byte, subslice []byte) int { + if len(subslice) == 0 { + return len(data) + } + for i := range data { + if &data[i] == &subslice[0] { + return i + } + } + panic("subslice is not within data") +} + // Next returns a pointer to the next node, or nil if there is no next node. func (n *Node) Next() *Node { if n.next < 0 { diff --git a/unstable/parser.go b/unstable/parser.go index 4b826ff..82c85de 100644 --- a/unstable/parser.go +++ b/unstable/parser.go @@ -69,8 +69,8 @@ func (p *Parser) Data() []byte { // panics. func (p *Parser) Range(b []byte) Range { return Range{ - Offset: uint32(p.subsliceOffset(b)), //nolint:gosec // TOML documents are small - Length: uint32(len(b)), //nolint:gosec // TOML documents are small + Offset: uint32(SubsliceOffset(p.data, b)), //nolint:gosec // TOML documents are small + Length: uint32(len(b)), //nolint:gosec // TOML documents are small } } @@ -82,20 +82,6 @@ func (p *Parser) rangeOfToken(token, rest []byte) Range { return Range{Offset: uint32(offset), Length: uint32(len(token))} //nolint:gosec // TOML documents are small } -// subsliceOffset finds the byte offset of subslice b within p.data -// by scanning for the matching element address. -func (p *Parser) subsliceOffset(b []byte) int { - if len(b) == 0 { - return len(p.data) - } - for i := range p.data { - if &p.data[i] == &b[0] { - return i - } - } - panic("subslice is not within parser data") -} - // Raw returns the slice corresponding to the bytes in the given range. func (p *Parser) Raw(raw Range) []byte { return p.data[raw.Offset : raw.Offset+raw.Length]