add slicing/indexing for bytes kind

This commit is contained in:
Fabio Bozzo
2024-10-24 12:27:01 +02:00
parent a8780f750c
commit 00ff88ef23
3 changed files with 72 additions and 56 deletions

View File

@@ -413,42 +413,6 @@ func TestParse(t *testing.T) {
fmt.Println(err)
})
t.Run("index out of range", func(t *testing.T) {
sel, err := Parse(".[1000]")
require.NoError(t, err)
require.Equal(t, 2, len(sel))
require.True(t, sel[0].Identity())
require.False(t, sel[0].Optional())
require.False(t, sel[0].Iterator())
require.Empty(t, sel[0].Slice())
require.Empty(t, sel[0].Field())
require.Empty(t, sel[0].Index())
require.False(t, sel[1].Identity())
require.False(t, sel[1].Optional())
require.False(t, sel[1].Iterator())
require.Empty(t, sel[1].Slice())
require.Empty(t, sel[1].Field())
require.Equal(t, sel[1].Index(), 1000)
})
t.Run("negative index out of range", func(t *testing.T) {
sel, err := Parse(".[-1000]")
require.NoError(t, err)
require.Equal(t, 2, len(sel))
require.True(t, sel[0].Identity())
require.False(t, sel[0].Optional())
require.False(t, sel[0].Iterator())
require.Empty(t, sel[0].Slice())
require.Empty(t, sel[0].Field())
require.Empty(t, sel[0].Index())
require.False(t, sel[1].Identity())
require.False(t, sel[1].Optional())
require.False(t, sel[1].Iterator())
require.Empty(t, sel[1].Slice())
require.Empty(t, sel[1].Field())
require.Equal(t, sel[1].Index(), -1000)
})
t.Run("slice with negative start and positive end", func(t *testing.T) {
sel, err := Parse(".[0:-2]")
require.NoError(t, err)

View File

@@ -3,7 +3,6 @@ package selector
import (
"errors"
"fmt"
"math"
"strconv"
"strings"
@@ -229,7 +228,7 @@ func resolve(sel Selector, subject ipld.Node, at []string) (ipld.Node, error) {
idx = len(b) + idx
}
if idx < 0 || idx >= len(b) {
err := newResolutionError(fmt.Sprintf("index out of bounds: %d", seg.Index()), at)
err := newResolutionError(fmt.Sprintf("index %d out of bounds for bytes of length %d", seg.Index(), len(b)), at)
return nil, errIfNotOptional(seg, err)
}
cur = basicnode.NewInt(int64(b[idx]))
@@ -263,32 +262,33 @@ func resolveSliceIndices(slice []int64, length int64) (start int64, end int64) {
start, end = slice[0], slice[1]
// adjust boundaries
switch {
case slice[0] == math.MinInt:
start = 0
case slice[0] < 0:
start = length + slice[0]
// clamp start index
if start < 0 {
start = length + start
if start < 0 {
start = 0
}
}
switch {
case slice[1] == math.MaxInt:
end = length
case slice[1] < 0:
end = length + slice[1]
if start > length {
start = length
}
// backward iteration is not allowed, shortcut to an empty result
if start >= end {
start, end = 0, 0
}
// clamp out of bound
if start < 0 {
start = 0
// clamp end index
if end < 0 {
end = length + end
if end < 0 {
end = 0
}
}
if end > length {
end = length
}
// handle backward slicing
if start > end {
start, end = 0, 0
}
return start, end
}

View File

@@ -246,6 +246,58 @@ func TestSelect(t *testing.T) {
require.NoError(t, err)
require.Equal(t, 2, int(must.Int(val))) // Assert sliced value at index 1
})
t.Run("slice on bytes", func(t *testing.T) {
sel, err := Parse(`.[1:3]`)
require.NoError(t, err)
node := basicnode.NewBytes([]byte{0x01, 0x02, 0x03, 0x04, 0x05})
res, err := sel.Select(node)
require.NoError(t, err)
require.NotEmpty(t, res)
bytes, err := res.AsBytes()
require.NoError(t, err)
require.Equal(t, []byte{0x02, 0x03}, bytes) // assert sliced bytes
})
t.Run("index on bytes", func(t *testing.T) {
sel, err := Parse(`.[2]`)
require.NoError(t, err)
node := basicnode.NewBytes([]byte{0x01, 0x02, 0x03, 0x04, 0x05})
res, err := sel.Select(node)
require.NoError(t, err)
require.NotEmpty(t, res)
val, err := res.AsInt()
require.NoError(t, err)
require.Equal(t, int64(0x03), val) // assert indexed byte value
})
t.Run("out of bounds slicing on bytes", func(t *testing.T) {
sel, err := Parse(`.[10:20]`)
require.NoError(t, err)
node := basicnode.NewBytes([]byte{0x01, 0x02, 0x03})
res, err := sel.Select(node)
require.NoError(t, err)
require.NotNil(t, res)
bytes, err := res.AsBytes()
require.NoError(t, err)
require.Empty(t, bytes) // assert empty result for out of bounds slice
})
t.Run("out of bounds indexing on bytes", func(t *testing.T) {
sel, err := Parse(`.[10]`)
require.NoError(t, err)
node := basicnode.NewBytes([]byte{0x01, 0x02, 0x03})
_, err = sel.Select(node)
require.Error(t, err)
require.Contains(t, err.Error(), "can not resolve path: .10") // assert error for out of bounds index
})
}
func FuzzParse(f *testing.F) {