mapreflect.go 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209
  1. /*
  2. Copyright 2019 The Kubernetes Authors.
  3. Licensed under the Apache License, Version 2.0 (the "License");
  4. you may not use this file except in compliance with the License.
  5. You may obtain a copy of the License at
  6. http://www.apache.org/licenses/LICENSE-2.0
  7. Unless required by applicable law or agreed to in writing, software
  8. distributed under the License is distributed on an "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. See the License for the specific language governing permissions and
  11. limitations under the License.
  12. */
  13. package value
  14. import (
  15. "reflect"
  16. )
  17. type mapReflect struct {
  18. valueReflect
  19. }
  20. func (r mapReflect) Length() int {
  21. val := r.Value
  22. return val.Len()
  23. }
  24. func (r mapReflect) Empty() bool {
  25. val := r.Value
  26. return val.Len() == 0
  27. }
  28. func (r mapReflect) Get(key string) (Value, bool) {
  29. return r.GetUsing(HeapAllocator, key)
  30. }
  31. func (r mapReflect) GetUsing(a Allocator, key string) (Value, bool) {
  32. k, v, ok := r.get(key)
  33. if !ok {
  34. return nil, false
  35. }
  36. return a.allocValueReflect().mustReuse(v, nil, &r.Value, &k), true
  37. }
  38. func (r mapReflect) get(k string) (key, value reflect.Value, ok bool) {
  39. mapKey := r.toMapKey(k)
  40. val := r.Value.MapIndex(mapKey)
  41. return mapKey, val, val.IsValid() && val != reflect.Value{}
  42. }
  43. func (r mapReflect) Has(key string) bool {
  44. var val reflect.Value
  45. val = r.Value.MapIndex(r.toMapKey(key))
  46. if !val.IsValid() {
  47. return false
  48. }
  49. return val != reflect.Value{}
  50. }
  51. func (r mapReflect) Set(key string, val Value) {
  52. r.Value.SetMapIndex(r.toMapKey(key), reflect.ValueOf(val.Unstructured()))
  53. }
  54. func (r mapReflect) Delete(key string) {
  55. val := r.Value
  56. val.SetMapIndex(r.toMapKey(key), reflect.Value{})
  57. }
  58. // TODO: Do we need to support types that implement json.Marshaler and are used as string keys?
  59. func (r mapReflect) toMapKey(key string) reflect.Value {
  60. val := r.Value
  61. return reflect.ValueOf(key).Convert(val.Type().Key())
  62. }
  63. func (r mapReflect) Iterate(fn func(string, Value) bool) bool {
  64. return r.IterateUsing(HeapAllocator, fn)
  65. }
  66. func (r mapReflect) IterateUsing(a Allocator, fn func(string, Value) bool) bool {
  67. if r.Value.Len() == 0 {
  68. return true
  69. }
  70. v := a.allocValueReflect()
  71. defer a.Free(v)
  72. return eachMapEntry(r.Value, func(e *TypeReflectCacheEntry, key reflect.Value, value reflect.Value) bool {
  73. return fn(key.String(), v.mustReuse(value, e, &r.Value, &key))
  74. })
  75. }
  76. func eachMapEntry(val reflect.Value, fn func(*TypeReflectCacheEntry, reflect.Value, reflect.Value) bool) bool {
  77. iter := val.MapRange()
  78. entry := TypeReflectEntryOf(val.Type().Elem())
  79. for iter.Next() {
  80. next := iter.Value()
  81. if !next.IsValid() {
  82. continue
  83. }
  84. if !fn(entry, iter.Key(), next) {
  85. return false
  86. }
  87. }
  88. return true
  89. }
  90. func (r mapReflect) Unstructured() interface{} {
  91. result := make(map[string]interface{}, r.Length())
  92. r.Iterate(func(s string, value Value) bool {
  93. result[s] = value.Unstructured()
  94. return true
  95. })
  96. return result
  97. }
  98. func (r mapReflect) Equals(m Map) bool {
  99. return r.EqualsUsing(HeapAllocator, m)
  100. }
  101. func (r mapReflect) EqualsUsing(a Allocator, m Map) bool {
  102. lhsLength := r.Length()
  103. rhsLength := m.Length()
  104. if lhsLength != rhsLength {
  105. return false
  106. }
  107. if lhsLength == 0 {
  108. return true
  109. }
  110. vr := a.allocValueReflect()
  111. defer a.Free(vr)
  112. entry := TypeReflectEntryOf(r.Value.Type().Elem())
  113. return m.Iterate(func(key string, value Value) bool {
  114. _, lhsVal, ok := r.get(key)
  115. if !ok {
  116. return false
  117. }
  118. return Equals(vr.mustReuse(lhsVal, entry, nil, nil), value)
  119. })
  120. }
  121. func (r mapReflect) Zip(other Map, order MapTraverseOrder, fn func(key string, lhs, rhs Value) bool) bool {
  122. return r.ZipUsing(HeapAllocator, other, order, fn)
  123. }
  124. func (r mapReflect) ZipUsing(a Allocator, other Map, order MapTraverseOrder, fn func(key string, lhs, rhs Value) bool) bool {
  125. if otherMapReflect, ok := other.(*mapReflect); ok && order == Unordered {
  126. return r.unorderedReflectZip(a, otherMapReflect, fn)
  127. }
  128. return defaultMapZip(a, &r, other, order, fn)
  129. }
  130. // unorderedReflectZip provides an optimized unordered zip for mapReflect types.
  131. func (r mapReflect) unorderedReflectZip(a Allocator, other *mapReflect, fn func(key string, lhs, rhs Value) bool) bool {
  132. if r.Empty() && (other == nil || other.Empty()) {
  133. return true
  134. }
  135. lhs := r.Value
  136. lhsEntry := TypeReflectEntryOf(lhs.Type().Elem())
  137. // map lookup via reflection is expensive enough that it is better to keep track of visited keys
  138. visited := map[string]struct{}{}
  139. vlhs, vrhs := a.allocValueReflect(), a.allocValueReflect()
  140. defer a.Free(vlhs)
  141. defer a.Free(vrhs)
  142. if other != nil {
  143. rhs := other.Value
  144. rhsEntry := TypeReflectEntryOf(rhs.Type().Elem())
  145. iter := rhs.MapRange()
  146. for iter.Next() {
  147. key := iter.Key()
  148. keyString := key.String()
  149. next := iter.Value()
  150. if !next.IsValid() {
  151. continue
  152. }
  153. rhsVal := vrhs.mustReuse(next, rhsEntry, &rhs, &key)
  154. visited[keyString] = struct{}{}
  155. var lhsVal Value
  156. if _, v, ok := r.get(keyString); ok {
  157. lhsVal = vlhs.mustReuse(v, lhsEntry, &lhs, &key)
  158. }
  159. if !fn(keyString, lhsVal, rhsVal) {
  160. return false
  161. }
  162. }
  163. }
  164. iter := lhs.MapRange()
  165. for iter.Next() {
  166. key := iter.Key()
  167. if _, ok := visited[key.String()]; ok {
  168. continue
  169. }
  170. next := iter.Value()
  171. if !next.IsValid() {
  172. continue
  173. }
  174. if !fn(key.String(), vlhs.mustReuse(next, lhsEntry, &lhs, &key), nil) {
  175. return false
  176. }
  177. }
  178. return true
  179. }