Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 32 additions & 0 deletions test/binSearch.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { describe, expect, it } from 'vitest'
import { binSearch } from '../ui/src/binSearch'

describe('binSearch', () => {
const rows = [
{ ts: 10, label: 'a' },
{ ts: 20, label: 'b' },
{ ts: 30, label: 'c' },
{ ts: 40, label: 'd' },
]

it('returns items inside the inclusive range', () => {
expect(binSearch(rows, 20, 30).map(row => row.label)).toEqual(['b', 'c'])
})

it('handles ranges that start before or end after the array', () => {
expect(binSearch(rows, 0, 20).map(row => row.label)).toEqual(['a', 'b'])
expect(binSearch(rows, 30, 100).map(row => row.label)).toEqual(['c', 'd'])
})

it('returns an empty array when the range misses the array', () => {
expect(binSearch(rows, 0, 5)).toEqual([])
expect(binSearch(rows, 45, 100)).toEqual([])
})

it('handles empty, single-item, and invalid ranges', () => {
expect(binSearch([], 0, 100)).toEqual([])
expect(binSearch([{ ts: 0 }], 0, 0)).toEqual([{ ts: 0 }])
expect(binSearch([{ ts: 0 }], 1, 1)).toEqual([])
expect(binSearch(rows, 30, 20)).toEqual([])
})
})
2 changes: 1 addition & 1 deletion ui/components/TreeNode.vue
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ function fetchTypes() {
function gotoPosition() {
if ('name' in props.tree.line) {
const { path, pos } = props.tree.line.args ?? { path: undefined, pos: undefined }
if (!path || !pos)
if (!path || pos === undefined)
return

sendMessage('gotoPosition', { fileName: path, pos })
Expand Down
44 changes: 18 additions & 26 deletions ui/src/binSearch.ts
Original file line number Diff line number Diff line change
@@ -1,37 +1,29 @@
// arr must be sorted by ts
export function binSearch<T extends { ts: number }>(arr: T[], from: number, to: number): T[] {
if (arr.length === 0 || from > to)
return arr
return []

let idx = Math.trunc(arr.length / 2)
let upperBound = arr.length
let lowerBound = 0
let start = 0
let end = arr.length

while (arr[idx].ts <= to) {
upperBound = idx
idx = Math.trunc(idx / 2)
while (start < end) {
const mid = Math.trunc((start + end) / 2)
if (arr[mid].ts < from)
start = mid + 1
else
end = mid
}

while (arr[idx].ts > to) {
lowerBound = idx
idx = Math.round(idx + (upperBound - idx) / 2)
}

const endPos = lowerBound
const startPos = start

upperBound = lowerBound
lowerBound = 0
while (arr[idx].ts > from) {
lowerBound = idx
idx = Math.round(idx + (upperBound - idx) / 2)
end = arr.length
while (start < end) {
const mid = Math.trunc((start + end) / 2)
if (arr[mid].ts <= to)
start = mid + 1
else
end = mid
}

while (arr[idx].ts <= from) {
upperBound = idx
idx = Math.trunc(idx / 2)
}

const startPos = upperBound

return arr.slice(startPos, endPos + 1)
return arr.slice(startPos, start)
}