diff --git a/internal/util/xslices/slices.go b/internal/util/xslices/slices.go index 9da716a36..1c1c159b2 100644 --- a/internal/util/xslices/slices.go +++ b/internal/util/xslices/slices.go @@ -28,11 +28,14 @@ // which simply guarantees extra through append() which // may allocate more than necessary extra size. func GrowJust[T any](in []T, size int) []T { + if cap(in)-len(in) < size { + // Reallocate enough for in + size. in2 := make([]T, len(in), len(in)+size) _ = copy(in2, in) in = in2 } + return in } @@ -42,14 +45,20 @@ func GrowJust[T any](in []T, size int) []T { // will append extra, in a manner to reduce the need // for new allocations on every call to append. func AppendJust[T any](in []T, extra ...T) []T { - if cap(in)-len(in) < len(extra) { - in2 := make([]T, len(in)+len(extra)) + l := len(in) + + if cap(in)-l < len(extra) { + // Reallocate enough for + extra. + in2 := make([]T, l+len(extra)) _ = copy(in2, in) in = in2 } else { - in = in[:len(in)+len(extra)] + // Reslice for + extra. + in = in[:l+len(extra)] } - _ = copy(in[len(in):], extra) + + // Copy extra into slice. + _ = copy(in[l:], extra) return in } diff --git a/internal/util/xslices/slices_test.go b/internal/util/xslices/slices_test.go index d4c87ba53..7c62ac77f 100644 --- a/internal/util/xslices/slices_test.go +++ b/internal/util/xslices/slices_test.go @@ -18,6 +18,7 @@ package xslices_test import ( + "math/rand" "net/url" "slices" "testing" @@ -57,12 +58,27 @@ func TestAppendJust(t *testing.T) { for _, l := range []int{0, 2, 4, 8, 16, 32, 64} { for _, x := range []int{0, 2, 4, 8, 16, 32, 64} { s := make([]int, l, l+x) + + // Randomize slice. + for i := range s { + s[i] = rand.Int() + } + for _, a := range []int{0, 2, 4, 8, 16, 32, 64} { toAppend := make([]int, a) + + // Randomize appended vals. + for i := range toAppend { + toAppend[i] = rand.Int() + } + s2 := xslices.AppendJust(s, toAppend...) // Slice length should be as expected. - assert.Equal(t, len(s2), len(s)+a) + assert.Equal(t, len(s)+a, len(s2)) + + // Slice contents should be as expected. + assert.Equal(t, append(s, toAppend...), s2) switch { // If slice already has capacity for @@ -74,7 +90,7 @@ func TestAppendJust(t *testing.T) { // have capacity for original length // plus extra elements, NOTHING MORE. default: - assert.Equal(t, cap(s2), len(s)+a) + assert.Equal(t, len(s)+a, cap(s2)) } } }