Skip to content

Commit 2c71f08

Browse files
cornelkaykevl
authored andcommitted
reflect: add Cap and Len support for map and chan
1 parent 7e64bc8 commit 2c71f08

File tree

2 files changed

+34
-8
lines changed

2 files changed

+34
-8
lines changed

src/reflect/value.go

Lines changed: 26 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -304,29 +304,48 @@ func (v Value) Slice(i, j int) Value {
304304
panic("unimplemented: (reflect.Value).Slice()")
305305
}
306306

307+
//go:linkname maplen runtime.hashmapLenUnsafePointer
308+
func maplen(p unsafe.Pointer) int
309+
310+
//go:linkname chanlen runtime.chanLenUnsafePointer
311+
func chanlen(p unsafe.Pointer) int
312+
307313
// Len returns the length of this value for slices, strings, arrays, channels,
308-
// and maps. For oter types, it panics.
314+
// and maps. For other types, it panics.
309315
func (v Value) Len() int {
310316
t := v.Type()
311317
switch t.Kind() {
318+
case Array:
319+
return v.Type().Len()
320+
case Chan:
321+
return chanlen(v.value)
322+
case Map:
323+
return maplen(v.value)
312324
case Slice:
313325
return int((*SliceHeader)(v.value).Len)
314326
case String:
315327
return int((*StringHeader)(v.value).Len)
316-
case Array:
317-
return v.Type().Len()
318-
default: // Chan, Map
319-
panic("unimplemented: (reflect.Value).Len()")
328+
default:
329+
panic(&ValueError{"Len"})
320330
}
321331
}
322332

333+
//go:linkname chancap runtime.chanCapUnsafePointer
334+
func chancap(p unsafe.Pointer) int
335+
336+
// Cap returns the capacity of this value for arrays, channels and slices.
337+
// For other types, it panics.
323338
func (v Value) Cap() int {
324339
t := v.Type()
325340
switch t.Kind() {
341+
case Array:
342+
return v.Type().Len()
343+
case Chan:
344+
return chancap(v.value)
326345
case Slice:
327346
return int((*SliceHeader)(v.value).Cap)
328-
default: // Array, Chan
329-
panic("unimplemented: (reflect.Value).Cap()")
347+
default:
348+
panic(&ValueError{"Cap"})
330349
}
331350
}
332351

src/runtime/hashmap.go

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
package runtime
22

33
// This is a hashmap implementation for the map[T]T type.
4-
// It is very rougly based on the implementation of the Go hashmap:
4+
// It is very roughly based on the implementation of the Go hashmap:
55
//
66
// https://golang.org/src/runtime/map.go
77

@@ -80,13 +80,20 @@ func hashmapMake(keySize, valueSize uint8, sizeHint uintptr) *hashmap {
8080

8181
// Return the number of entries in this hashmap, called from the len builtin.
8282
// A nil hashmap is defined as having length 0.
83+
//go:inline
8384
func hashmapLen(m *hashmap) int {
8485
if m == nil {
8586
return 0
8687
}
8788
return int(m.count)
8889
}
8990

91+
// wrapper for use in reflect
92+
func hashmapLenUnsafePointer(p unsafe.Pointer) int {
93+
m := (*hashmap)(p)
94+
return hashmapLen(m)
95+
}
96+
9097
// Set a specified key to a given value. Grow the map if necessary.
9198
//go:nobounds
9299
func hashmapSet(m *hashmap, key unsafe.Pointer, value unsafe.Pointer, hash uint32, keyEqual func(x, y unsafe.Pointer, n uintptr) bool) {

0 commit comments

Comments
 (0)