Skip to content

Commit 892cd0b

Browse files
cuiweixiegopherbot
authored andcommitted
reflect: support Len and Cap on pointer-to-array Value
Fixes #52411 Change-Id: I2fd13a453622992c52d49aade7cd058cfc8a77ca GitHub-Last-Rev: d5987c2 GitHub-Pull-Request: #52423 Reviewed-on: https://go-review.googlesource.com/c/go/+/400954 Reviewed-by: Keith Randall <[email protected]> Run-TryBot: Ian Lance Taylor <[email protected]> TryBot-Result: Gopher Robot <[email protected]> Reviewed-by: Keith Randall <[email protected]> Auto-Submit: Keith Randall <[email protected]> Reviewed-by: Ian Lance Taylor <[email protected]> Run-TryBot: Ian Lance Taylor <[email protected]> Auto-Submit: Ian Lance Taylor <[email protected]>
1 parent 35f2aba commit 892cd0b

File tree

2 files changed

+78
-2
lines changed

2 files changed

+78
-2
lines changed

src/reflect/all_test.go

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7913,3 +7913,69 @@ func BenchmarkSliceCap(b *testing.B) {
79137913
sinkAll.RawInt = sourceAll.SliceAny.Cap()
79147914
}
79157915
}
7916+
7917+
func TestValue_Cap(t *testing.T) {
7918+
a := &[3]int{1, 2, 3}
7919+
v := ValueOf(a)
7920+
if v.Cap() != cap(a) {
7921+
t.Errorf("Cap = %d want %d", v.Cap(), cap(a))
7922+
}
7923+
7924+
a = nil
7925+
v = ValueOf(a)
7926+
if v.Cap() != cap(a) {
7927+
t.Errorf("Cap = %d want %d", v.Cap(), cap(a))
7928+
}
7929+
7930+
getError := func(f func()) (errorStr string) {
7931+
defer func() {
7932+
e := recover()
7933+
if str, ok := e.(string); ok {
7934+
errorStr = str
7935+
}
7936+
}()
7937+
f()
7938+
return
7939+
}
7940+
e := getError(func() {
7941+
var ptr *int
7942+
ValueOf(ptr).Cap()
7943+
})
7944+
wantStr := "reflect: call of reflect.Value.Cap on ptr to non-array Value"
7945+
if e != wantStr {
7946+
t.Errorf("error is %q, want %q", e, wantStr)
7947+
}
7948+
}
7949+
7950+
func TestValue_Len(t *testing.T) {
7951+
a := &[3]int{1, 2, 3}
7952+
v := ValueOf(a)
7953+
if v.Len() != len(a) {
7954+
t.Errorf("Len = %d want %d", v.Len(), len(a))
7955+
}
7956+
7957+
a = nil
7958+
v = ValueOf(a)
7959+
if v.Len() != len(a) {
7960+
t.Errorf("Len = %d want %d", v.Len(), len(a))
7961+
}
7962+
7963+
getError := func(f func()) (errorStr string) {
7964+
defer func() {
7965+
e := recover()
7966+
if str, ok := e.(string); ok {
7967+
errorStr = str
7968+
}
7969+
}()
7970+
f()
7971+
return
7972+
}
7973+
e := getError(func() {
7974+
var ptr *int
7975+
ValueOf(ptr).Len()
7976+
})
7977+
wantStr := "reflect: call of reflect.Value.Len on ptr to non-array Value"
7978+
if e != wantStr {
7979+
t.Errorf("error is %q, want %q", e, wantStr)
7980+
}
7981+
}

src/reflect/value.go

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1144,7 +1144,7 @@ func funcName(f func([]Value) []Value) string {
11441144
}
11451145

11461146
// Cap returns v's capacity.
1147-
// It panics if v's Kind is not Array, Chan, or Slice.
1147+
// It panics if v's Kind is not Array, Chan, Slice or pointer to Array.
11481148
func (v Value) Cap() int {
11491149
// capNonSlice is split out to keep Cap inlineable for slice kinds.
11501150
if v.kind() == Slice {
@@ -1160,6 +1160,11 @@ func (v Value) capNonSlice() int {
11601160
return v.typ.Len()
11611161
case Chan:
11621162
return chancap(v.pointer())
1163+
case Ptr:
1164+
if v.typ.Elem().Kind() == Array {
1165+
return v.typ.Elem().Len()
1166+
}
1167+
panic("reflect: call of reflect.Value.Cap on ptr to non-array Value")
11631168
}
11641169
panic(&ValueError{"reflect.Value.Cap", v.kind()})
11651170
}
@@ -1600,7 +1605,7 @@ func (v Value) Kind() Kind {
16001605
}
16011606

16021607
// Len returns v's length.
1603-
// It panics if v's Kind is not Array, Chan, Map, Slice, or String.
1608+
// It panics if v's Kind is not Array, Chan, Map, Slice, String, or pointer to Array.
16041609
func (v Value) Len() int {
16051610
// lenNonSlice is split out to keep Len inlineable for slice kinds.
16061611
if v.kind() == Slice {
@@ -1621,6 +1626,11 @@ func (v Value) lenNonSlice() int {
16211626
case String:
16221627
// String is bigger than a word; assume flagIndir.
16231628
return (*unsafeheader.String)(v.ptr).Len
1629+
case Ptr:
1630+
if v.typ.Elem().Kind() == Array {
1631+
return v.typ.Elem().Len()
1632+
}
1633+
panic("reflect: call of reflect.Value.Len on ptr to non-array Value")
16241634
}
16251635
panic(&ValueError{"reflect.Value.Len", v.kind()})
16261636
}

0 commit comments

Comments
 (0)