make AppendJust() test check for slice contents, fix AppendJust() final copying behaviour

This commit is contained in:
kim 2024-11-08 14:49:33 +00:00
parent 91056bca79
commit c4461809ea
2 changed files with 31 additions and 6 deletions

View file

@ -28,11 +28,14 @@
// which simply guarantees extra through append() which // which simply guarantees extra through append() which
// may allocate more than necessary extra size. // may allocate more than necessary extra size.
func GrowJust[T any](in []T, size int) []T { func GrowJust[T any](in []T, size int) []T {
if cap(in)-len(in) < size { if cap(in)-len(in) < size {
// Reallocate enough for in + size.
in2 := make([]T, len(in), len(in)+size) in2 := make([]T, len(in), len(in)+size)
_ = copy(in2, in) _ = copy(in2, in)
in = in2 in = in2
} }
return in 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 // will append extra, in a manner to reduce the need
// for new allocations on every call to append. // for new allocations on every call to append.
func AppendJust[T any](in []T, extra ...T) []T { func AppendJust[T any](in []T, extra ...T) []T {
if cap(in)-len(in) < len(extra) { l := len(in)
in2 := make([]T, len(in)+len(extra))
if cap(in)-l < len(extra) {
// Reallocate enough for + extra.
in2 := make([]T, l+len(extra))
_ = copy(in2, in) _ = copy(in2, in)
in = in2 in = in2
} else { } 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 return in
} }

View file

@ -18,6 +18,7 @@
package xslices_test package xslices_test
import ( import (
"math/rand"
"net/url" "net/url"
"slices" "slices"
"testing" "testing"
@ -57,12 +58,27 @@ func TestAppendJust(t *testing.T) {
for _, l := range []int{0, 2, 4, 8, 16, 32, 64} { for _, l := range []int{0, 2, 4, 8, 16, 32, 64} {
for _, x := 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) 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} { for _, a := range []int{0, 2, 4, 8, 16, 32, 64} {
toAppend := make([]int, a) toAppend := make([]int, a)
// Randomize appended vals.
for i := range toAppend {
toAppend[i] = rand.Int()
}
s2 := xslices.AppendJust(s, toAppend...) s2 := xslices.AppendJust(s, toAppend...)
// Slice length should be as expected. // 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 { switch {
// If slice already has capacity for // If slice already has capacity for
@ -74,7 +90,7 @@ func TestAppendJust(t *testing.T) {
// have capacity for original length // have capacity for original length
// plus extra elements, NOTHING MORE. // plus extra elements, NOTHING MORE.
default: default:
assert.Equal(t, cap(s2), len(s)+a) assert.Equal(t, len(s)+a, cap(s2))
} }
} }
} }