From 0661700640c712d666936b15799ce8e5d5242cc7 Mon Sep 17 00:00:00 2001 From: Luke Shumaker Date: Fri, 10 Feb 2023 18:09:19 -0700 Subject: decode: Have .decodeObject take and return *DecodeError --- decode.go | 54 ++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 34 insertions(+), 20 deletions(-) (limited to 'decode.go') diff --git a/decode.go b/decode.go index 976ab9b..275b18c 100644 --- a/decode.go +++ b/decode.go @@ -530,12 +530,13 @@ func (dec *Decoder) decode(val reflect.Value, nullOK bool) (_err *DecodeError) { } index := jsonstruct.IndexStruct(typ) var nameBuf strings.Builder - dec.decodeObject(typ, func() { + return dec.decodeObject(typ, func() *DecodeError { dec.posStackPush() defer dec.posStackPop() nameBuf.Reset() dec.decodeString(nil, &nameBuf) - }, func() { + return nil + }, func() *DecodeError { dec.posStackPush() defer dec.posStackPop() name := nameBuf.String() @@ -556,7 +557,7 @@ func (dec *Decoder) decode(val reflect.Value, nullOK bool) (_err *DecodeError) { dec.panicType("", typ, fmt.Errorf("json: unknown field %q", name)) } dec.scan(fastio.Discard) - return + return nil } field := index.ByPos[idx] fVal := val @@ -604,10 +605,9 @@ func (dec *Decoder) decode(val reflect.Value, nullOK bool) (_err *DecodeError) { fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal unquoted value into %v", fVal.Type())) } + return nil } else { - if err := dec.decode(fVal, true); err != nil { - panic(decodeError(*err)) - } + return dec.decode(fVal, true) } }) case reflect.Map: @@ -621,7 +621,7 @@ func (dec *Decoder) decode(val reflect.Value, nullOK bool) (_err *DecodeError) { } var nameBuf bytes.Buffer var nameValPtr reflect.Value - dec.decodeObject(typ, func() { + return dec.decodeObject(typ, func() *DecodeError { dec.posStackPush() defer dec.posStackPop() nameBuf.Reset() @@ -654,7 +654,8 @@ func (dec *Decoder) decode(val reflect.Value, nullOK bool) (_err *DecodeError) { dec.panicType("object", typ, &DecodeArgumentError{Type: nameValTyp}) } } - }, func() { + return nil + }, func() *DecodeError { dec.posStackPush() defer dec.posStackPop() dec.structStackPush(typ, nameValPtr.Elem()) @@ -666,6 +667,7 @@ func (dec *Decoder) decode(val reflect.Value, nullOK bool) (_err *DecodeError) { } val.SetMapIndex(nameValPtr.Elem(), fValPtr.Elem()) + return nil }) default: dec.panicType(t.JSONType(), typ, nil) @@ -799,19 +801,23 @@ func (dec *Decoder) decodeAny() any { ret := make(map[string]any) typ := reflect.TypeOf(ret) var nameBuf strings.Builder - dec.decodeObject(typ, func() { + if err := dec.decodeObject(typ, func() *DecodeError { dec.posStackPush() defer dec.posStackPop() nameBuf.Reset() dec.decodeString(nil, &nameBuf) - }, func() { + return nil + }, func() *DecodeError { dec.posStackPush() defer dec.posStackPop() name := nameBuf.String() dec.structStackPush(typ, name) defer dec.structStackPop() ret[name] = dec.decodeAny() - }) + return nil + }); err != nil { + panic(decodeError(*err)) + } return ret case '[': ret := []any{} @@ -877,8 +883,8 @@ func DecodeObject(r io.RuneScanner, decodeKey, decodeVal func(io.RuneScanner) er } dec.posStackPush() defer dec.posStackPop() - dec.decodeObject(nil, - func() { + if err := dec.decodeObject(nil, + func() *DecodeError { dec.posStackPush() defer dec.posStackPop() l := dec.limitingScanner() @@ -890,8 +896,9 @@ func DecodeObject(r io.RuneScanner, decodeKey, decodeVal func(io.RuneScanner) er // TODO: Find a better Go type to use than `nil`. dec.panicType("string", nil, fmt.Errorf("did not consume entire string")) } + return nil }, - func() { + func() *DecodeError { dec.posStackPush() defer dec.posStackPop() t := dec.peekRuneType() @@ -904,29 +911,36 @@ func DecodeObject(r io.RuneScanner, decodeKey, decodeVal func(io.RuneScanner) er // TODO: Find a better Go type to use than `nil`. dec.panicType(t.JSONType(), nil, fmt.Errorf("did not consume entire %s", t.JSONType())) } - }) + return nil + }); err != nil { + return err + } return nil } -func (dec *Decoder) decodeObject(gTyp reflect.Type, decodeKey, decodeVal func()) { +func (dec *Decoder) decodeObject(gTyp reflect.Type, decodeKey, decodeVal func() *DecodeError) *DecodeError { dec.expectRuneType('{', jsonparse.RuneTypeObjectBeg, gTyp) _, t := dec.readRune() switch t { case jsonparse.RuneTypeObjectEnd: - return + return nil case jsonparse.RuneTypeStringBeg: decodeMember: dec.unreadRune() - decodeKey() + if err := decodeKey(); err != nil { + return err + } dec.expectRune(':', jsonparse.RuneTypeObjectColon) - decodeVal() + if err := decodeVal(); err != nil { + return err + } _, t := dec.readRune() switch t { case jsonparse.RuneTypeObjectComma: dec.expectRune('"', jsonparse.RuneTypeStringBeg) goto decodeMember case jsonparse.RuneTypeObjectEnd: - return + return nil default: panic("should not happen") } -- cgit v1.2.3-2-g168b