diff --git a/src/reflect/value.go b/src/reflect/value.go index a1c69370..e71eaee8 100644 --- a/src/reflect/value.go +++ b/src/reflect/value.go @@ -304,29 +304,48 @@ func (v Value) Slice(i, j int) Value { panic("unimplemented: (reflect.Value).Slice()") } +//go:linkname maplen runtime.hashmapLenUnsafePointer +func maplen(p unsafe.Pointer) int + +//go:linkname chanlen runtime.chanLenUnsafePointer +func chanlen(p unsafe.Pointer) int + // Len returns the length of this value for slices, strings, arrays, channels, -// and maps. For oter types, it panics. +// and maps. For other types, it panics. func (v Value) Len() int { t := v.Type() switch t.Kind() { + case Array: + return v.Type().Len() + case Chan: + return chanlen(v.value) + case Map: + return maplen(v.value) case Slice: return int((*SliceHeader)(v.value).Len) case String: return int((*StringHeader)(v.value).Len) - case Array: - return v.Type().Len() - default: // Chan, Map - panic("unimplemented: (reflect.Value).Len()") + default: + panic(&ValueError{"Len"}) } } +//go:linkname chancap runtime.chanCapUnsafePointer +func chancap(p unsafe.Pointer) int + +// Cap returns the capacity of this value for arrays, channels and slices. +// For other types, it panics. func (v Value) Cap() int { t := v.Type() switch t.Kind() { + case Array: + return v.Type().Len() + case Chan: + return chancap(v.value) case Slice: return int((*SliceHeader)(v.value).Cap) - default: // Array, Chan - panic("unimplemented: (reflect.Value).Cap()") + default: + panic(&ValueError{"Cap"}) } } diff --git a/src/runtime/hashmap.go b/src/runtime/hashmap.go index bd940c75..d7d60c89 100644 --- a/src/runtime/hashmap.go +++ b/src/runtime/hashmap.go @@ -1,7 +1,7 @@ package runtime // This is a hashmap implementation for the map[T]T type. -// It is very rougly based on the implementation of the Go hashmap: +// It is very roughly based on the implementation of the Go hashmap: // // https://golang.org/src/runtime/map.go @@ -80,6 +80,7 @@ func hashmapMake(keySize, valueSize uint8, sizeHint uintptr) *hashmap { // Return the number of entries in this hashmap, called from the len builtin. // A nil hashmap is defined as having length 0. +//go:inline func hashmapLen(m *hashmap) int { if m == nil { return 0 @@ -87,6 +88,12 @@ func hashmapLen(m *hashmap) int { return int(m.count) } +// wrapper for use in reflect +func hashmapLenUnsafePointer(p unsafe.Pointer) int { + m := (*hashmap)(p) + return hashmapLen(m) +} + // Set a specified key to a given value. Grow the map if necessary. //go:nobounds func hashmapSet(m *hashmap, key unsafe.Pointer, value unsafe.Pointer, hash uint32, keyEqual func(x, y unsafe.Pointer, n uintptr) bool) {