From d98c0afbab5d4cf08c08fa1b7f4030355da34784 Mon Sep 17 00:00:00 2001 From: Damian Gryski Date: Sat, 25 Feb 2023 17:51:27 -0800 Subject: [PATCH] reflect: add Bytes() --- src/reflect/value.go | 22 +++++++++++++++++++++- src/reflect/value_test.go | 31 +++++++++++++++++++++++++++++++ 2 files changed, 52 insertions(+), 1 deletion(-) diff --git a/src/reflect/value.go b/src/reflect/value.go index 12ac2d84..c9fd9892 100644 --- a/src/reflect/value.go +++ b/src/reflect/value.go @@ -378,7 +378,27 @@ func (v Value) String() string { } func (v Value) Bytes() []byte { - panic("unimplemented: (reflect.Value).Bytes()") + switch v.Kind() { + case Slice: + if v.typecode.elem().Kind() != Uint8 { + panic(&ValueError{Method: "Bytes", Kind: v.Kind()}) + } + return *(*[]byte)(v.value) + + case Array: + v.checkAddressable() + + if v.typecode.elem().Kind() != Uint8 { + panic(&ValueError{Method: "Bytes", Kind: v.Kind()}) + } + + // Small inline arrays are not addressable, so we only have to + // handle addressable arrays which will be stored as pointers + // in v.value + return unsafe.Slice((*byte)(v.value), v.Len()) + } + + panic(&ValueError{Method: "Bytes", Kind: v.Kind()}) } func (v Value) Slice(i, j int) Value { diff --git a/src/reflect/value_test.go b/src/reflect/value_test.go index d7fdcc30..a50edd06 100644 --- a/src/reflect/value_test.go +++ b/src/reflect/value_test.go @@ -169,6 +169,37 @@ func TestSlice(t *testing.T) { } } +func TestBytes(t *testing.T) { + s := []byte("abcde") + refs := ValueOf(s) + + s2 := refs.Bytes() + + if !equal(s, s2) { + t.Errorf("Failed to get Bytes(): %v != %v", s, s2) + } + + Copy(refs, ValueOf("12345")) + + if string(s) != "12345" { + t.Errorf("Copy()=%q, want `12345`", string(s)) + } + + // test small arrays that fit in a pointer + a := [3]byte{10, 20, 30} + v := ValueOf(&a) + vslice := v.Elem().Bytes() + if len(vslice) != 3 || cap(vslice) != 3 { + t.Errorf("len(vslice)=%v, cap(vslice)=%v", len(vslice), cap(vslice)) + } + + for i, got := range vslice { + if want := (byte(i) + 1) * 10; got != want { + t.Errorf("vslice[%d]=%d, want %d", i, got, want) + } + } +} + func equal[T comparable](a, b []T) bool { if len(a) != len(b) { return false