add slicing/indexing for bytes kind
This commit is contained in:
@@ -413,42 +413,6 @@ func TestParse(t *testing.T) {
|
|||||||
fmt.Println(err)
|
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) {
|
t.Run("slice with negative start and positive end", func(t *testing.T) {
|
||||||
sel, err := Parse(".[0:-2]")
|
sel, err := Parse(".[0:-2]")
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ package selector
|
|||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"math"
|
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
@@ -229,7 +228,7 @@ func resolve(sel Selector, subject ipld.Node, at []string) (ipld.Node, error) {
|
|||||||
idx = len(b) + idx
|
idx = len(b) + idx
|
||||||
}
|
}
|
||||||
if idx < 0 || idx >= len(b) {
|
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)
|
return nil, errIfNotOptional(seg, err)
|
||||||
}
|
}
|
||||||
cur = basicnode.NewInt(int64(b[idx]))
|
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]
|
start, end = slice[0], slice[1]
|
||||||
|
|
||||||
// adjust boundaries
|
// clamp start index
|
||||||
switch {
|
if start < 0 {
|
||||||
case slice[0] == math.MinInt:
|
start = length + start
|
||||||
start = 0
|
if start < 0 {
|
||||||
case slice[0] < 0:
|
start = 0
|
||||||
start = length + slice[0]
|
}
|
||||||
}
|
}
|
||||||
switch {
|
if start > length {
|
||||||
case slice[1] == math.MaxInt:
|
start = length
|
||||||
end = length
|
|
||||||
case slice[1] < 0:
|
|
||||||
end = length + slice[1]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// backward iteration is not allowed, shortcut to an empty result
|
// clamp end index
|
||||||
if start >= end {
|
if end < 0 {
|
||||||
start, end = 0, 0
|
end = length + end
|
||||||
}
|
if end < 0 {
|
||||||
// clamp out of bound
|
end = 0
|
||||||
if start < 0 {
|
}
|
||||||
start = 0
|
|
||||||
}
|
}
|
||||||
if end > length {
|
if end > length {
|
||||||
end = length
|
end = length
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// handle backward slicing
|
||||||
|
if start > end {
|
||||||
|
start, end = 0, 0
|
||||||
|
}
|
||||||
|
|
||||||
return start, end
|
return start, end
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -246,6 +246,58 @@ func TestSelect(t *testing.T) {
|
|||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Equal(t, 2, int(must.Int(val))) // Assert sliced value at index 1
|
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) {
|
func FuzzParse(f *testing.F) {
|
||||||
|
|||||||
Reference in New Issue
Block a user