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)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Загрузка…
	
	Создание таблицы
		
		Сослаться в новой задаче