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