mirror of
https://github.com/golang/go
synced 2024-11-19 16:54:44 -07:00
reflect: allow Copy to a byte array or byte slice from a string
This somewhat mirrors the special case behavior of the copy built-in. Fixes #22215 Change-Id: Ic353003ad3de659d3a6b4e9d97295b42510f3bf7 Reviewed-on: https://go-review.googlesource.com/70431 Reviewed-by: Ian Lance Taylor <iant@golang.org>
This commit is contained in:
parent
c14dcfda6b
commit
245e386e4c
@ -668,6 +668,47 @@ func TestCopy(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestCopyString(t *testing.T) {
|
||||
t.Run("Slice", func(t *testing.T) {
|
||||
s := bytes.Repeat([]byte{'_'}, 8)
|
||||
val := ValueOf(s)
|
||||
|
||||
n := Copy(val, ValueOf(""))
|
||||
if expecting := []byte("________"); n != 0 || !bytes.Equal(s, expecting) {
|
||||
t.Errorf("got n = %d, s = %s, expecting n = 0, s = %s", n, s, expecting)
|
||||
}
|
||||
|
||||
n = Copy(val, ValueOf("hello"))
|
||||
if expecting := []byte("hello___"); n != 5 || !bytes.Equal(s, expecting) {
|
||||
t.Errorf("got n = %d, s = %s, expecting n = 5, s = %s", n, s, expecting)
|
||||
}
|
||||
|
||||
n = Copy(val, ValueOf("helloworld"))
|
||||
if expecting := []byte("hellowor"); n != 8 || !bytes.Equal(s, expecting) {
|
||||
t.Errorf("got n = %d, s = %s, expecting n = 8, s = %s", n, s, expecting)
|
||||
}
|
||||
})
|
||||
t.Run("Array", func(t *testing.T) {
|
||||
s := [...]byte{'_', '_', '_', '_', '_', '_', '_', '_'}
|
||||
val := ValueOf(&s).Elem()
|
||||
|
||||
n := Copy(val, ValueOf(""))
|
||||
if expecting := []byte("________"); n != 0 || !bytes.Equal(s[:], expecting) {
|
||||
t.Errorf("got n = %d, s = %s, expecting n = 0, s = %s", n, s[:], expecting)
|
||||
}
|
||||
|
||||
n = Copy(val, ValueOf("hello"))
|
||||
if expecting := []byte("hello___"); n != 5 || !bytes.Equal(s[:], expecting) {
|
||||
t.Errorf("got n = %d, s = %s, expecting n = 5, s = %s", n, s[:], expecting)
|
||||
}
|
||||
|
||||
n = Copy(val, ValueOf("helloworld"))
|
||||
if expecting := []byte("hellowor"); n != 8 || !bytes.Equal(s[:], expecting) {
|
||||
t.Errorf("got n = %d, s = %s, expecting n = 8, s = %s", n, s[:], expecting)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func TestCopyArray(t *testing.T) {
|
||||
a := [8]int{1, 2, 3, 4, 10, 9, 8, 7}
|
||||
b := [11]int{11, 22, 33, 44, 1010, 99, 88, 77, 66, 55, 44}
|
||||
|
@ -1864,6 +1864,8 @@ func AppendSlice(s, t Value) Value {
|
||||
// It returns the number of elements copied.
|
||||
// Dst and src each must have kind Slice or Array, and
|
||||
// dst and src must have the same element type.
|
||||
//
|
||||
// As a special case, src can have kind String if the element type of dst is kind Uint8.
|
||||
func Copy(dst, src Value) int {
|
||||
dk := dst.kind()
|
||||
if dk != Array && dk != Slice {
|
||||
@ -1875,14 +1877,20 @@ func Copy(dst, src Value) int {
|
||||
dst.mustBeExported()
|
||||
|
||||
sk := src.kind()
|
||||
var stringCopy bool
|
||||
if sk != Array && sk != Slice {
|
||||
panic(&ValueError{"reflect.Copy", sk})
|
||||
stringCopy = sk == String && dst.typ.Elem().Kind() == Uint8
|
||||
if !stringCopy {
|
||||
panic(&ValueError{"reflect.Copy", sk})
|
||||
}
|
||||
}
|
||||
src.mustBeExported()
|
||||
|
||||
de := dst.typ.Elem()
|
||||
se := src.typ.Elem()
|
||||
typesMustMatch("reflect.Copy", de, se)
|
||||
if !stringCopy {
|
||||
se := src.typ.Elem()
|
||||
typesMustMatch("reflect.Copy", de, se)
|
||||
}
|
||||
|
||||
var ds, ss sliceHeader
|
||||
if dk == Array {
|
||||
@ -1896,8 +1904,13 @@ func Copy(dst, src Value) int {
|
||||
ss.Data = src.ptr
|
||||
ss.Len = src.Len()
|
||||
ss.Cap = ss.Len
|
||||
} else {
|
||||
} else if sk == Slice {
|
||||
ss = *(*sliceHeader)(src.ptr)
|
||||
} else {
|
||||
sh := *(*stringHeader)(src.ptr)
|
||||
ss.Data = sh.Data
|
||||
ss.Len = sh.Len
|
||||
ss.Cap = sh.Len
|
||||
}
|
||||
|
||||
return typedslicecopy(de.common(), ds, ss)
|
||||
|
Loading…
Reference in New Issue
Block a user