Skip to content

Commit

Permalink
bytes: add Clone function
Browse files Browse the repository at this point in the history
The new Clone function returns a copy of b[:len(b)]
for the input byte slice b.
The result may have additional unused capacity.
Clone(nil) returns nil.

Fixes golang#45038

Change-Id: I0469a202d77a7b491f1341c08915d07ddd1f0300
Reviewed-on: https://go-review.googlesource.com/c/go/+/359675
Run-TryBot: Martin Möhrmann <martin@golang.org>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Joseph Tsai <joetsai@digital-static.net>
Reviewed-by: Martin Möhrmann <moehrmann@google.com>
Reviewed-by: Ian Lance Taylor <iant@google.com>
(cherry picked from commit 7b45edb)
  • Loading branch information
Martin Möhrmann authored and tmm1 committed May 26, 2023
1 parent 768170e commit e93b412
Show file tree
Hide file tree
Showing 3 changed files with 44 additions and 0 deletions.
1 change: 1 addition & 0 deletions api/next/45038.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
pkg bytes, func Clone([]uint8) []uint8 #45038
10 changes: 10 additions & 0 deletions src/bytes/bytes.go
Original file line number Diff line number Diff line change
Expand Up @@ -1299,3 +1299,13 @@ func Cut(s, sep []byte) (before, after []byte, found bool) {
}
return s, nil, false
}

// Clone returns a copy of b[:len(b)].
// The result may have additional unused capacity.
// Clone(nil) returns nil.
func Clone(b []byte) []byte {
if b == nil {
return nil
}
return append([]byte{}, b...)
}
33 changes: 33 additions & 0 deletions src/bytes/bytes_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import (
"testing"
"unicode"
"unicode/utf8"
"unsafe"
)

func eq(a, b []string) bool {
Expand Down Expand Up @@ -2116,3 +2117,35 @@ func BenchmarkIndexPeriodic(b *testing.B) {
})
}
}

func TestClone(t *testing.T) {
var cloneTests = [][]byte{
[]byte(nil),
[]byte{},
Clone([]byte{}),
[]byte(strings.Repeat("a", 42))[:0],
[]byte(strings.Repeat("a", 42))[:0:0],
[]byte("short"),
[]byte(strings.Repeat("a", 42)),
}
for _, input := range cloneTests {
clone := Clone(input)
if !Equal(clone, input) {
t.Errorf("Clone(%q) = %q; want %q", input, clone, input)
}

if input == nil && clone != nil {
t.Errorf("Clone(%#v) return value should be equal to nil slice.", input)
}

if input != nil && clone == nil {
t.Errorf("Clone(%#v) return value should not be equal to nil slice.", input)
}

inputHeader := (*reflect.SliceHeader)(unsafe.Pointer(&input))
cloneHeader := (*reflect.SliceHeader)(unsafe.Pointer(&clone))
if cap(input) != 0 && cloneHeader.Data == inputHeader.Data {
t.Errorf("Clone(%q) return value should not reference inputs backing memory.", input)
}
}
}

0 comments on commit e93b412

Please sign in to comment.