1
16
17 package value
18
19 import (
20 "fmt"
21 "reflect"
22 )
23
24 type structReflect struct {
25 valueReflect
26 }
27
28 func (r structReflect) Length() int {
29 i := 0
30 eachStructField(r.Value, func(_ *TypeReflectCacheEntry, s string, value reflect.Value) bool {
31 i++
32 return true
33 })
34 return i
35 }
36
37 func (r structReflect) Empty() bool {
38 return eachStructField(r.Value, func(_ *TypeReflectCacheEntry, s string, value reflect.Value) bool {
39 return false
40 })
41 }
42
43 func (r structReflect) Get(key string) (Value, bool) {
44 return r.GetUsing(HeapAllocator, key)
45 }
46
47 func (r structReflect) GetUsing(a Allocator, key string) (Value, bool) {
48 if val, ok := r.findJsonNameField(key); ok {
49 return a.allocValueReflect().mustReuse(val, nil, nil, nil), true
50 }
51 return nil, false
52 }
53
54 func (r structReflect) Has(key string) bool {
55 _, ok := r.findJsonNameField(key)
56 return ok
57 }
58
59 func (r structReflect) Set(key string, val Value) {
60 fieldEntry, ok := TypeReflectEntryOf(r.Value.Type()).Fields()[key]
61 if !ok {
62 panic(fmt.Sprintf("key %s may not be set on struct %T: field does not exist", key, r.Value.Interface()))
63 }
64 oldVal := fieldEntry.GetFrom(r.Value)
65 newVal := reflect.ValueOf(val.Unstructured())
66 r.update(fieldEntry, key, oldVal, newVal)
67 }
68
69 func (r structReflect) Delete(key string) {
70 fieldEntry, ok := TypeReflectEntryOf(r.Value.Type()).Fields()[key]
71 if !ok {
72 panic(fmt.Sprintf("key %s may not be deleted on struct %T: field does not exist", key, r.Value.Interface()))
73 }
74 oldVal := fieldEntry.GetFrom(r.Value)
75 if oldVal.Kind() != reflect.Ptr && !fieldEntry.isOmitEmpty {
76 panic(fmt.Sprintf("key %s may not be deleted on struct: %T: value is neither a pointer nor an omitempty field", key, r.Value.Interface()))
77 }
78 r.update(fieldEntry, key, oldVal, reflect.Zero(oldVal.Type()))
79 }
80
81 func (r structReflect) update(fieldEntry *FieldCacheEntry, key string, oldVal, newVal reflect.Value) {
82 if oldVal.CanSet() {
83 oldVal.Set(newVal)
84 return
85 }
86
87
88
89 if r.ParentMap != nil {
90 if r.ParentMapKey == nil {
91 panic("ParentMapKey must not be nil if ParentMap is not nil")
92 }
93 replacement := reflect.New(r.Value.Type()).Elem()
94 fieldEntry.GetFrom(replacement).Set(newVal)
95 r.ParentMap.SetMapIndex(*r.ParentMapKey, replacement)
96 return
97 }
98
99
100
101 panic(fmt.Sprintf("key %s may not be modified on struct: %T: struct is not settable", key, r.Value.Interface()))
102 }
103
104 func (r structReflect) Iterate(fn func(string, Value) bool) bool {
105 return r.IterateUsing(HeapAllocator, fn)
106 }
107
108 func (r structReflect) IterateUsing(a Allocator, fn func(string, Value) bool) bool {
109 vr := a.allocValueReflect()
110 defer a.Free(vr)
111 return eachStructField(r.Value, func(e *TypeReflectCacheEntry, s string, value reflect.Value) bool {
112 return fn(s, vr.mustReuse(value, e, nil, nil))
113 })
114 }
115
116 func eachStructField(structVal reflect.Value, fn func(*TypeReflectCacheEntry, string, reflect.Value) bool) bool {
117 for _, fieldCacheEntry := range TypeReflectEntryOf(structVal.Type()).OrderedFields() {
118 fieldVal := fieldCacheEntry.GetFrom(structVal)
119 if fieldCacheEntry.CanOmit(fieldVal) {
120
121 continue
122 }
123 ok := fn(fieldCacheEntry.TypeEntry, fieldCacheEntry.JsonName, fieldVal)
124 if !ok {
125 return false
126 }
127 }
128 return true
129 }
130
131 func (r structReflect) Unstructured() interface{} {
132
133 result := make(map[string]interface{}, r.Value.NumField())
134 r.Iterate(func(s string, value Value) bool {
135 result[s] = value.Unstructured()
136 return true
137 })
138 return result
139 }
140
141 func (r structReflect) Equals(m Map) bool {
142 return r.EqualsUsing(HeapAllocator, m)
143 }
144
145 func (r structReflect) EqualsUsing(a Allocator, m Map) bool {
146
147 return MapEqualsUsing(a, &r, m)
148 }
149
150 func (r structReflect) findJsonNameFieldAndNotEmpty(jsonName string) (reflect.Value, bool) {
151 structCacheEntry, ok := TypeReflectEntryOf(r.Value.Type()).Fields()[jsonName]
152 if !ok {
153 return reflect.Value{}, false
154 }
155 fieldVal := structCacheEntry.GetFrom(r.Value)
156 return fieldVal, !structCacheEntry.CanOmit(fieldVal)
157 }
158
159 func (r structReflect) findJsonNameField(jsonName string) (val reflect.Value, ok bool) {
160 structCacheEntry, ok := TypeReflectEntryOf(r.Value.Type()).Fields()[jsonName]
161 if !ok {
162 return reflect.Value{}, false
163 }
164 fieldVal := structCacheEntry.GetFrom(r.Value)
165 return fieldVal, !structCacheEntry.CanOmit(fieldVal)
166 }
167
168 func (r structReflect) Zip(other Map, order MapTraverseOrder, fn func(key string, lhs, rhs Value) bool) bool {
169 return r.ZipUsing(HeapAllocator, other, order, fn)
170 }
171
172 func (r structReflect) ZipUsing(a Allocator, other Map, order MapTraverseOrder, fn func(key string, lhs, rhs Value) bool) bool {
173 if otherStruct, ok := other.(*structReflect); ok && r.Value.Type() == otherStruct.Value.Type() {
174 lhsvr, rhsvr := a.allocValueReflect(), a.allocValueReflect()
175 defer a.Free(lhsvr)
176 defer a.Free(rhsvr)
177 return r.structZip(otherStruct, lhsvr, rhsvr, fn)
178 }
179 return defaultMapZip(a, &r, other, order, fn)
180 }
181
182
183
184 func (r structReflect) structZip(other *structReflect, lhsvr, rhsvr *valueReflect, fn func(key string, lhs, rhs Value) bool) bool {
185 lhsVal := r.Value
186 rhsVal := other.Value
187
188 for _, fieldCacheEntry := range TypeReflectEntryOf(lhsVal.Type()).OrderedFields() {
189 lhsFieldVal := fieldCacheEntry.GetFrom(lhsVal)
190 rhsFieldVal := fieldCacheEntry.GetFrom(rhsVal)
191 lhsOmit := fieldCacheEntry.CanOmit(lhsFieldVal)
192 rhsOmit := fieldCacheEntry.CanOmit(rhsFieldVal)
193 if lhsOmit && rhsOmit {
194 continue
195 }
196 var lhsVal, rhsVal Value
197 if !lhsOmit {
198 lhsVal = lhsvr.mustReuse(lhsFieldVal, fieldCacheEntry.TypeEntry, nil, nil)
199 }
200 if !rhsOmit {
201 rhsVal = rhsvr.mustReuse(rhsFieldVal, fieldCacheEntry.TypeEntry, nil, nil)
202 }
203 if !fn(fieldCacheEntry.JsonName, lhsVal, rhsVal) {
204 return false
205 }
206 }
207 return true
208 }
209
View as plain text