Skip to content

Commit 80a9825

Browse files
committed
perf: allow FASS strides on nested homogeneous object arrays
Stop disabling equal-size array strides when elements contain nested object-arrays. Confirm+landing skipContainer checks already prevent false jumps; GitHub-style issues[].labels[] can now stride like flat user lists.
1 parent ec3f3d9 commit 80a9825

2 files changed

Lines changed: 35 additions & 29 deletions

File tree

navigate.go

Lines changed: 1 addition & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -249,34 +249,6 @@ func firstKeyEqual(data []byte, obj int, ks, ke int) bool {
249249
return true
250250
}
251251

252-
func hasNestedObjectArray(data []byte, start, end int) bool {
253-
i := start + 1
254-
for i < end {
255-
c := data[i]
256-
if c == '"' {
257-
e, ok := skipStringBody(data, i+1)
258-
if !ok || e > end {
259-
return false
260-
}
261-
i = e
262-
continue
263-
}
264-
if c == '[' {
265-
j := i + 1
266-
for j < end {
267-
cj := data[j]
268-
if cj == ' ' || cj == 9 || cj == 10 || cj == 13 {
269-
j++
270-
continue
271-
}
272-
return cj == '{'
273-
}
274-
return false
275-
}
276-
i++
277-
}
278-
return false
279-
}
280252
func strideObject(data []byte, i, lastLen, nlen int, ks, ke int, haveKey bool) (int, bool) {
281253
if lastLen < 2 {
282254
return i, false
@@ -494,7 +466,7 @@ func findIndexObjectStride(data []byte, i, n, nlen int) (int, bool) {
494466
}
495467
}
496468
if !strideOK && lastLen > 0 {
497-
strideOK = !hasNestedObjectArray(data, start, start+lastLen)
469+
strideOK = true
498470
}
499471
}
500472
if i >= nlen {

navigate_stride_test.go

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,3 +164,37 @@ func TestFindIndexStrideRejectsFalseEqualSize(t *testing.T) {
164164
t.Fatalf("valid equal-size still works: %q %v", v, err)
165165
}
166166
}
167+
168+
func TestFindIndexStrideGitHubLikeIssues(t *testing.T) {
169+
var b strings.Builder
170+
b.WriteByte('[')
171+
for i := 0; i < 120; i++ {
172+
if i > 0 {
173+
b.WriteByte(',')
174+
}
175+
fmt.Fprintf(&b, `{"id":%d,"number":%d,"title":"Issue number %d","state":"open",`, 1000+i, i, i)
176+
fmt.Fprintf(&b, `"user":{"login":"user%d","id":%d,"type":"User"},`, i, 2000+i)
177+
fmt.Fprintf(&b, `"labels":[{"id":%d,"name":"bug","color":"f29513"},{"id":%d,"name":"help wanted","color":"159818"}],`, i, i+1)
178+
fmt.Fprintf(&b, `"comments":%d,"body":"body %d"}`, i%30, i)
179+
}
180+
b.WriteByte(']')
181+
data := []byte(b.String())
182+
for _, n := range []int{0, 1, 9, 10, 50, 99, 100, 119} {
183+
v, _, _, err := Get(data, "["+strconv.Itoa(n)+"]", "title")
184+
if err != nil {
185+
t.Fatalf("n=%d: %v", n, err)
186+
}
187+
want := "Issue number " + strconv.Itoa(n)
188+
if string(v) != want {
189+
t.Fatalf("n=%d title=%q want %q", n, v, want)
190+
}
191+
u, _, _, err := Get(data, "["+strconv.Itoa(n)+"]", "user", "login")
192+
if err != nil || string(u) != "user"+strconv.Itoa(n) {
193+
t.Fatalf("n=%d user=%q err=%v", n, u, err)
194+
}
195+
lab, _, _, err := Get(data, "["+strconv.Itoa(n)+"]", "labels", "[1]", "name")
196+
if err != nil || string(lab) != "help wanted" {
197+
t.Fatalf("n=%d label=%q err=%v", n, lab, err)
198+
}
199+
}
200+
}

0 commit comments

Comments
 (0)