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