github.com/egonelbre/exp@v0.0.0-20240430123955-ed1d3aa93911/reflectmap/reflect_interface.go (about) 1 package reflectmap 2 3 import ( 4 "reflect" 5 ) 6 7 // only supports int for key 8 type Map struct { 9 keyType reflect.Type 10 valueType reflect.Type 11 bucketType reflect.Type 12 13 bucketCount int 14 buckets reflect.Value 15 } 16 17 func NewMap(key, value interface{}) *Map { 18 keyType := reflect.TypeOf(key) 19 valueType := reflect.TypeOf(value) 20 bucketCount := 128 21 22 bucketType := reflect.StructOf([]reflect.StructField{ 23 reflect.StructField{ 24 Name: "Hash", 25 Type: reflect.TypeOf(hashBucket{}), 26 }, 27 reflect.StructField{ 28 Name: "Key", 29 Type: reflect.ArrayOf(bucketSize, keyType), 30 }, 31 reflect.StructField{ 32 Name: "Value", 33 Type: reflect.ArrayOf(bucketSize, valueType), 34 }, 35 }) 36 37 buckets := reflect.New(reflect.ArrayOf(bucketCount, bucketType)) 38 return &Map{ 39 keyType: keyType, 40 valueType: valueType, 41 bucketType: bucketType, 42 43 bucketCount: bucketCount, 44 buckets: buckets, 45 } 46 } 47 48 /* 49 type bucketType struct { 50 hash [bucketSize]byte 51 key [bucketSize]keyType 52 value [bucketSize]valueType 53 } 54 */ 55 56 func (m *Map) Add(key, value interface{}) { 57 // hack to avoid figuring out a hash function 58 keyi := key.(int) 59 60 bucketi := keyi % m.bucketCount 61 tophash := byte(keyi) 62 if tophash == 0 { 63 tophash = 1 64 } 65 66 bucket := m.buckets.Elem().Index(bucketi) 67 hashesField := bucket.Field(0) 68 keys := bucket.Field(1) 69 values := bucket.Field(2) 70 71 hashes := hashesField.Addr().Interface().(*hashBucket) 72 for i, v := range *hashes { 73 if v == 0 { 74 (*hashes)[i] = tophash 75 keys.Index(i).Set(reflect.ValueOf(key)) 76 values.Index(i).Set(reflect.ValueOf(value)) 77 return 78 } 79 } 80 81 (*hashes)[0] = tophash 82 keys.Index(0).Set(reflect.ValueOf(key)) 83 values.Index(0).Set(reflect.ValueOf(value)) 84 }