Skip to content

Commit e93b412

Browse files
Martin Möhrmanntmm1
Martin Möhrmann
authored andcommitted
bytes: add Clone function
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 <[email protected]> TryBot-Result: Gopher Robot <[email protected]> Reviewed-by: Joseph Tsai <[email protected]> Reviewed-by: Martin Möhrmann <[email protected]> Reviewed-by: Ian Lance Taylor <[email protected]> (cherry picked from commit 7b45edb)
1 parent 768170e commit e93b412

File tree

3 files changed

+44
-0
lines changed

3 files changed

+44
-0
lines changed

api/next/45038.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
pkg bytes, func Clone([]uint8) []uint8 #45038

src/bytes/bytes.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1299,3 +1299,13 @@ func Cut(s, sep []byte) (before, after []byte, found bool) {
12991299
}
13001300
return s, nil, false
13011301
}
1302+
1303+
// Clone returns a copy of b[:len(b)].
1304+
// The result may have additional unused capacity.
1305+
// Clone(nil) returns nil.
1306+
func Clone(b []byte) []byte {
1307+
if b == nil {
1308+
return nil
1309+
}
1310+
return append([]byte{}, b...)
1311+
}

src/bytes/bytes_test.go

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import (
1515
"testing"
1616
"unicode"
1717
"unicode/utf8"
18+
"unsafe"
1819
)
1920

2021
func eq(a, b []string) bool {
@@ -2116,3 +2117,35 @@ func BenchmarkIndexPeriodic(b *testing.B) {
21162117
})
21172118
}
21182119
}
2120+
2121+
func TestClone(t *testing.T) {
2122+
var cloneTests = [][]byte{
2123+
[]byte(nil),
2124+
[]byte{},
2125+
Clone([]byte{}),
2126+
[]byte(strings.Repeat("a", 42))[:0],
2127+
[]byte(strings.Repeat("a", 42))[:0:0],
2128+
[]byte("short"),
2129+
[]byte(strings.Repeat("a", 42)),
2130+
}
2131+
for _, input := range cloneTests {
2132+
clone := Clone(input)
2133+
if !Equal(clone, input) {
2134+
t.Errorf("Clone(%q) = %q; want %q", input, clone, input)
2135+
}
2136+
2137+
if input == nil && clone != nil {
2138+
t.Errorf("Clone(%#v) return value should be equal to nil slice.", input)
2139+
}
2140+
2141+
if input != nil && clone == nil {
2142+
t.Errorf("Clone(%#v) return value should not be equal to nil slice.", input)
2143+
}
2144+
2145+
inputHeader := (*reflect.SliceHeader)(unsafe.Pointer(&input))
2146+
cloneHeader := (*reflect.SliceHeader)(unsafe.Pointer(&clone))
2147+
if cap(input) != 0 && cloneHeader.Data == inputHeader.Data {
2148+
t.Errorf("Clone(%q) return value should not reference inputs backing memory.", input)
2149+
}
2150+
}
2151+
}

0 commit comments

Comments
 (0)