reflect: add MapIndex()
Этот коммит содержится в:
родитель
c0a50e9b47
коммит
d0f4702f8b
3 изменённых файлов: 71 добавлений и 0 удалений
|
@ -785,6 +785,29 @@ func (t *rawType) Comparable() bool {
|
|||
}
|
||||
}
|
||||
|
||||
// isbinary() returns if the hashmapAlgorithmBinary functions can be used on this type
|
||||
func (t *rawType) isBinary() bool {
|
||||
switch t.Kind() {
|
||||
case Bool, Int, Int8, Int16, Int32, Int64, Uint, Uint8, Uint16, Uint32, Uint64, Uintptr:
|
||||
return true
|
||||
case Float32, Float64, Complex64, Complex128:
|
||||
return true
|
||||
case Pointer:
|
||||
return true
|
||||
case Array:
|
||||
return t.elem().isBinary()
|
||||
case Struct:
|
||||
numField := t.NumField()
|
||||
for i := 0; i < numField; i++ {
|
||||
if !t.rawField(i).Type.isBinary() {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (t rawType) ChanDir() ChanDir {
|
||||
panic("unimplemented: (reflect.Type).ChanDir()")
|
||||
}
|
||||
|
|
|
@ -644,7 +644,46 @@ func (v Value) MapKeys() []Value {
|
|||
panic("unimplemented: (reflect.Value).MapKeys()")
|
||||
}
|
||||
|
||||
//go:linkname hashmapStringGet runtime.hashmapStringGetUnsafePointer
|
||||
func hashmapStringGet(m unsafe.Pointer, key string, value unsafe.Pointer, valueSize uintptr) bool
|
||||
|
||||
//go:linkname hashmapBinaryGet runtime.hashmapBinaryGetUnsafePointer
|
||||
func hashmapBinaryGet(m unsafe.Pointer, key, value unsafe.Pointer, valueSize uintptr) bool
|
||||
|
||||
func (v Value) MapIndex(key Value) Value {
|
||||
if v.Kind() != Map {
|
||||
panic(&ValueError{Method: "MapIndex", Kind: v.Kind()})
|
||||
}
|
||||
|
||||
// compare key type with actual key type of map
|
||||
if key.typecode != v.typecode.key() {
|
||||
// type error?
|
||||
panic("reflect.Value.MapIndex: incompatible types for key")
|
||||
}
|
||||
|
||||
elemType := v.typecode.Elem()
|
||||
elem := New(elemType)
|
||||
|
||||
if key.Kind() == String {
|
||||
if ok := hashmapStringGet(v.pointer(), *(*string)(key.value), elem.value, elemType.Size()); !ok {
|
||||
return Value{}
|
||||
}
|
||||
return elem.Elem()
|
||||
} else if key.typecode.isBinary() {
|
||||
var keyptr unsafe.Pointer
|
||||
if key.isIndirect() || key.typecode.Size() > unsafe.Sizeof(uintptr(0)) {
|
||||
keyptr = key.value
|
||||
} else {
|
||||
keyptr = unsafe.Pointer(&key.value)
|
||||
}
|
||||
//TODO(dgryski): zero out padding bytes in key, if any
|
||||
if ok := hashmapBinaryGet(v.pointer(), keyptr, elem.value, elemType.Size()); !ok {
|
||||
return Value{}
|
||||
}
|
||||
return elem.Elem()
|
||||
}
|
||||
|
||||
// TODO(dgryski): Add other map types. For now, just string and binary types are supported.
|
||||
panic("unimplemented: (reflect.Value).MapIndex()")
|
||||
}
|
||||
|
||||
|
|
|
@ -44,4 +44,13 @@ func TestMap(t *testing.T) {
|
|||
if got, want := mtyp.Elem().Kind().String(), "int"; got != want {
|
||||
t.Errorf("m.Elem().String()=%q, want %q", got, want)
|
||||
}
|
||||
|
||||
m["foo"] = 2
|
||||
|
||||
mref := ValueOf(m)
|
||||
two := mref.MapIndex(ValueOf("foo"))
|
||||
|
||||
if got, want := two.Interface().(int), 2; got != want {
|
||||
t.Errorf("MapIndex(`foo`)=%v, want %v", got, want)
|
||||
}
|
||||
}
|
||||
|
|
Загрузка…
Создание таблицы
Сослаться в новой задаче