blob: ef1b37050f6d876dbbdfcca7b2c482b4fec87e1c [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// With Go 1.12 and above, we can use reflect.Value.MapRange to iterate
12// over maps more efficiently than using reflect.Value.MapKeys.
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
20 return true
21 }
22
23 iter := a.MapRange()
24 for iter.Next() {
25 k := iter.Key()
26 av := iter.Value()
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
38func 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 iter := val.MapRange()
45 for iter.Next() {
46 k := iter.Key()
47 if k.Kind() == reflect.Interface {
48 // unwrap it
49 k = reflect.ValueOf(k.Interface())
50 }
51 kk, err := validElementFieldValueForRv(keyField, k, false)
52 if err != nil {
53 return nil, err
54 }
55 v := iter.Value()
56 if v.Kind() == reflect.Interface {
57 // unwrap it
58 v = reflect.ValueOf(v.Interface())
59 }
60 vv, err := validElementFieldValueForRv(valField, v, true)
61 if err != nil {
62 return nil, err
63 }
64 m[kk] = vv
65 }
66 return m, nil
67}
68
69func canConvertMap(src reflect.Value, target reflect.Type) bool {
70 kt := target.Key()
71 vt := target.Elem()
72 iter := src.MapRange()
73 for iter.Next() {
74 if !canConvert(iter.Key(), kt) {
75 return false
76 }
77 if !canConvert(iter.Value(), vt) {
78 return false
79 }
80 }
81 return true
82}
83
84func mergeMapVal(src, target reflect.Value, targetType reflect.Type, deterministic bool) error {
85 tkt := targetType.Key()
86 tvt := targetType.Elem()
87 iter := src.MapRange()
88 for iter.Next() {
89 k := iter.Key()
90 v := iter.Value()
91 skt := k.Type()
92 svt := v.Type()
93 var nk, nv reflect.Value
94 if tkt == skt {
95 nk = k
96 } else if tkt.Kind() == reflect.Ptr && tkt.Elem() == skt {
97 nk = k.Addr()
98 } else {
99 nk = reflect.New(tkt).Elem()
100 if err := mergeVal(k, nk, deterministic); err != nil {
101 return err
102 }
103 }
104 if tvt == svt {
105 nv = v
106 } else if tvt.Kind() == reflect.Ptr && tvt.Elem() == svt {
107 nv = v.Addr()
108 } else {
109 nv = reflect.New(tvt).Elem()
110 if err := mergeVal(v, nv, deterministic); err != nil {
111 return err
112 }
113 }
114 if target.IsNil() {
115 target.Set(reflect.MakeMap(targetType))
116 }
117 target.SetMapIndex(nk, nv)
118 }
119 return nil
120}
121
122func mergeMapField(m *Message, fd *desc.FieldDescriptor, rv reflect.Value) error {
123 iter := rv.MapRange()
124 for iter.Next() {
125 k := iter.Key()
126 v := iter.Value()
127 if k.Kind() == reflect.Interface && !k.IsNil() {
128 k = k.Elem()
129 }
130 if v.Kind() == reflect.Interface && !v.IsNil() {
131 v = v.Elem()
132 }
133 if err := m.putMapField(fd, k.Interface(), v.Interface()); err != nil {
134 return err
135 }
136 }
137 return nil
138}