}
func TestBytes(t *testing.T) {
- type B []byte
- x := B{1, 2, 3, 4}
+ shouldPanic("on int Value", func() { ValueOf(0).Bytes() })
+ shouldPanic("of non-byte slice", func() { ValueOf([]string{}).Bytes() })
+
+ type S []byte
+ x := S{1, 2, 3, 4}
y := ValueOf(x).Bytes()
if !bytes.Equal(x, y) {
t.Fatalf("ValueOf(%v).Bytes() = %v", x, y)
if &x[0] != &y[0] {
t.Errorf("ValueOf(%p).Bytes() = %p", &x[0], &y[0])
}
+
+ type A [4]byte
+ a := A{1, 2, 3, 4}
+ shouldPanic("unaddressable", func() { ValueOf(a).Bytes() })
+ shouldPanic("on ptr Value", func() { ValueOf(&a).Bytes() })
+ b := ValueOf(&a).Elem().Bytes()
+ if !bytes.Equal(a[:], y) {
+ t.Fatalf("ValueOf(%v).Bytes() = %v", a, b)
+ }
+ if &a[0] != &b[0] {
+ t.Errorf("ValueOf(%p).Bytes() = %p", &a[0], &b[0])
+ }
+
+ // Per issue #24746, it was decided that Bytes can be called on byte slices
+ // that normally cannot be converted from per Go language semantics.
+ type B byte
+ type SB []B
+ type AB [4]B
+ ValueOf([]B{1, 2, 3, 4}).Bytes() // should not panic
+ ValueOf(new([4]B)).Elem().Bytes() // should not panic
+ ValueOf(SB{1, 2, 3, 4}).Bytes() // should not panic
+ ValueOf(new(AB)).Elem().Bytes() // should not panic
}
func TestSetBytes(t *testing.T) {
}
// Bytes returns v's underlying value.
-// It panics if v's underlying value is not a slice of bytes.
+// It panics if v's underlying value is not a slice of bytes or
+// an addressable array of bytes.
func (v Value) Bytes() []byte {
- v.mustBe(Slice)
- if v.typ.Elem().Kind() != Uint8 {
- panic("reflect.Value.Bytes of non-byte slice")
+ switch v.kind() {
+ case Slice:
+ if v.typ.Elem().Kind() != Uint8 {
+ panic("reflect.Value.Bytes of non-byte slice")
+ }
+ // Slice is always bigger than a word; assume flagIndir.
+ return *(*[]byte)(v.ptr)
+ case Array:
+ if v.typ.Elem().Kind() != Uint8 {
+ panic("reflect.Value.Bytes of non-byte array")
+ }
+ if !v.CanAddr() {
+ panic("reflect.Value.Bytes of unaddressable byte array")
+ }
+ p := (*byte)(v.ptr)
+ n := int((*arrayType)(unsafe.Pointer(v.typ)).len)
+ return unsafe.Slice(p, n)
}
- // Slice is always bigger than a word; assume flagIndir.
- return *(*[]byte)(v.ptr)
+ panic(&ValueError{"reflect.Value.Bytes", v.kind()})
}
// runes returns v's underlying value.