From 99a5b20e5e4a5b194036fff4127118fedac83f97 Mon Sep 17 00:00:00 2001 From: Masaaki Goshima Date: Tue, 25 Aug 2020 17:18:37 +0900 Subject: [PATCH] Fix decoding of recursive type --- decode.go | 8 ++++++-- decode_compile.go | 9 ++++++++- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/decode.go b/decode.go index d092057..56b9c24 100644 --- a/decode.go +++ b/decode.go @@ -23,6 +23,7 @@ type decoder interface { type Decoder struct { s *stream disallowUnknownFields bool + structTypeToDecoder map[uintptr]decoder } type decoderMap struct { @@ -61,7 +62,9 @@ const ( func NewDecoder(r io.Reader) *Decoder { s := &stream{r: r} s.read() - return &Decoder{s: s} + return &Decoder{ + s: s, + } } // Buffered returns a reader of the data remaining in the Decoder's @@ -90,7 +93,7 @@ func (d *Decoder) decode(src []byte, header *interfaceHeader) error { } dec := cachedDecoder.get(typeptr) if dec == nil { - + d.structTypeToDecoder = map[uintptr]decoder{} compiledDec, err := d.compileHead(copiedType) if err != nil { return err @@ -155,6 +158,7 @@ func (d *Decoder) Decode(v interface{}) error { dec := cachedDecoder.get(typeptr) if dec == nil { + d.structTypeToDecoder = map[uintptr]decoder{} compiledDec, err := d.compileHead(typ) if err != nil { return err diff --git a/decode_compile.go b/decode_compile.go index bb6ab06..1ed11aa 100644 --- a/decode_compile.go +++ b/decode_compile.go @@ -204,6 +204,12 @@ func (d *Decoder) compileInterface(typ *rtype) (decoder, error) { func (d *Decoder) compileStruct(typ *rtype) (decoder, error) { fieldNum := typ.NumField() fieldMap := map[string]*structFieldSet{} + typeptr := uintptr(unsafe.Pointer(typ)) + if dec, exists := d.structTypeToDecoder[typeptr]; exists { + return dec, nil + } + structDec := newStructDecoder(fieldMap) + d.structTypeToDecoder[typeptr] = structDec for i := 0; i < fieldNum; i++ { field := typ.Field(i) if isIgnoredStructField(field) { @@ -222,5 +228,6 @@ func (d *Decoder) compileStruct(typ *rtype) (decoder, error) { fieldMap[tag.key] = fieldSet fieldMap[strings.ToLower(tag.key)] = fieldSet } - return newStructDecoder(fieldMap), nil + delete(d.structTypeToDecoder, typeptr) + return structDec, nil }