github.com/segmentio/encoding@v0.4.0/internal/runtime_reflect/map.go (about) 1 // Package runtime_reflect exposes internal APIs of the Go runtime. 2 // 3 // This package is internal so it doesn't become part of the exported APIs that 4 // users of this package can take dependencies on. There is a risk that these 5 // APIs will be implicitly changed by Go, in which case packages that depend on 6 // it will break. We use these APIs to have access to optimziations that aren't 7 // possible today via the reflect package. Ideally, the reflect package evolves 8 // to expose APIs that are efficient enough that we can drop the need for this 9 // package, but until then we will be maintaining bridges to these Go runtime 10 // functions and types. 11 package runtime_reflect 12 13 import "unsafe" 14 15 func Assign(typ, dst, src unsafe.Pointer) { 16 typedmemmove(typ, dst, src) 17 } 18 19 func MapAssign(t, m, k unsafe.Pointer) unsafe.Pointer { 20 return mapassign(t, m, k) 21 } 22 23 func MakeMap(t unsafe.Pointer, cap int) unsafe.Pointer { 24 return makemap(t, cap) 25 } 26 27 type MapIter struct{ hiter } 28 29 func (it *MapIter) Init(t unsafe.Pointer, m unsafe.Pointer) { 30 mapiterinit(t, m, &it.hiter) 31 } 32 33 func (it *MapIter) Done() { 34 if it.h != nil { 35 it.key = nil 36 mapiternext(&it.hiter) 37 } 38 } 39 40 func (it *MapIter) Next() { 41 mapiternext(&it.hiter) 42 } 43 44 func (it *MapIter) HasNext() bool { 45 return it.key != nil 46 } 47 48 func (it *MapIter) Key() unsafe.Pointer { return it.key } 49 50 func (it *MapIter) Value() unsafe.Pointer { return it.value } 51 52 // copied from src/runtime/map.go, all pointer types replaced with 53 // unsafe.Pointer. 54 // 55 // Alternatively we could get away with a heap allocation and only 56 // defining key and val if we were using reflect.mapiterinit instead, 57 // which returns a heap-allocated *hiter. 58 type hiter struct { 59 key unsafe.Pointer // nil when iteration is done 60 value unsafe.Pointer 61 t unsafe.Pointer 62 h unsafe.Pointer 63 buckets unsafe.Pointer // bucket ptr at hash_iter initialization time 64 bptr unsafe.Pointer // current bucket 65 overflow unsafe.Pointer // keeps overflow buckets of hmap.buckets alive 66 oldoverflow unsafe.Pointer // keeps overflow buckets of hmap.oldbuckets alive 67 startBucket uintptr // bucket iteration started at 68 offset uint8 // intra-bucket offset to start from during iteration (should be big enough to hold bucketCnt-1) 69 wrapped bool // already wrapped around from end of bucket array to beginning 70 B uint8 71 i uint8 72 bucket uintptr 73 checkBucket uintptr 74 } 75 76 //go:noescape 77 //go:linkname makemap reflect.makemap 78 func makemap(t unsafe.Pointer, cap int) unsafe.Pointer 79 80 // m escapes into the return value, but the caller of mapiterinit 81 // doesn't let the return value escape. 82 //go:noescape 83 //go:linkname mapiterinit runtime.mapiterinit 84 func mapiterinit(t unsafe.Pointer, m unsafe.Pointer, it *hiter) 85 86 //go:noescape 87 //go:linkname mapiternext runtime.mapiternext 88 func mapiternext(it *hiter) 89 90 //go:noescape 91 //go:linkname mapassign runtime.mapassign 92 func mapassign(t, m, k unsafe.Pointer) unsafe.Pointer 93 94 //go:nosplit 95 //go:noescape 96 //go:linkname typedmemmove runtime.typedmemmove 97 func typedmemmove(typ, dst, src unsafe.Pointer)