From 960a0b79bf3a4d4f5839159fc87b391ac1302ade Mon Sep 17 00:00:00 2001 From: Damian Gryski Date: Tue, 28 Feb 2023 09:54:39 -0800 Subject: [PATCH] reflect: add SetLen() --- src/reflect/value.go | 10 +++++++++- src/reflect/value_test.go | 17 +++++++++++++++-- 2 files changed, 24 insertions(+), 3 deletions(-) diff --git a/src/reflect/value.go b/src/reflect/value.go index e6c039f0..844c2e91 100644 --- a/src/reflect/value.go +++ b/src/reflect/value.go @@ -952,7 +952,15 @@ func (v Value) SetCap(n int) { } func (v Value) SetLen(n int) { - panic("unimplemented: (reflect.Value).SetLen()") + if v.typecode.Kind() != Slice { + panic(&ValueError{"reflect.Value.SetLen", v.Kind()}) + } + + hdr := (*sliceHeader)(v.value) + if int(uintptr(n)) != n || uintptr(n) > hdr.cap { + panic("reflect.Value.SetLen: slice length out of range") + } + hdr.len = uintptr(n) } func (v Value) checkAddressable() { diff --git a/src/reflect/value_test.go b/src/reflect/value_test.go index a50edd06..53dbc9cb 100644 --- a/src/reflect/value_test.go +++ b/src/reflect/value_test.go @@ -137,7 +137,7 @@ func TestSlice(t *testing.T) { s28ref := refs.Slice(2, 8) if len(s28) != s28ref.Len() || cap(s28) != s28ref.Cap() { - t.Errorf("len(s28)=%d s28ref.Len()=%d cap(s28)=%d s28ref.Cap()=%d\n", len(s28), s28ref.Len(), cap(s28), s28ref.Cap()) + t.Errorf("Slice: len(s28)=%d s28ref.Len()=%d cap(s28)=%d s28ref.Cap()=%d\n", len(s28), s28ref.Len(), cap(s28), s28ref.Cap()) } for i, got := range s28 { @@ -151,7 +151,7 @@ func TestSlice(t *testing.T) { s268ref := refs.Slice3(2, 6, 8) if len(s268) != s268ref.Len() || cap(s268) != s268ref.Cap() { - t.Errorf("len(s268)=%d s268ref.Len()=%d cap(s268)=%d s268ref.Cap()=%d\n", len(s268), s268ref.Len(), cap(s268), s268ref.Cap()) + t.Errorf("Slice3: len(s268)=%d s268ref.Len()=%d cap(s268)=%d s268ref.Cap()=%d\n", len(s268), s268ref.Len(), cap(s268), s268ref.Cap()) } for i, got := range s268 { @@ -161,6 +161,19 @@ func TestSlice(t *testing.T) { } } + // should be equivalent to s28 now, except for the capacity which doesn't change + s268ref.SetLen(6) + if len(s28) != s268ref.Len() || cap(s268) != s268ref.Cap() { + t.Errorf("SetLen: len(s268)=%d s268ref.Len()=%d cap(s268)=%d s268ref.Cap()=%d\n", len(s28), s268ref.Len(), cap(s268), s268ref.Cap()) + } + + for i, got := range s28 { + want := int(s268ref.Index(i).Int()) + if got != want { + t.Errorf("s28[%d]=%d, want %d", i, got, want) + } + } + refs = MakeSlice(TypeOf(s), 5, 10) s = refs.Interface().([]int)