]> Cypherpunks repositories - gostls13.git/commitdiff
bytes: add Clone function
authorMartin Möhrmann <martin@golang.org>
Sun, 31 Oct 2021 09:04:03 +0000 (10:04 +0100)
committerMartin Möhrmann <martin@golang.org>
Mon, 15 Aug 2022 19:17:20 +0000 (19:17 +0000)
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 #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>
api/next/45038.txt [new file with mode: 0644]
src/bytes/bytes.go
src/bytes/bytes_test.go

diff --git a/api/next/45038.txt b/api/next/45038.txt
new file mode 100644 (file)
index 0000000..64c3f5f
--- /dev/null
@@ -0,0 +1 @@
+pkg bytes, func Clone([]uint8) []uint8 #45038
index 659a82bcc8c95b39823c2ad53c1080caa284dbf6..27834fc6db723e5b378c96f52a7fa9f66d5db974 100644 (file)
@@ -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...)
+}
index b407fe8a2d91e11aec4cd6c84731b3fdf74c7854..392657d1fada7a347d4b83b230e0b549f5ea2692 100644 (file)
@@ -15,6 +15,7 @@ import (
        "testing"
        "unicode"
        "unicode/utf8"
+       "unsafe"
 )
 
 func eq(a, b []string) bool {
@@ -2118,3 +2119,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)
+               }
+       }
+}