Skip to content

Commit a386638

Browse files
committed
support recursive struct
1 parent 2fcbb23 commit a386638

14 files changed

+221
-151
lines changed

any.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -247,7 +247,7 @@ func locatePath(iter *Iterator, path []interface{}) Any {
247247

248248
var anyType = reflect.TypeOf((*Any)(nil)).Elem()
249249

250-
func createDecoderOfAny(cfg *frozenConfig, prefix string, typ reflect.Type) ValDecoder {
250+
func createDecoderOfAny(ctx *ctx, typ reflect.Type) ValDecoder {
251251
if typ == anyType {
252252
return &directAnyCodec{}
253253
}
@@ -259,7 +259,7 @@ func createDecoderOfAny(cfg *frozenConfig, prefix string, typ reflect.Type) ValD
259259
return nil
260260
}
261261

262-
func createEncoderOfAny(cfg *frozenConfig, prefix string, typ reflect.Type) ValEncoder {
262+
func createEncoderOfAny(ctx *ctx, typ reflect.Type) ValEncoder {
263263
if typ == anyType {
264264
return &directAnyCodec{}
265265
}

reflect.go

Lines changed: 105 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,22 @@ type checkIsEmpty interface {
3333
IsEmpty(ptr unsafe.Pointer) bool
3434
}
3535

36+
type ctx struct {
37+
*frozenConfig
38+
prefix string
39+
encoders map[reflect.Type]ValEncoder
40+
decoders map[reflect.Type]ValDecoder
41+
}
42+
43+
func (b *ctx) append(prefix string) *ctx {
44+
return &ctx{
45+
frozenConfig: b.frozenConfig,
46+
prefix: b.prefix + " " + prefix,
47+
encoders: b.encoders,
48+
decoders: b.decoders,
49+
}
50+
}
51+
3652
// ReadVal copy the underlying JSON into go interface, same as json.Unmarshal
3753
func (iter *Iterator) ReadVal(obj interface{}) {
3854
typ := reflect.TypeOf(obj)
@@ -66,44 +82,62 @@ func (cfg *frozenConfig) DecoderOf(typ reflect.Type) ValDecoder {
6682
if decoder != nil {
6783
return decoder
6884
}
69-
decoder = decoderOfType(cfg, "", typ.Elem())
85+
ctx := &ctx{
86+
frozenConfig: cfg,
87+
prefix: "",
88+
decoders: map[reflect.Type]ValDecoder{},
89+
encoders: map[reflect.Type]ValEncoder{},
90+
}
91+
decoder = decoderOfType(ctx, typ.Elem())
7092
cfg.addDecoderToCache(cacheKey, decoder)
7193
return decoder
7294
}
7395

74-
func decoderOfType(cfg *frozenConfig, prefix string, typ reflect.Type) ValDecoder {
75-
decoder := getTypeDecoderFromExtension(cfg, typ)
96+
func decoderOfType(ctx *ctx, typ reflect.Type) ValDecoder {
97+
decoder := getTypeDecoderFromExtension(ctx, typ)
7698
if decoder != nil {
7799
return decoder
78100
}
79-
decoder = createDecoderOfType(cfg, prefix, typ)
101+
decoder = createDecoderOfType(ctx, typ)
80102
for _, extension := range extensions {
81103
decoder = extension.DecorateDecoder(typ, decoder)
82104
}
83-
for _, extension := range cfg.extensions {
105+
for _, extension := range ctx.extensions {
84106
decoder = extension.DecorateDecoder(typ, decoder)
85107
}
86108
return decoder
87109
}
88110

89-
func createDecoderOfType(cfg *frozenConfig, prefix string, typ reflect.Type) ValDecoder {
90-
decoder := createDecoderOfJsonRawMessage(cfg, prefix, typ)
111+
func createDecoderOfType(ctx *ctx, typ reflect.Type) ValDecoder {
112+
decoder := ctx.decoders[typ]
91113
if decoder != nil {
92114
return decoder
93115
}
94-
decoder = createDecoderOfJsonNumber(cfg, prefix, typ)
116+
placeholder := &placeholderDecoder{}
117+
ctx.decoders[typ] = placeholder
118+
decoder = _createDecoderOfType(ctx, typ)
119+
placeholder.decoder = decoder
120+
return decoder
121+
}
122+
123+
func _createDecoderOfType(ctx *ctx, typ reflect.Type) ValDecoder {
124+
decoder := createDecoderOfJsonRawMessage(ctx, typ)
125+
if decoder != nil {
126+
return decoder
127+
}
128+
decoder = createDecoderOfJsonNumber(ctx, typ)
95129
if decoder != nil {
96130
return decoder
97131
}
98-
decoder = createDecoderOfMarshaler(cfg, prefix, typ)
132+
decoder = createDecoderOfMarshaler(ctx, typ)
99133
if decoder != nil {
100134
return decoder
101135
}
102-
decoder = createDecoderOfAny(cfg, prefix, typ)
136+
decoder = createDecoderOfAny(ctx, typ)
103137
if decoder != nil {
104138
return decoder
105139
}
106-
decoder = createDecoderOfNative(cfg, prefix, typ)
140+
decoder = createDecoderOfNative(ctx, typ)
107141
if decoder != nil {
108142
return decoder
109143
}
@@ -115,17 +149,17 @@ func createDecoderOfType(cfg *frozenConfig, prefix string, typ reflect.Type) Val
115149
}
116150
return &efaceDecoder{}
117151
case reflect.Struct:
118-
return decoderOfStruct(cfg, prefix, typ)
152+
return decoderOfStruct(ctx, typ)
119153
case reflect.Array:
120-
return decoderOfArray(cfg, prefix, typ)
154+
return decoderOfArray(ctx, typ)
121155
case reflect.Slice:
122-
return decoderOfSlice(cfg, prefix, typ)
156+
return decoderOfSlice(ctx, typ)
123157
case reflect.Map:
124-
return decoderOfMap(cfg, prefix, typ)
158+
return decoderOfMap(ctx, typ)
125159
case reflect.Ptr:
126-
return decoderOfOptional(cfg, prefix, typ)
160+
return decoderOfOptional(ctx, typ)
127161
default:
128-
return &lazyErrorDecoder{err: fmt.Errorf("%s%s is unsupported type", prefix, typ.String())}
162+
return &lazyErrorDecoder{err: fmt.Errorf("%s%s is unsupported type", ctx.prefix, typ.String())}
129163
}
130164
}
131165

@@ -135,7 +169,13 @@ func (cfg *frozenConfig) EncoderOf(typ reflect.Type) ValEncoder {
135169
if encoder != nil {
136170
return encoder
137171
}
138-
encoder = encoderOfType(cfg, "", typ)
172+
ctx := &ctx{
173+
frozenConfig: cfg,
174+
prefix: "",
175+
decoders: map[reflect.Type]ValDecoder{},
176+
encoders: map[reflect.Type]ValEncoder{},
177+
}
178+
encoder = encoderOfType(ctx, typ)
139179
if shouldFixOnePtr(typ) {
140180
encoder = &onePtrEncoder{encoder}
141181
}
@@ -159,39 +199,50 @@ func shouldFixOnePtr(typ reflect.Type) bool {
159199
return reflect2.Type2(typ).LikePtr()
160200
}
161201

162-
func encoderOfType(cfg *frozenConfig, prefix string, typ reflect.Type) ValEncoder {
163-
encoder := getTypeEncoderFromExtension(cfg, typ)
202+
func encoderOfType(ctx *ctx, typ reflect.Type) ValEncoder {
203+
encoder := getTypeEncoderFromExtension(ctx, typ)
164204
if encoder != nil {
165205
return encoder
166206
}
167-
encoder = createEncoderOfType(cfg, prefix, typ)
207+
encoder = createEncoderOfType(ctx, typ)
168208
for _, extension := range extensions {
169209
encoder = extension.DecorateEncoder(typ, encoder)
170210
}
171-
for _, extension := range cfg.extensions {
211+
for _, extension := range ctx.extensions {
172212
encoder = extension.DecorateEncoder(typ, encoder)
173213
}
174214
return encoder
175215
}
176216

177-
func createEncoderOfType(cfg *frozenConfig, prefix string, typ reflect.Type) ValEncoder {
178-
encoder := createEncoderOfJsonRawMessage(cfg, prefix, typ)
217+
func createEncoderOfType(ctx *ctx, typ reflect.Type) ValEncoder {
218+
encoder := ctx.encoders[typ]
179219
if encoder != nil {
180220
return encoder
181221
}
182-
encoder = createEncoderOfJsonNumber(cfg, prefix, typ)
222+
placeholder := &placeholderEncoder{}
223+
ctx.encoders[typ] = placeholder
224+
encoder = _createEncoderOfType(ctx, typ)
225+
placeholder.encoder = encoder
226+
return encoder
227+
}
228+
func _createEncoderOfType(ctx *ctx, typ reflect.Type) ValEncoder {
229+
encoder := createEncoderOfJsonRawMessage(ctx, typ)
183230
if encoder != nil {
184231
return encoder
185232
}
186-
encoder = createEncoderOfMarshaler(cfg, prefix, typ)
233+
encoder = createEncoderOfJsonNumber(ctx, typ)
187234
if encoder != nil {
188235
return encoder
189236
}
190-
encoder = createEncoderOfAny(cfg, prefix, typ)
237+
encoder = createEncoderOfMarshaler(ctx, typ)
191238
if encoder != nil {
192239
return encoder
193240
}
194-
encoder = createEncoderOfNative(cfg, prefix, typ)
241+
encoder = createEncoderOfAny(ctx, typ)
242+
if encoder != nil {
243+
return encoder
244+
}
245+
encoder = createEncoderOfNative(ctx, typ)
195246
if encoder != nil {
196247
return encoder
197248
}
@@ -200,17 +251,17 @@ func createEncoderOfType(cfg *frozenConfig, prefix string, typ reflect.Type) Val
200251
case reflect.Interface:
201252
return &dynamicEncoder{reflect2.Type2(typ)}
202253
case reflect.Struct:
203-
return encoderOfStruct(cfg, prefix, typ)
254+
return encoderOfStruct(ctx, typ)
204255
case reflect.Array:
205-
return encoderOfArray(cfg, prefix, typ)
256+
return encoderOfArray(ctx, typ)
206257
case reflect.Slice:
207-
return encoderOfSlice(cfg, prefix, typ)
258+
return encoderOfSlice(ctx, typ)
208259
case reflect.Map:
209-
return encoderOfMap(cfg, prefix, typ)
260+
return encoderOfMap(ctx, typ)
210261
case reflect.Ptr:
211-
return encoderOfOptional(cfg, prefix, typ)
262+
return encoderOfOptional(ctx, typ)
212263
default:
213-
return &lazyErrorEncoder{err: fmt.Errorf("%s%s is unsupported type", prefix, typ.String())}
264+
return &lazyErrorEncoder{err: fmt.Errorf("%s%s is unsupported type", ctx.prefix, typ.String())}
214265
}
215266
}
216267

@@ -243,3 +294,23 @@ func (encoder *lazyErrorEncoder) Encode(ptr unsafe.Pointer, stream *Stream) {
243294
func (encoder *lazyErrorEncoder) IsEmpty(ptr unsafe.Pointer) bool {
244295
return false
245296
}
297+
298+
type placeholderDecoder struct {
299+
decoder ValDecoder
300+
}
301+
302+
func (decoder *placeholderDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) {
303+
decoder.decoder.Decode(ptr, iter)
304+
}
305+
306+
type placeholderEncoder struct {
307+
encoder ValEncoder
308+
}
309+
310+
func (encoder *placeholderEncoder) Encode(ptr unsafe.Pointer, stream *Stream) {
311+
encoder.encoder.Encode(ptr, stream)
312+
}
313+
314+
func (encoder *placeholderEncoder) IsEmpty(ptr unsafe.Pointer) bool {
315+
return encoder.encoder.IsEmpty(ptr)
316+
}

reflect_array.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,16 +7,16 @@ import (
77
"unsafe"
88
)
99

10-
func decoderOfArray(cfg *frozenConfig, prefix string, typ reflect.Type) ValDecoder {
11-
decoder := decoderOfType(cfg, prefix+"[array]->", typ.Elem())
10+
func decoderOfArray(ctx *ctx, typ reflect.Type) ValDecoder {
11+
decoder := decoderOfType(ctx.append("[arrayElem]"), typ.Elem())
1212
return &arrayDecoder{typ, typ.Elem(), decoder}
1313
}
1414

15-
func encoderOfArray(cfg *frozenConfig, prefix string, typ reflect.Type) ValEncoder {
15+
func encoderOfArray(ctx *ctx, typ reflect.Type) ValEncoder {
1616
if typ.Len() == 0 {
1717
return emptyArrayEncoder{}
1818
}
19-
encoder := encoderOfType(cfg, prefix+"[array]->", typ.Elem())
19+
encoder := encoderOfType(ctx.append("[arrayElem]"), typ.Elem())
2020
return &arrayEncoder{typ, typ.Elem(), encoder}
2121
}
2222

0 commit comments

Comments
 (0)