Code refactoring for bpa operator
[icn.git] / cmd / bpa-operator / vendor / github.com / json-iterator / go / reflect_struct_encoder.go
1 package jsoniter
2
3 import (
4         "fmt"
5         "github.com/modern-go/reflect2"
6         "io"
7         "reflect"
8         "unsafe"
9 )
10
11 func encoderOfStruct(ctx *ctx, typ reflect2.Type) ValEncoder {
12         type bindingTo struct {
13                 binding *Binding
14                 toName  string
15                 ignored bool
16         }
17         orderedBindings := []*bindingTo{}
18         structDescriptor := describeStruct(ctx, typ)
19         for _, binding := range structDescriptor.Fields {
20                 for _, toName := range binding.ToNames {
21                         new := &bindingTo{
22                                 binding: binding,
23                                 toName:  toName,
24                         }
25                         for _, old := range orderedBindings {
26                                 if old.toName != toName {
27                                         continue
28                                 }
29                                 old.ignored, new.ignored = resolveConflictBinding(ctx.frozenConfig, old.binding, new.binding)
30                         }
31                         orderedBindings = append(orderedBindings, new)
32                 }
33         }
34         if len(orderedBindings) == 0 {
35                 return &emptyStructEncoder{}
36         }
37         finalOrderedFields := []structFieldTo{}
38         for _, bindingTo := range orderedBindings {
39                 if !bindingTo.ignored {
40                         finalOrderedFields = append(finalOrderedFields, structFieldTo{
41                                 encoder: bindingTo.binding.Encoder.(*structFieldEncoder),
42                                 toName:  bindingTo.toName,
43                         })
44                 }
45         }
46         return &structEncoder{typ, finalOrderedFields}
47 }
48
49 func createCheckIsEmpty(ctx *ctx, typ reflect2.Type) checkIsEmpty {
50         encoder := createEncoderOfNative(ctx, typ)
51         if encoder != nil {
52                 return encoder
53         }
54         kind := typ.Kind()
55         switch kind {
56         case reflect.Interface:
57                 return &dynamicEncoder{typ}
58         case reflect.Struct:
59                 return &structEncoder{typ: typ}
60         case reflect.Array:
61                 return &arrayEncoder{}
62         case reflect.Slice:
63                 return &sliceEncoder{}
64         case reflect.Map:
65                 return encoderOfMap(ctx, typ)
66         case reflect.Ptr:
67                 return &OptionalEncoder{}
68         default:
69                 return &lazyErrorEncoder{err: fmt.Errorf("unsupported type: %v", typ)}
70         }
71 }
72
73 func resolveConflictBinding(cfg *frozenConfig, old, new *Binding) (ignoreOld, ignoreNew bool) {
74         newTagged := new.Field.Tag().Get(cfg.getTagKey()) != ""
75         oldTagged := old.Field.Tag().Get(cfg.getTagKey()) != ""
76         if newTagged {
77                 if oldTagged {
78                         if len(old.levels) > len(new.levels) {
79                                 return true, false
80                         } else if len(new.levels) > len(old.levels) {
81                                 return false, true
82                         } else {
83                                 return true, true
84                         }
85                 } else {
86                         return true, false
87                 }
88         } else {
89                 if oldTagged {
90                         return true, false
91                 }
92                 if len(old.levels) > len(new.levels) {
93                         return true, false
94                 } else if len(new.levels) > len(old.levels) {
95                         return false, true
96                 } else {
97                         return true, true
98                 }
99         }
100 }
101
102 type structFieldEncoder struct {
103         field        reflect2.StructField
104         fieldEncoder ValEncoder
105         omitempty    bool
106 }
107
108 func (encoder *structFieldEncoder) Encode(ptr unsafe.Pointer, stream *Stream) {
109         fieldPtr := encoder.field.UnsafeGet(ptr)
110         encoder.fieldEncoder.Encode(fieldPtr, stream)
111         if stream.Error != nil && stream.Error != io.EOF {
112                 stream.Error = fmt.Errorf("%s: %s", encoder.field.Name(), stream.Error.Error())
113         }
114 }
115
116 func (encoder *structFieldEncoder) IsEmpty(ptr unsafe.Pointer) bool {
117         fieldPtr := encoder.field.UnsafeGet(ptr)
118         return encoder.fieldEncoder.IsEmpty(fieldPtr)
119 }
120
121 func (encoder *structFieldEncoder) IsEmbeddedPtrNil(ptr unsafe.Pointer) bool {
122         isEmbeddedPtrNil, converted := encoder.fieldEncoder.(IsEmbeddedPtrNil)
123         if !converted {
124                 return false
125         }
126         fieldPtr := encoder.field.UnsafeGet(ptr)
127         return isEmbeddedPtrNil.IsEmbeddedPtrNil(fieldPtr)
128 }
129
130 type IsEmbeddedPtrNil interface {
131         IsEmbeddedPtrNil(ptr unsafe.Pointer) bool
132 }
133
134 type structEncoder struct {
135         typ    reflect2.Type
136         fields []structFieldTo
137 }
138
139 type structFieldTo struct {
140         encoder *structFieldEncoder
141         toName  string
142 }
143
144 func (encoder *structEncoder) Encode(ptr unsafe.Pointer, stream *Stream) {
145         stream.WriteObjectStart()
146         isNotFirst := false
147         for _, field := range encoder.fields {
148                 if field.encoder.omitempty && field.encoder.IsEmpty(ptr) {
149                         continue
150                 }
151                 if field.encoder.IsEmbeddedPtrNil(ptr) {
152                         continue
153                 }
154                 if isNotFirst {
155                         stream.WriteMore()
156                 }
157                 stream.WriteObjectField(field.toName)
158                 field.encoder.Encode(ptr, stream)
159                 isNotFirst = true
160         }
161         stream.WriteObjectEnd()
162         if stream.Error != nil && stream.Error != io.EOF {
163                 stream.Error = fmt.Errorf("%v.%s", encoder.typ, stream.Error.Error())
164         }
165 }
166
167 func (encoder *structEncoder) IsEmpty(ptr unsafe.Pointer) bool {
168         return false
169 }
170
171 type emptyStructEncoder struct {
172 }
173
174 func (encoder *emptyStructEncoder) Encode(ptr unsafe.Pointer, stream *Stream) {
175         stream.WriteEmptyObject()
176 }
177
178 func (encoder *emptyStructEncoder) IsEmpty(ptr unsafe.Pointer) bool {
179         return false
180 }
181
182 type stringModeNumberEncoder struct {
183         elemEncoder ValEncoder
184 }
185
186 func (encoder *stringModeNumberEncoder) Encode(ptr unsafe.Pointer, stream *Stream) {
187         stream.writeByte('"')
188         encoder.elemEncoder.Encode(ptr, stream)
189         stream.writeByte('"')
190 }
191
192 func (encoder *stringModeNumberEncoder) IsEmpty(ptr unsafe.Pointer) bool {
193         return encoder.elemEncoder.IsEmpty(ptr)
194 }
195
196 type stringModeStringEncoder struct {
197         elemEncoder ValEncoder
198         cfg         *frozenConfig
199 }
200
201 func (encoder *stringModeStringEncoder) Encode(ptr unsafe.Pointer, stream *Stream) {
202         tempStream := encoder.cfg.BorrowStream(nil)
203         defer encoder.cfg.ReturnStream(tempStream)
204         encoder.elemEncoder.Encode(ptr, tempStream)
205         stream.WriteString(string(tempStream.Buffer()))
206 }
207
208 func (encoder *stringModeStringEncoder) IsEmpty(ptr unsafe.Pointer) bool {
209         return encoder.elemEncoder.IsEmpty(ptr)
210 }