github.com/jhump/protoreflect@v1.16.0/dynamic/maps_1.11.go (about) 1 //go:build !go1.12 2 // +build !go1.12 3 4 package dynamic 5 6 import ( 7 "reflect" 8 9 "github.com/jhump/protoreflect/desc" 10 ) 11 12 // Pre-Go-1.12, we must use reflect.Value.MapKeys to reflectively 13 // iterate a map. (We can be more efficient in Go 1.12 and up...) 14 15 func mapsEqual(a, b reflect.Value) bool { 16 if a.Len() != b.Len() { 17 return false 18 } 19 if a.Len() == 0 && b.Len() == 0 { 20 // Optimize the case where maps are frequently empty because MapKeys() 21 // function allocates heavily. 22 return true 23 } 24 25 for _, k := range a.MapKeys() { 26 av := a.MapIndex(k) 27 bv := b.MapIndex(k) 28 if !bv.IsValid() { 29 return false 30 } 31 if !fieldsEqual(av.Interface(), bv.Interface()) { 32 return false 33 } 34 } 35 return true 36 } 37 38 func validFieldValueForMapField(fd *desc.FieldDescriptor, val reflect.Value) (interface{}, error) { 39 // make a defensive copy while we check the contents 40 // (also converts to map[interface{}]interface{} if it's some other type) 41 keyField := fd.GetMessageType().GetFields()[0] 42 valField := fd.GetMessageType().GetFields()[1] 43 m := map[interface{}]interface{}{} 44 for _, k := range val.MapKeys() { 45 if k.Kind() == reflect.Interface { 46 // unwrap it 47 k = reflect.ValueOf(k.Interface()) 48 } 49 kk, err := validElementFieldValueForRv(keyField, k, false) 50 if err != nil { 51 return nil, err 52 } 53 v := val.MapIndex(k) 54 if v.Kind() == reflect.Interface { 55 // unwrap it 56 v = reflect.ValueOf(v.Interface()) 57 } 58 vv, err := validElementFieldValueForRv(valField, v, true) 59 if err != nil { 60 return nil, err 61 } 62 m[kk] = vv 63 } 64 return m, nil 65 } 66 67 func canConvertMap(src reflect.Value, target reflect.Type) bool { 68 kt := target.Key() 69 vt := target.Elem() 70 for _, k := range src.MapKeys() { 71 if !canConvert(k, kt) { 72 return false 73 } 74 if !canConvert(src.MapIndex(k), vt) { 75 return false 76 } 77 } 78 return true 79 } 80 81 func mergeMapVal(src, target reflect.Value, targetType reflect.Type, deterministic bool) error { 82 tkt := targetType.Key() 83 tvt := targetType.Elem() 84 for _, k := range src.MapKeys() { 85 v := src.MapIndex(k) 86 skt := k.Type() 87 svt := v.Type() 88 var nk, nv reflect.Value 89 if tkt == skt { 90 nk = k 91 } else if tkt.Kind() == reflect.Ptr && tkt.Elem() == skt { 92 nk = k.Addr() 93 } else { 94 nk = reflect.New(tkt).Elem() 95 if err := mergeVal(k, nk, deterministic); err != nil { 96 return err 97 } 98 } 99 if tvt == svt { 100 nv = v 101 } else if tvt.Kind() == reflect.Ptr && tvt.Elem() == svt { 102 nv = v.Addr() 103 } else { 104 nv = reflect.New(tvt).Elem() 105 if err := mergeVal(v, nv, deterministic); err != nil { 106 return err 107 } 108 } 109 if target.IsNil() { 110 target.Set(reflect.MakeMap(targetType)) 111 } 112 target.SetMapIndex(nk, nv) 113 } 114 return nil 115 } 116 117 func mergeMapField(m *Message, fd *desc.FieldDescriptor, rv reflect.Value) error { 118 for _, k := range rv.MapKeys() { 119 if k.Kind() == reflect.Interface && !k.IsNil() { 120 k = k.Elem() 121 } 122 v := rv.MapIndex(k) 123 if v.Kind() == reflect.Interface && !v.IsNil() { 124 v = v.Elem() 125 } 126 if err := m.putMapField(fd, k.Interface(), v.Interface()); err != nil { 127 return err 128 } 129 } 130 return nil 131 }