Этот коммит содержится в:
Damian Gryski 2023-02-25 14:15:35 -08:00 коммит произвёл Ayke
родитель 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 { func (t rawType) ChanDir() ChanDir {
panic("unimplemented: (reflect.Type).ChanDir()") panic("unimplemented: (reflect.Type).ChanDir()")
} }

Просмотреть файл

@ -644,7 +644,46 @@ func (v Value) MapKeys() []Value {
panic("unimplemented: (reflect.Value).MapKeys()") 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 { 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()") panic("unimplemented: (reflect.Value).MapIndex()")
} }

Просмотреть файл

@ -44,4 +44,13 @@ func TestMap(t *testing.T) {
if got, want := mtyp.Elem().Kind().String(), "int"; got != want { if got, want := mtyp.Elem().Kind().String(), "int"; got != want {
t.Errorf("m.Elem().String()=%q, want %q", 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)
}
} }