From a8d2fdc1ae082f350c221dbea0cfc9065a6ef2c0 Mon Sep 17 00:00:00 2001 From: Luke Shumaker Date: Fri, 27 Jan 2023 01:59:27 -0700 Subject: decode: Rewrite .scan() to avoid making a new scanner --- decode.go | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'decode.go') diff --git a/decode.go b/decode.go index 645f8de..2078f92 100644 --- a/decode.go +++ b/decode.go @@ -760,14 +760,15 @@ func (dec *Decoder) decode(val reflect.Value, nullOK bool) { } func (dec *Decoder) scan(out fastio.RuneWriter) { - limiter := dec.limitingScanner() + dec.io.PushReadBarrier() for { - c, _, err := limiter.ReadRune() - if err == io.EOF { - return + c, t := dec.readRune() + if t == jsonparse.RuneTypeEOF { + break } _, _ = out.WriteRune(c) } + dec.io.PopReadBarrier() } func (dec *Decoder) scanNumber(gTyp reflect.Type, out fastio.RuneWriter) { -- cgit v1.2.3-2-g168b From ef47f7b3b0c39c6512f55a48324342f95063d3a3 Mon Sep 17 00:00:00 2001 From: Luke Shumaker Date: Fri, 10 Feb 2023 17:57:33 -0700 Subject: decode: Move the recover() from Decode() to decode() --- decode.go | 49 +++++++++++++++++++++++++++++++------------------ 1 file changed, 31 insertions(+), 18 deletions(-) (limited to 'decode.go') diff --git a/decode.go b/decode.go index 2078f92..976ab9b 100644 --- a/decode.go +++ b/decode.go @@ -243,17 +243,9 @@ func (dec *Decoder) Decode(ptr any) (err error) { dec.io.Reset() dec.io.PushReadBarrier() - defer func() { - if r := recover(); r != nil { - if de, ok := r.(decodeError); ok { - pub := DecodeError(de) - err = &pub - } else { - panic(r) - } - } - }() - dec.decode(ptrVal.Elem(), false) + if err := dec.decode(ptrVal.Elem(), false); err != nil { + return err + } dec.io.PopReadBarrier() return nil } @@ -375,7 +367,17 @@ var kind2bits = map[reflect.Kind]int{ reflect.Float64: 64, } -func (dec *Decoder) decode(val reflect.Value, nullOK bool) { +func (dec *Decoder) decode(val reflect.Value, nullOK bool) (_err *DecodeError) { + defer func() { + if r := recover(); r != nil { + if de, ok := r.(decodeError); ok { + pub := DecodeError(de) + _err = &pub + } else { + panic(r) + } + } + }() dec.posStackPush() defer dec.posStackPop() typ := val.Type() @@ -507,7 +509,9 @@ func (dec *Decoder) decode(val reflect.Value, nullOK bool) { // We only need the pointer itself to be settable if we're // decoding null. if ptr.Elem() != val && (ptr.CanSet() || dec.peekRuneType() != jsonparse.RuneTypeNullN) { - dec.decode(ptr, false) + if err := dec.decode(ptr, false); err != nil { + return err + } break } } @@ -601,7 +605,9 @@ func (dec *Decoder) decode(val reflect.Value, nullOK bool) { fVal.Type())) } } else { - dec.decode(fVal, true) + if err := dec.decode(fVal, true); err != nil { + panic(decodeError(*err)) + } } }) case reflect.Map: @@ -655,7 +661,9 @@ func (dec *Decoder) decode(val reflect.Value, nullOK bool) { defer dec.structStackPop() fValPtr := reflect.New(typ.Elem()) - dec.decode(fValPtr.Elem(), false) + if err := dec.decode(fValPtr.Elem(), false); err != nil { + panic(decodeError(*err)) + } val.SetMapIndex(nameValPtr.Elem(), fValPtr.Elem()) }) @@ -710,7 +718,9 @@ func (dec *Decoder) decode(val reflect.Value, nullOK bool) { dec.structStackPush(typ, i) defer dec.structStackPop() mValPtr := reflect.New(typ.Elem()) - dec.decode(mValPtr.Elem(), false) + if err := dec.decode(mValPtr.Elem(), false); err != nil { + panic(decodeError(*err)) + } val.Set(reflect.Append(val, mValPtr.Elem())) i++ }) @@ -732,7 +742,9 @@ func (dec *Decoder) decode(val reflect.Value, nullOK bool) { defer dec.structStackPop() if i < n { mValPtr := reflect.New(typ.Elem()) - dec.decode(mValPtr.Elem(), false) + if err := dec.decode(mValPtr.Elem(), false); err != nil { + panic(decodeError(*err)) + } val.Index(i).Set(mValPtr.Elem()) } else { dec.scan(fastio.Discard) @@ -751,12 +763,13 @@ func (dec *Decoder) decode(val reflect.Value, nullOK bool) { if val.IsNil() { val.Set(reflect.New(typ.Elem())) } - dec.decode(val.Elem(), false) + return dec.decode(val.Elem(), false) } default: dec.panicType("", typ, fmt.Errorf("unsupported type (kind=%v)", typ.Kind())) } } + return nil } func (dec *Decoder) scan(out fastio.RuneWriter) { -- cgit v1.2.3-2-g168b 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 From 891375baa811d92be99c950fdd377d42f03ec0d3 Mon Sep 17 00:00:00 2001 From: Luke Shumaker Date: Fri, 10 Feb 2023 18:16:16 -0700 Subject: decode: Have .decodeArray take and return *DecodeError --- decode.go | 40 ++++++++++++++++++++++++++-------------- 1 file changed, 26 insertions(+), 14 deletions(-) (limited to 'decode.go') diff --git a/decode.go b/decode.go index 275b18c..806ee1d 100644 --- a/decode.go +++ b/decode.go @@ -663,7 +663,7 @@ func (dec *Decoder) decode(val reflect.Value, nullOK bool) (_err *DecodeError) { fValPtr := reflect.New(typ.Elem()) if err := dec.decode(fValPtr.Elem(), false); err != nil { - panic(decodeError(*err)) + return err } val.SetMapIndex(nameValPtr.Elem(), fValPtr.Elem()) @@ -714,17 +714,18 @@ func (dec *Decoder) decode(val reflect.Value, nullOK bool) (_err *DecodeError) { val.Set(val.Slice(0, 0)) } i := 0 - dec.decodeArray(typ, func() { + return dec.decodeArray(typ, func() *DecodeError { dec.posStackPush() defer dec.posStackPop() dec.structStackPush(typ, i) defer dec.structStackPop() mValPtr := reflect.New(typ.Elem()) if err := dec.decode(mValPtr.Elem(), false); err != nil { - panic(decodeError(*err)) + return err } val.Set(reflect.Append(val, mValPtr.Elem())) i++ + return nil }) default: dec.panicType(t.JSONType(), typ, nil) @@ -737,7 +738,7 @@ func (dec *Decoder) decode(val reflect.Value, nullOK bool) (_err *DecodeError) { } i := 0 n := val.Len() - dec.decodeArray(typ, func() { + if err := dec.decodeArray(typ, func() *DecodeError { dec.posStackPush() defer dec.posStackPop() dec.structStackPush(typ, i) @@ -745,14 +746,17 @@ func (dec *Decoder) decode(val reflect.Value, nullOK bool) (_err *DecodeError) { if i < n { mValPtr := reflect.New(typ.Elem()) if err := dec.decode(mValPtr.Elem(), false); err != nil { - panic(decodeError(*err)) + return err } val.Index(i).Set(mValPtr.Elem()) } else { dec.scan(fastio.Discard) } i++ - }) + return nil + }); err != nil { + return err + } for ; i < n; i++ { val.Index(i).Set(reflect.Zero(typ.Elem())) } @@ -822,13 +826,16 @@ func (dec *Decoder) decodeAny() any { case '[': ret := []any{} typ := reflect.TypeOf(ret) - dec.decodeArray(typ, func() { + if err := dec.decodeArray(typ, func() *DecodeError { dec.posStackPush() defer dec.posStackPop() dec.structStackPush(typ, len(ret)) defer dec.structStackPop() ret = append(ret, dec.decodeAny()) - }) + return nil + }); err != nil { + panic(decodeError(*err)) + } return ret case '"': var buf strings.Builder @@ -976,7 +983,7 @@ func DecodeArray(r io.RuneScanner, decodeMember func(r io.RuneScanner) error) (e } dec.posStackPush() defer dec.posStackPop() - dec.decodeArray(nil, func() { + if err := dec.decodeArray(nil, func() *DecodeError { dec.posStackPush() defer dec.posStackPop() t := dec.peekRuneType() @@ -989,26 +996,31 @@ func DecodeArray(r io.RuneScanner, decodeMember func(r io.RuneScanner) error) (e // 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) decodeArray(gTyp reflect.Type, decodeMember func()) { +func (dec *Decoder) decodeArray(gTyp reflect.Type, decodeMember func() *DecodeError) *DecodeError { dec.expectRuneType('[', jsonparse.RuneTypeArrayBeg, gTyp) _, t := dec.readRune() switch t { case jsonparse.RuneTypeArrayEnd: - return + return nil default: dec.unreadRune() decodeNextMember: - decodeMember() + if err := decodeMember(); err != nil { + return err + } _, t := dec.readRune() switch t { case jsonparse.RuneTypeArrayComma: goto decodeNextMember case jsonparse.RuneTypeArrayEnd: - return + return nil default: panic("should not happen") } -- cgit v1.2.3-2-g168b From 9d2ae945e330516fa1b3586262f7fe218ff60d33 Mon Sep 17 00:00:00 2001 From: Luke Shumaker Date: Fri, 10 Feb 2023 18:19:17 -0700 Subject: decode: Have .decodeAny return a *DecodeError --- decode.go | 38 +++++++++++++++++++++++++------------- 1 file changed, 25 insertions(+), 13 deletions(-) (limited to 'decode.go') diff --git a/decode.go b/decode.go index 806ee1d..8c836d5 100644 --- a/decode.go +++ b/decode.go @@ -521,7 +521,11 @@ func (dec *Decoder) decode(val reflect.Value, nullOK bool) (_err *DecodeError) { dec.decodeNull() val.Set(reflect.Zero(typ)) default: - val.Set(reflect.ValueOf(dec.decodeAny())) + v, err := dec.decodeAny() + if err != nil { + return err + } + val.Set(reflect.ValueOf(v)) } case reflect.Struct: if nullOK && dec.peekRuneType() == jsonparse.RuneTypeNullN { @@ -797,7 +801,7 @@ func (dec *Decoder) scanNumber(gTyp reflect.Type, out fastio.RuneWriter) { dec.scan(out) } -func (dec *Decoder) decodeAny() any { +func (dec *Decoder) decodeAny() (any, *DecodeError) { c, _ := dec.readRune() dec.unreadRune() switch c { @@ -817,12 +821,16 @@ func (dec *Decoder) decodeAny() any { name := nameBuf.String() dec.structStackPush(typ, name) defer dec.structStackPop() - ret[name] = dec.decodeAny() + v, err := dec.decodeAny() + if err != nil { + return err + } + ret[name] = v return nil }); err != nil { - panic(decodeError(*err)) + return nil, err } - return ret + return ret, nil case '[': ret := []any{} typ := reflect.TypeOf(ret) @@ -831,33 +839,37 @@ func (dec *Decoder) decodeAny() any { defer dec.posStackPop() dec.structStackPush(typ, len(ret)) defer dec.structStackPop() - ret = append(ret, dec.decodeAny()) + v, err := dec.decodeAny() + if err != nil { + return err + } + ret = append(ret, v) return nil }); err != nil { - panic(decodeError(*err)) + return nil, err } - return ret + return ret, nil case '"': var buf strings.Builder dec.decodeString(nil, &buf) - return buf.String() + return buf.String(), nil case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9': var buf strings.Builder dec.scan(&buf) num := Number(buf.String()) if dec.useNumber { - return num + return num, nil } f64, err := num.Float64() if err != nil { dec.panicType("number "+buf.String(), float64Type, err) } - return f64 + return f64, nil case 't', 'f': - return dec.decodeBool(nil) + return dec.decodeBool(nil), nil case 'n': dec.decodeNull() - return nil + return nil, nil default: panic("should not happen") } -- cgit v1.2.3-2-g168b From 0a1e3f5174191d78513fbcc5fb5bf7fa93032469 Mon Sep 17 00:00:00 2001 From: Luke Shumaker Date: Fri, 27 Jan 2023 01:59:27 -0700 Subject: decode: Separate the scanner's panic-flow from the decoder's panic-flow It may be useful to hit "ignore space change" when viewing this patch. --- decode.go | 105 ++++++++++++++++++++++++++++++++++++-------------------------- 1 file changed, 61 insertions(+), 44 deletions(-) (limited to 'decode.go') diff --git a/decode.go b/decode.go index 8c836d5..b206a88 100644 --- a/decode.go +++ b/decode.go @@ -53,8 +53,8 @@ import ( // or another is encountered; if it does not, then the parent Decode // call will return a *DecodeTypeError. // -// Implementor's note: "limitingScanner" is the thing to search for in -// decode.go if you want to read up on that io.RuneScanner. +// Implementor's note: "withLimitingScanner" is the thing to search +// for in decode.go if you want to read up on that io.RuneScanner. type Decodable interface { DecodeJSON(io.RuneScanner) error } @@ -314,6 +314,8 @@ type decRuneScanner struct { eof bool } +type scannerPanic *DecodeError + func (sc *decRuneScanner) ReadRune() (rune, int, error) { if sc.eof { return 0, 0, io.EOF @@ -325,12 +327,12 @@ func (sc *decRuneScanner) ReadRune() (rune, int, error) { return 0, 0, io.EOF } if e != nil { - panic(decodeError{ + panic(scannerPanic(&DecodeError{ Field: sc.dec.structStackStr(), FieldParent: sc.dec.structStackParent(), FieldName: sc.dec.structStackName(), Err: e, - }) + })) } return c, s, nil } @@ -339,11 +341,21 @@ func (sc *decRuneScanner) UnreadRune() error { return sc.dec.io.UnreadRune() } -func (dec *Decoder) limitingScanner() io.RuneScanner { +func (dec *Decoder) withLimitingScanner(fn func(io.RuneScanner) *DecodeError) (err *DecodeError) { dec.io.PushReadBarrier() - return &decRuneScanner{ - dec: dec, + defer func() { + if r := recover(); r != nil { + if sp, ok := r.(scannerPanic); ok { + err = (*DecodeError)(sp) + } else { + panic(r) + } + } + }() + if err := fn(&decRuneScanner{dec: dec}); err != nil { + return err } + return nil } // decoder main //////////////////////////////////////////////////////////////////////////////////// @@ -392,13 +404,15 @@ func (dec *Decoder) decode(val reflect.Value, nullOK bool) (_err *DecodeError) { case val.CanAddr() && reflect.PointerTo(typ).Implements(decodableType): t := dec.peekRuneType() obj := val.Addr().Interface().(Decodable) - l := dec.limitingScanner() - if err := obj.DecodeJSON(l); err != nil { - dec.panicType(t.JSONType(), reflect.PointerTo(typ), err) - } - if _, _, err := l.ReadRune(); err != io.EOF { - dec.panicType(t.JSONType(), reflect.PointerTo(typ), fmt.Errorf("did not consume entire %s", t.JSONType())) - } + return dec.withLimitingScanner(func(l io.RuneScanner) *DecodeError { + if err := obj.DecodeJSON(l); err != nil { + dec.panicType(t.JSONType(), reflect.PointerTo(typ), err) + } + if _, _, err := l.ReadRune(); err != io.EOF { + dec.panicType(t.JSONType(), reflect.PointerTo(typ), fmt.Errorf("did not consume entire %s", t.JSONType())) + } + return nil + }) case val.CanAddr() && reflect.PointerTo(typ).Implements(jsonUnmarshalerType): t := dec.peekRuneType() var buf bytes.Buffer @@ -906,31 +920,33 @@ func DecodeObject(r io.RuneScanner, decodeKey, decodeVal func(io.RuneScanner) er func() *DecodeError { dec.posStackPush() defer dec.posStackPop() - l := dec.limitingScanner() - if err := decodeKey(l); err != nil { - // TODO: Find a better Go type to use than `nil`. - dec.panicType("string", nil, err) - } - if _, _, err := l.ReadRune(); err != io.EOF { - // TODO: Find a better Go type to use than `nil`. - dec.panicType("string", nil, fmt.Errorf("did not consume entire string")) - } - return nil + return dec.withLimitingScanner(func(l io.RuneScanner) *DecodeError { + if err := decodeKey(l); err != nil { + // TODO: Find a better Go type to use than `nil`. + dec.panicType("string", nil, err) + } + if _, _, err := l.ReadRune(); err != io.EOF { + // TODO: Find a better Go type to use than `nil`. + dec.panicType("string", nil, fmt.Errorf("did not consume entire string")) + } + return nil + }) }, func() *DecodeError { dec.posStackPush() defer dec.posStackPop() t := dec.peekRuneType() - l := dec.limitingScanner() - if err := decodeVal(l); err != nil { - // TODO: Find a better Go type to use than `nil`. - dec.panicType(t.JSONType(), nil, err) - } - if _, _, err := l.ReadRune(); err != io.EOF { - // 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 + return dec.withLimitingScanner(func(l io.RuneScanner) *DecodeError { + if err := decodeVal(l); err != nil { + // TODO: Find a better Go type to use than `nil`. + dec.panicType(t.JSONType(), nil, err) + } + if _, _, err := l.ReadRune(); err != io.EOF { + // 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 } @@ -999,16 +1015,17 @@ func DecodeArray(r io.RuneScanner, decodeMember func(r io.RuneScanner) error) (e dec.posStackPush() defer dec.posStackPop() t := dec.peekRuneType() - l := dec.limitingScanner() - if err := decodeMember(l); err != nil { - // TODO: Find a better Go type to use than `nil`. - dec.panicType(t.JSONType(), nil, err) - } - if _, _, err := l.ReadRune(); err != io.EOF { - // 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 + return dec.withLimitingScanner(func(l io.RuneScanner) *DecodeError { + if err := decodeMember(l); err != nil { + // TODO: Find a better Go type to use than `nil`. + dec.panicType(t.JSONType(), nil, err) + } + if _, _, err := l.ReadRune(); err != io.EOF { + // 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 } -- cgit v1.2.3-2-g168b From d287a39cb902713ab0e5dff2f300c4e161ceb3d7 Mon Sep 17 00:00:00 2001 From: Luke Shumaker Date: Fri, 10 Feb 2023 18:31:41 -0700 Subject: decode: Replace .panicType() with .newTypeError() --- decode.go | 74 ++++++++++++++++++++++++++++++++------------------------------- 1 file changed, 38 insertions(+), 36 deletions(-) (limited to 'decode.go') diff --git a/decode.go b/decode.go index b206a88..a79f7cd 100644 --- a/decode.go +++ b/decode.go @@ -254,8 +254,8 @@ func (dec *Decoder) Decode(ptr any) (err error) { type decodeError DecodeError -func (dec *Decoder) panicType(jTyp string, gTyp reflect.Type, err error) { - panic(decodeError{ +func (dec *Decoder) newTypeError(jTyp string, gTyp reflect.Type, err error) *DecodeError { + return &DecodeError{ Field: dec.structStackStr(), FieldParent: dec.structStackParent(), FieldName: dec.structStackName(), @@ -265,7 +265,7 @@ func (dec *Decoder) panicType(jTyp string, gTyp reflect.Type, err error) { Err: err, Offset: dec.posStack[len(dec.posStack)-1], }, - }) + } } func (dec *Decoder) readRune() (rune, jsonparse.RuneType) { @@ -305,7 +305,8 @@ func (dec *Decoder) expectRune(ec rune, et jsonparse.RuneType) { func (dec *Decoder) expectRuneType(ec rune, et jsonparse.RuneType, gt reflect.Type) { ac, at := dec.readRune() if ac != ec || at != et { - dec.panicType(at.JSONType(), gt, nil) + err := dec.newTypeError(at.JSONType(), gt, nil) + panic(decodeError(*err)) } } @@ -399,17 +400,17 @@ func (dec *Decoder) decode(val reflect.Value, nullOK bool) (_err *DecodeError) { var buf bytes.Buffer dec.scan(&buf) if err := val.Addr().Interface().(*RawMessage).UnmarshalJSON(buf.Bytes()); err != nil { - dec.panicType(t.JSONType(), reflect.PointerTo(typ), err) + return dec.newTypeError(t.JSONType(), reflect.PointerTo(typ), err) } case val.CanAddr() && reflect.PointerTo(typ).Implements(decodableType): t := dec.peekRuneType() obj := val.Addr().Interface().(Decodable) return dec.withLimitingScanner(func(l io.RuneScanner) *DecodeError { if err := obj.DecodeJSON(l); err != nil { - dec.panicType(t.JSONType(), reflect.PointerTo(typ), err) + return dec.newTypeError(t.JSONType(), reflect.PointerTo(typ), err) } if _, _, err := l.ReadRune(); err != io.EOF { - dec.panicType(t.JSONType(), reflect.PointerTo(typ), fmt.Errorf("did not consume entire %s", t.JSONType())) + return dec.newTypeError(t.JSONType(), reflect.PointerTo(typ), fmt.Errorf("did not consume entire %s", t.JSONType())) } return nil }) @@ -419,7 +420,7 @@ func (dec *Decoder) decode(val reflect.Value, nullOK bool) (_err *DecodeError) { dec.scan(&buf) obj := val.Addr().Interface().(jsonUnmarshaler) if err := obj.UnmarshalJSON(buf.Bytes()); err != nil { - dec.panicType(t.JSONType(), reflect.PointerTo(typ), err) + return dec.newTypeError(t.JSONType(), reflect.PointerTo(typ), err) } case val.CanAddr() && reflect.PointerTo(typ).Implements(textUnmarshalerType): if nullOK && dec.peekRuneType() == jsonparse.RuneTypeNullN { @@ -430,7 +431,7 @@ func (dec *Decoder) decode(val reflect.Value, nullOK bool) (_err *DecodeError) { dec.decodeString(reflect.PointerTo(typ), &buf) obj := val.Addr().Interface().(encoding.TextUnmarshaler) if err := obj.UnmarshalText(buf.Bytes()); err != nil { - dec.panicType("string", reflect.PointerTo(typ), err) + return dec.newTypeError("string", reflect.PointerTo(typ), err) } default: switch kind := typ.Kind(); kind { @@ -449,7 +450,7 @@ func (dec *Decoder) decode(val reflect.Value, nullOK bool) (_err *DecodeError) { dec.scanNumber(typ, &buf) n, err := strconv.ParseInt(buf.String(), 10, kind2bits[kind]) if err != nil { - dec.panicType("number "+buf.String(), typ, err) + return dec.newTypeError("number "+buf.String(), typ, err) } val.SetInt(n) case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: @@ -461,7 +462,7 @@ func (dec *Decoder) decode(val reflect.Value, nullOK bool) (_err *DecodeError) { dec.scanNumber(typ, &buf) n, err := strconv.ParseUint(buf.String(), 10, kind2bits[kind]) if err != nil { - dec.panicType("number "+buf.String(), typ, err) + return dec.newTypeError("number "+buf.String(), typ, err) } val.SetUint(n) case reflect.Float32, reflect.Float64: @@ -473,7 +474,7 @@ func (dec *Decoder) decode(val reflect.Value, nullOK bool) (_err *DecodeError) { dec.scanNumber(typ, &buf) n, err := strconv.ParseFloat(buf.String(), kind2bits[kind]) if err != nil { - dec.panicType("number "+buf.String(), typ, err) + return dec.newTypeError("number "+buf.String(), typ, err) } val.SetFloat(n) case reflect.String: @@ -486,7 +487,7 @@ func (dec *Decoder) decode(val reflect.Value, nullOK bool) (_err *DecodeError) { t := dec.peekRuneType() dec.scan(&buf) if !t.IsNumber() { - dec.panicType(t.JSONType(), typ, + return dec.newTypeError(t.JSONType(), typ, fmt.Errorf("json: invalid number literal, trying to unmarshal %q into Number", buf.String())) } @@ -497,7 +498,7 @@ func (dec *Decoder) decode(val reflect.Value, nullOK bool) (_err *DecodeError) { } case reflect.Interface: if typ.NumMethod() > 0 { - dec.panicType(dec.peekRuneType().JSONType(), typ, ErrDecodeNonEmptyInterface) + return dec.newTypeError(dec.peekRuneType().JSONType(), typ, ErrDecodeNonEmptyInterface) } // If the interface stores a pointer, try to use the type information of the pointer. if !val.IsNil() && val.Elem().Kind() == reflect.Pointer { @@ -572,7 +573,7 @@ func (dec *Decoder) decode(val reflect.Value, nullOK bool) (_err *DecodeError) { } if !ok { if dec.disallowUnknownFields { - dec.panicType("", typ, fmt.Errorf("json: unknown field %q", name)) + return dec.newTypeError("", typ, fmt.Errorf("json: unknown field %q", name)) } dec.scan(fastio.Discard) return nil @@ -582,7 +583,7 @@ func (dec *Decoder) decode(val reflect.Value, nullOK bool) (_err *DecodeError) { for _, idx := range field.Path { if fVal.Kind() == reflect.Pointer { if fVal.IsNil() && !fVal.CanSet() { // https://golang.org/issue/21357 - dec.panicType("", fVal.Type().Elem(), + return dec.newTypeError("", fVal.Type().Elem(), fmt.Errorf("json: cannot set embedded pointer to unexported struct: %v", fVal.Type().Elem())) } @@ -613,13 +614,13 @@ func (dec *Decoder) decode(val reflect.Value, nullOK bool) (_err *DecodeError) { dec.decodeString(nil, &buf) if err := NewDecoder(bytes.NewReader(buf.Bytes())).Decode(fVal.Addr().Interface()); err != nil { if str := buf.String(); str != "null" { - dec.panicType("", fVal.Type(), + return dec.newTypeError("", fVal.Type(), fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", str, fVal.Type())) } } default: - dec.panicType(t.JSONType(), fVal.Type(), + return dec.newTypeError(t.JSONType(), fVal.Type(), fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal unquoted value into %v", fVal.Type())) } @@ -650,7 +651,7 @@ func (dec *Decoder) decode(val reflect.Value, nullOK bool) (_err *DecodeError) { case reflect.PointerTo(nameValTyp).Implements(textUnmarshalerType): obj := nameValPtr.Interface().(encoding.TextUnmarshaler) if err := obj.UnmarshalText(nameBuf.Bytes()); err != nil { - dec.panicType("string", reflect.PointerTo(nameValTyp), err) + return dec.newTypeError("string", reflect.PointerTo(nameValTyp), err) } default: switch nameValTyp.Kind() { @@ -659,17 +660,17 @@ func (dec *Decoder) decode(val reflect.Value, nullOK bool) (_err *DecodeError) { case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: n, err := strconv.ParseInt(nameBuf.String(), 10, kind2bits[nameValTyp.Kind()]) if err != nil { - dec.panicType("number "+nameBuf.String(), nameValTyp, err) + return dec.newTypeError("number "+nameBuf.String(), nameValTyp, err) } nameValPtr.Elem().SetInt(n) case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: n, err := strconv.ParseUint(nameBuf.String(), 10, kind2bits[nameValTyp.Kind()]) if err != nil { - dec.panicType("number "+nameBuf.String(), nameValTyp, err) + return dec.newTypeError("number "+nameBuf.String(), nameValTyp, err) } nameValPtr.Elem().SetUint(n) default: - dec.panicType("object", typ, &DecodeArgumentError{Type: nameValTyp}) + return dec.newTypeError("object", typ, &DecodeArgumentError{Type: nameValTyp}) } } return nil @@ -688,7 +689,7 @@ func (dec *Decoder) decode(val reflect.Value, nullOK bool) (_err *DecodeError) { return nil }) default: - dec.panicType(t.JSONType(), typ, nil) + return dec.newTypeError(t.JSONType(), typ, nil) } case reflect.Slice: switch { @@ -717,7 +718,7 @@ func (dec *Decoder) decode(val reflect.Value, nullOK bool) (_err *DecodeError) { } } default: - dec.panicType(t.JSONType(), typ, nil) + return dec.newTypeError(t.JSONType(), typ, nil) } default: switch t := dec.peekRuneType(); t { @@ -746,7 +747,7 @@ func (dec *Decoder) decode(val reflect.Value, nullOK bool) (_err *DecodeError) { return nil }) default: - dec.panicType(t.JSONType(), typ, nil) + return dec.newTypeError(t.JSONType(), typ, nil) } } case reflect.Array: @@ -790,7 +791,7 @@ func (dec *Decoder) decode(val reflect.Value, nullOK bool) (_err *DecodeError) { return dec.decode(val.Elem(), false) } default: - dec.panicType("", typ, fmt.Errorf("unsupported type (kind=%v)", typ.Kind())) + return dec.newTypeError("", typ, fmt.Errorf("unsupported type (kind=%v)", typ.Kind())) } } return nil @@ -810,7 +811,8 @@ func (dec *Decoder) scan(out fastio.RuneWriter) { func (dec *Decoder) scanNumber(gTyp reflect.Type, out fastio.RuneWriter) { if t := dec.peekRuneType(); !t.IsNumber() { - dec.panicType(t.JSONType(), gTyp, nil) + err := dec.newTypeError(t.JSONType(), gTyp, nil) + panic(decodeError(*err)) } dec.scan(out) } @@ -876,7 +878,7 @@ func (dec *Decoder) decodeAny() (any, *DecodeError) { } f64, err := num.Float64() if err != nil { - dec.panicType("number "+buf.String(), float64Type, err) + return nil, dec.newTypeError("number "+buf.String(), float64Type, err) } return f64, nil case 't', 'f': @@ -923,11 +925,11 @@ func DecodeObject(r io.RuneScanner, decodeKey, decodeVal func(io.RuneScanner) er return dec.withLimitingScanner(func(l io.RuneScanner) *DecodeError { if err := decodeKey(l); err != nil { // TODO: Find a better Go type to use than `nil`. - dec.panicType("string", nil, err) + return dec.newTypeError("string", nil, err) } if _, _, err := l.ReadRune(); err != io.EOF { // TODO: Find a better Go type to use than `nil`. - dec.panicType("string", nil, fmt.Errorf("did not consume entire string")) + return dec.newTypeError("string", nil, fmt.Errorf("did not consume entire string")) } return nil }) @@ -939,11 +941,11 @@ func DecodeObject(r io.RuneScanner, decodeKey, decodeVal func(io.RuneScanner) er return dec.withLimitingScanner(func(l io.RuneScanner) *DecodeError { if err := decodeVal(l); err != nil { // TODO: Find a better Go type to use than `nil`. - dec.panicType(t.JSONType(), nil, err) + return dec.newTypeError(t.JSONType(), nil, err) } if _, _, err := l.ReadRune(); err != io.EOF { // 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 dec.newTypeError(t.JSONType(), nil, fmt.Errorf("did not consume entire %s", t.JSONType())) } return nil }) @@ -1018,11 +1020,11 @@ func DecodeArray(r io.RuneScanner, decodeMember func(r io.RuneScanner) error) (e return dec.withLimitingScanner(func(l io.RuneScanner) *DecodeError { if err := decodeMember(l); err != nil { // TODO: Find a better Go type to use than `nil`. - dec.panicType(t.JSONType(), nil, err) + return dec.newTypeError(t.JSONType(), nil, err) } if _, _, err := l.ReadRune(); err != io.EOF { // 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 dec.newTypeError(t.JSONType(), nil, fmt.Errorf("did not consume entire %s", t.JSONType())) } return nil }) @@ -1159,8 +1161,8 @@ func (dec *Decoder) decodeBool(gTyp reflect.Type) bool { dec.expectRune('e', jsonparse.RuneTypeFalseE) return false default: - dec.panicType(t.JSONType(), gTyp, nil) - panic("not reached") + err := dec.newTypeError(t.JSONType(), gTyp, nil) + panic(decodeError(*err)) } } -- cgit v1.2.3-2-g168b From 3aa6f66af3ceff7e0d9044678dbf1edeec1bc09d Mon Sep 17 00:00:00 2001 From: Luke Shumaker Date: Fri, 10 Feb 2023 18:33:45 -0700 Subject: decode: Have .decodeBool() return a *DecodeError --- decode.go | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) (limited to 'decode.go') diff --git a/decode.go b/decode.go index a79f7cd..237c739 100644 --- a/decode.go +++ b/decode.go @@ -440,7 +440,11 @@ func (dec *Decoder) decode(val reflect.Value, nullOK bool) (_err *DecodeError) { dec.decodeNull() return } - val.SetBool(dec.decodeBool(typ)) + b, err := dec.decodeBool(typ) + if err != nil { + return err + } + val.SetBool(b) case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: if nullOK && dec.peekRuneType() == jsonparse.RuneTypeNullN { dec.decodeNull() @@ -882,7 +886,7 @@ func (dec *Decoder) decodeAny() (any, *DecodeError) { } return f64, nil case 't', 'f': - return dec.decodeBool(nil), nil + return dec.decodeBool(nil) case 'n': dec.decodeNull() return nil, nil @@ -1146,23 +1150,22 @@ func (dec *Decoder) decodeString(gTyp reflect.Type, out fastio.RuneWriter) { } } -func (dec *Decoder) decodeBool(gTyp reflect.Type) bool { +func (dec *Decoder) decodeBool(gTyp reflect.Type) (bool, *DecodeError) { c, t := dec.readRune() switch c { case 't': dec.expectRune('r', jsonparse.RuneTypeTrueR) dec.expectRune('u', jsonparse.RuneTypeTrueU) dec.expectRune('e', jsonparse.RuneTypeTrueE) - return true + return true, nil case 'f': dec.expectRune('a', jsonparse.RuneTypeFalseA) dec.expectRune('l', jsonparse.RuneTypeFalseL) dec.expectRune('s', jsonparse.RuneTypeFalseS) dec.expectRune('e', jsonparse.RuneTypeFalseE) - return false + return false, nil default: - err := dec.newTypeError(t.JSONType(), gTyp, nil) - panic(decodeError(*err)) + return false, dec.newTypeError(t.JSONType(), gTyp, nil) } } -- cgit v1.2.3-2-g168b From 46f143c7336f723ce5ba9bda5d78f11b19efda4f Mon Sep 17 00:00:00 2001 From: Luke Shumaker Date: Fri, 10 Feb 2023 18:36:36 -0700 Subject: decode: Have .decodeNull() return a *DecodeError --- decode.go | 54 +++++++++++++++++++++++++++++------------------------- 1 file changed, 29 insertions(+), 25 deletions(-) (limited to 'decode.go') diff --git a/decode.go b/decode.go index 237c739..522e41e 100644 --- a/decode.go +++ b/decode.go @@ -424,8 +424,7 @@ func (dec *Decoder) decode(val reflect.Value, nullOK bool) (_err *DecodeError) { } case val.CanAddr() && reflect.PointerTo(typ).Implements(textUnmarshalerType): if nullOK && dec.peekRuneType() == jsonparse.RuneTypeNullN { - dec.decodeNull() - return + return dec.decodeNull() } var buf bytes.Buffer dec.decodeString(reflect.PointerTo(typ), &buf) @@ -437,8 +436,7 @@ func (dec *Decoder) decode(val reflect.Value, nullOK bool) (_err *DecodeError) { switch kind := typ.Kind(); kind { case reflect.Bool: if nullOK && dec.peekRuneType() == jsonparse.RuneTypeNullN { - dec.decodeNull() - return + return dec.decodeNull() } b, err := dec.decodeBool(typ) if err != nil { @@ -447,8 +445,7 @@ func (dec *Decoder) decode(val reflect.Value, nullOK bool) (_err *DecodeError) { val.SetBool(b) case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: if nullOK && dec.peekRuneType() == jsonparse.RuneTypeNullN { - dec.decodeNull() - return + return dec.decodeNull() } var buf strings.Builder dec.scanNumber(typ, &buf) @@ -459,8 +456,7 @@ func (dec *Decoder) decode(val reflect.Value, nullOK bool) (_err *DecodeError) { val.SetInt(n) case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: if nullOK && dec.peekRuneType() == jsonparse.RuneTypeNullN { - dec.decodeNull() - return + return dec.decodeNull() } var buf strings.Builder dec.scanNumber(typ, &buf) @@ -471,8 +467,7 @@ func (dec *Decoder) decode(val reflect.Value, nullOK bool) (_err *DecodeError) { val.SetUint(n) case reflect.Float32, reflect.Float64: if nullOK && dec.peekRuneType() == jsonparse.RuneTypeNullN { - dec.decodeNull() - return + return dec.decodeNull() } var buf strings.Builder dec.scanNumber(typ, &buf) @@ -483,8 +478,7 @@ func (dec *Decoder) decode(val reflect.Value, nullOK bool) (_err *DecodeError) { val.SetFloat(n) case reflect.String: if nullOK && dec.peekRuneType() == jsonparse.RuneTypeNullN { - dec.decodeNull() - return + return dec.decodeNull() } var buf strings.Builder if typ == numberType { @@ -537,7 +531,9 @@ func (dec *Decoder) decode(val reflect.Value, nullOK bool) (_err *DecodeError) { // Couldn't get type information from a pointer; fall back to untyped mode. switch dec.peekRuneType() { case jsonparse.RuneTypeNullN: - dec.decodeNull() + if err := dec.decodeNull(); err != nil { + return err + } val.Set(reflect.Zero(typ)) default: v, err := dec.decodeAny() @@ -548,8 +544,7 @@ func (dec *Decoder) decode(val reflect.Value, nullOK bool) (_err *DecodeError) { } case reflect.Struct: if nullOK && dec.peekRuneType() == jsonparse.RuneTypeNullN { - dec.decodeNull() - return + return dec.decodeNull() } index := jsonstruct.IndexStruct(typ) var nameBuf strings.Builder @@ -603,7 +598,9 @@ func (dec *Decoder) decode(val reflect.Value, nullOK bool) (_err *DecodeError) { if field.Quote { switch t := dec.peekRuneType(); t { case jsonparse.RuneTypeNullN: - dec.decodeNull() + if err := dec.decodeNull(); err != nil { + return err + } switch fVal.Kind() { // XXX: I can't justify this list, other than "it's what encoding/json // does, but I don't understand their rationale". @@ -636,7 +633,9 @@ func (dec *Decoder) decode(val reflect.Value, nullOK bool) (_err *DecodeError) { case reflect.Map: switch t := dec.peekRuneType(); t { case jsonparse.RuneTypeNullN: - dec.decodeNull() + if err := dec.decodeNull(); err != nil { + return err + } val.Set(reflect.Zero(typ)) case jsonparse.RuneTypeObjectBeg: if val.IsNil() { @@ -703,7 +702,9 @@ func (dec *Decoder) decode(val reflect.Value, nullOK bool) (_err *DecodeError) { reflect.PointerTo(typ.Elem()).Implements(textUnmarshalerType))): switch t := dec.peekRuneType(); t { case jsonparse.RuneTypeNullN: - dec.decodeNull() + if err := dec.decodeNull(); err != nil { + return err + } val.Set(reflect.Zero(typ)) case jsonparse.RuneTypeStringBeg: if typ.Elem() == byteType { @@ -727,7 +728,9 @@ func (dec *Decoder) decode(val reflect.Value, nullOK bool) (_err *DecodeError) { default: switch t := dec.peekRuneType(); t { case jsonparse.RuneTypeNullN: - dec.decodeNull() + if err := dec.decodeNull(); err != nil { + return err + } val.Set(reflect.Zero(typ)) case jsonparse.RuneTypeArrayBeg: if val.IsNil() { @@ -756,8 +759,7 @@ func (dec *Decoder) decode(val reflect.Value, nullOK bool) (_err *DecodeError) { } case reflect.Array: if nullOK && dec.peekRuneType() == jsonparse.RuneTypeNullN { - dec.decodeNull() - return + return dec.decodeNull() } i := 0 n := val.Len() @@ -786,7 +788,9 @@ func (dec *Decoder) decode(val reflect.Value, nullOK bool) (_err *DecodeError) { case reflect.Pointer: switch dec.peekRuneType() { case jsonparse.RuneTypeNullN: - dec.decodeNull() + if err := dec.decodeNull(); err != nil { + return err + } val.Set(reflect.Zero(typ)) default: if val.IsNil() { @@ -888,8 +892,7 @@ func (dec *Decoder) decodeAny() (any, *DecodeError) { case 't', 'f': return dec.decodeBool(nil) case 'n': - dec.decodeNull() - return nil, nil + return nil, dec.decodeNull() default: panic("should not happen") } @@ -1169,9 +1172,10 @@ func (dec *Decoder) decodeBool(gTyp reflect.Type) (bool, *DecodeError) { } } -func (dec *Decoder) decodeNull() { +func (dec *Decoder) decodeNull() *DecodeError { dec.expectRune('n', jsonparse.RuneTypeNullN) dec.expectRune('u', jsonparse.RuneTypeNullU) dec.expectRune('l', jsonparse.RuneTypeNullL1) dec.expectRune('l', jsonparse.RuneTypeNullL2) + return nil } -- cgit v1.2.3-2-g168b From 46f4b0c2a67911b7438621b6181f5888b8be55b6 Mon Sep 17 00:00:00 2001 From: Luke Shumaker Date: Fri, 10 Feb 2023 18:40:08 -0700 Subject: decode: Have .scan() and .scanNumber() return *DecodeError --- decode.go | 45 ++++++++++++++++++++++++++++++--------------- 1 file changed, 30 insertions(+), 15 deletions(-) (limited to 'decode.go') diff --git a/decode.go b/decode.go index 522e41e..de10370 100644 --- a/decode.go +++ b/decode.go @@ -398,7 +398,9 @@ func (dec *Decoder) decode(val reflect.Value, nullOK bool) (_err *DecodeError) { case val.CanAddr() && reflect.PointerTo(typ) == rawMessagePtrType: t := dec.peekRuneType() var buf bytes.Buffer - dec.scan(&buf) + if err := dec.scan(&buf); err != nil { + return err + } if err := val.Addr().Interface().(*RawMessage).UnmarshalJSON(buf.Bytes()); err != nil { return dec.newTypeError(t.JSONType(), reflect.PointerTo(typ), err) } @@ -417,7 +419,9 @@ func (dec *Decoder) decode(val reflect.Value, nullOK bool) (_err *DecodeError) { case val.CanAddr() && reflect.PointerTo(typ).Implements(jsonUnmarshalerType): t := dec.peekRuneType() var buf bytes.Buffer - dec.scan(&buf) + if err := dec.scan(&buf); err != nil { + return err + } obj := val.Addr().Interface().(jsonUnmarshaler) if err := obj.UnmarshalJSON(buf.Bytes()); err != nil { return dec.newTypeError(t.JSONType(), reflect.PointerTo(typ), err) @@ -448,7 +452,9 @@ func (dec *Decoder) decode(val reflect.Value, nullOK bool) (_err *DecodeError) { return dec.decodeNull() } var buf strings.Builder - dec.scanNumber(typ, &buf) + if err := dec.scanNumber(typ, &buf); err != nil { + return err + } n, err := strconv.ParseInt(buf.String(), 10, kind2bits[kind]) if err != nil { return dec.newTypeError("number "+buf.String(), typ, err) @@ -459,7 +465,9 @@ func (dec *Decoder) decode(val reflect.Value, nullOK bool) (_err *DecodeError) { return dec.decodeNull() } var buf strings.Builder - dec.scanNumber(typ, &buf) + if err := dec.scanNumber(typ, &buf); err != nil { + return err + } n, err := strconv.ParseUint(buf.String(), 10, kind2bits[kind]) if err != nil { return dec.newTypeError("number "+buf.String(), typ, err) @@ -470,7 +478,9 @@ func (dec *Decoder) decode(val reflect.Value, nullOK bool) (_err *DecodeError) { return dec.decodeNull() } var buf strings.Builder - dec.scanNumber(typ, &buf) + if err := dec.scanNumber(typ, &buf); err != nil { + return err + } n, err := strconv.ParseFloat(buf.String(), kind2bits[kind]) if err != nil { return dec.newTypeError("number "+buf.String(), typ, err) @@ -483,7 +493,9 @@ func (dec *Decoder) decode(val reflect.Value, nullOK bool) (_err *DecodeError) { var buf strings.Builder if typ == numberType { t := dec.peekRuneType() - dec.scan(&buf) + if err := dec.scan(&buf); err != nil { + return err + } if !t.IsNumber() { return dec.newTypeError(t.JSONType(), typ, fmt.Errorf("json: invalid number literal, trying to unmarshal %q into Number", @@ -574,8 +586,7 @@ func (dec *Decoder) decode(val reflect.Value, nullOK bool) (_err *DecodeError) { if dec.disallowUnknownFields { return dec.newTypeError("", typ, fmt.Errorf("json: unknown field %q", name)) } - dec.scan(fastio.Discard) - return nil + return dec.scan(fastio.Discard) } field := index.ByPos[idx] fVal := val @@ -775,7 +786,9 @@ func (dec *Decoder) decode(val reflect.Value, nullOK bool) (_err *DecodeError) { } val.Index(i).Set(mValPtr.Elem()) } else { - dec.scan(fastio.Discard) + if err := dec.scan(fastio.Discard); err != nil { + return err + } } i++ return nil @@ -805,7 +818,7 @@ func (dec *Decoder) decode(val reflect.Value, nullOK bool) (_err *DecodeError) { return nil } -func (dec *Decoder) scan(out fastio.RuneWriter) { +func (dec *Decoder) scan(out fastio.RuneWriter) *DecodeError { dec.io.PushReadBarrier() for { c, t := dec.readRune() @@ -815,14 +828,14 @@ func (dec *Decoder) scan(out fastio.RuneWriter) { _, _ = out.WriteRune(c) } dec.io.PopReadBarrier() + return nil } -func (dec *Decoder) scanNumber(gTyp reflect.Type, out fastio.RuneWriter) { +func (dec *Decoder) scanNumber(gTyp reflect.Type, out fastio.RuneWriter) *DecodeError { if t := dec.peekRuneType(); !t.IsNumber() { - err := dec.newTypeError(t.JSONType(), gTyp, nil) - panic(decodeError(*err)) + return dec.newTypeError(t.JSONType(), gTyp, nil) } - dec.scan(out) + return dec.scan(out) } func (dec *Decoder) decodeAny() (any, *DecodeError) { @@ -879,7 +892,9 @@ func (dec *Decoder) decodeAny() (any, *DecodeError) { return buf.String(), nil case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9': var buf strings.Builder - dec.scan(&buf) + if err := dec.scan(&buf); err != nil { + return nil, err + } num := Number(buf.String()) if dec.useNumber { return num, nil -- cgit v1.2.3-2-g168b From abd63cfa18dbb5d9ef37f07442e70d2d9d9e6b49 Mon Sep 17 00:00:00 2001 From: Luke Shumaker Date: Fri, 10 Feb 2023 18:44:18 -0700 Subject: decode: Have .decodeString() return a *DecodeError --- decode.go | 38 +++++++++++++++++++++++++------------- 1 file changed, 25 insertions(+), 13 deletions(-) (limited to 'decode.go') diff --git a/decode.go b/decode.go index de10370..77652af 100644 --- a/decode.go +++ b/decode.go @@ -431,7 +431,9 @@ func (dec *Decoder) decode(val reflect.Value, nullOK bool) (_err *DecodeError) { return dec.decodeNull() } var buf bytes.Buffer - dec.decodeString(reflect.PointerTo(typ), &buf) + if err := dec.decodeString(reflect.PointerTo(typ), &buf); err != nil { + return err + } obj := val.Addr().Interface().(encoding.TextUnmarshaler) if err := obj.UnmarshalText(buf.Bytes()); err != nil { return dec.newTypeError("string", reflect.PointerTo(typ), err) @@ -503,7 +505,9 @@ func (dec *Decoder) decode(val reflect.Value, nullOK bool) (_err *DecodeError) { } val.SetString(buf.String()) } else { - dec.decodeString(typ, &buf) + if err := dec.decodeString(typ, &buf); err != nil { + return err + } val.SetString(buf.String()) } case reflect.Interface: @@ -564,8 +568,7 @@ func (dec *Decoder) decode(val reflect.Value, nullOK bool) (_err *DecodeError) { dec.posStackPush() defer dec.posStackPop() nameBuf.Reset() - dec.decodeString(nil, &nameBuf) - return nil + return dec.decodeString(nil, &nameBuf) }, func() *DecodeError { dec.posStackPush() defer dec.posStackPop() @@ -623,7 +626,9 @@ func (dec *Decoder) decode(val reflect.Value, nullOK bool) (_err *DecodeError) { case jsonparse.RuneTypeStringBeg: // TODO: Figure out how to do this without buffering, have correct offsets. var buf bytes.Buffer - dec.decodeString(nil, &buf) + if err := dec.decodeString(nil, &buf); err != nil { + return err + } if err := NewDecoder(bytes.NewReader(buf.Bytes())).Decode(fVal.Addr().Interface()); err != nil { if str := buf.String(); str != "null" { return dec.newTypeError("", fVal.Type(), @@ -658,7 +663,9 @@ func (dec *Decoder) decode(val reflect.Value, nullOK bool) (_err *DecodeError) { dec.posStackPush() defer dec.posStackPop() nameBuf.Reset() - dec.decodeString(nil, &nameBuf) + if err := dec.decodeString(nil, &nameBuf); err != nil { + return err + } nameValTyp := typ.Key() nameValPtr = reflect.New(nameValTyp) switch { @@ -720,13 +727,17 @@ func (dec *Decoder) decode(val reflect.Value, nullOK bool) (_err *DecodeError) { case jsonparse.RuneTypeStringBeg: if typ.Elem() == byteType { var buf bytes.Buffer - dec.decodeString(typ, base64dec.NewBase64Decoder(&buf)) + if err := dec.decodeString(typ, base64dec.NewBase64Decoder(&buf)); err != nil { + return err + } val.Set(reflect.ValueOf(buf.Bytes())) } else { // TODO: Surely there's a better way. At the very least, we should // avoid buffering. var buf bytes.Buffer - dec.decodeString(typ, base64dec.NewBase64Decoder(&buf)) + if err := dec.decodeString(typ, base64dec.NewBase64Decoder(&buf)); err != nil { + return err + } bs := buf.Bytes() val.Set(reflect.MakeSlice(typ, len(bs), len(bs))) for i := 0; i < len(bs); i++ { @@ -850,8 +861,7 @@ func (dec *Decoder) decodeAny() (any, *DecodeError) { dec.posStackPush() defer dec.posStackPop() nameBuf.Reset() - dec.decodeString(nil, &nameBuf) - return nil + return dec.decodeString(nil, &nameBuf) }, func() *DecodeError { dec.posStackPush() defer dec.posStackPop() @@ -888,7 +898,9 @@ func (dec *Decoder) decodeAny() (any, *DecodeError) { return ret, nil case '"': var buf strings.Builder - dec.decodeString(nil, &buf) + if err := dec.decodeString(nil, &buf); err != nil { + return nil, err + } return buf.String(), nil case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9': var buf strings.Builder @@ -1080,7 +1092,7 @@ func (dec *Decoder) decodeArray(gTyp reflect.Type, decodeMember func() *DecodeEr } } -func (dec *Decoder) decodeString(gTyp reflect.Type, out fastio.RuneWriter) { +func (dec *Decoder) decodeString(gTyp reflect.Type, out fastio.RuneWriter) *DecodeError { dec.expectRuneType('"', jsonparse.RuneTypeStringBeg, gTyp) var uhex [4]byte for { @@ -1161,7 +1173,7 @@ func (dec *Decoder) decodeString(gTyp reflect.Type, out fastio.RuneWriter) { _, _ = out.WriteRune(c) } case jsonparse.RuneTypeStringEnd: - return + return nil default: panic("should not happen") } -- cgit v1.2.3-2-g168b From 2b6a4ece366b83ddd53d91b41a62b9c5d548958d Mon Sep 17 00:00:00 2001 From: Luke Shumaker Date: Fri, 10 Feb 2023 18:46:00 -0700 Subject: decode: Have .expectRuneType() return a *DecodeError --- decode.go | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) (limited to 'decode.go') diff --git a/decode.go b/decode.go index 77652af..60667c0 100644 --- a/decode.go +++ b/decode.go @@ -302,12 +302,12 @@ func (dec *Decoder) expectRune(ec rune, et jsonparse.RuneType) { } } -func (dec *Decoder) expectRuneType(ec rune, et jsonparse.RuneType, gt reflect.Type) { +func (dec *Decoder) expectRuneType(ec rune, et jsonparse.RuneType, gt reflect.Type) *DecodeError { ac, at := dec.readRune() if ac != ec || at != et { - err := dec.newTypeError(at.JSONType(), gt, nil) - panic(decodeError(*err)) + return dec.newTypeError(at.JSONType(), gt, nil) } + return nil } type decRuneScanner struct { @@ -990,7 +990,9 @@ func DecodeObject(r io.RuneScanner, decodeKey, decodeVal func(io.RuneScanner) er } func (dec *Decoder) decodeObject(gTyp reflect.Type, decodeKey, decodeVal func() *DecodeError) *DecodeError { - dec.expectRuneType('{', jsonparse.RuneTypeObjectBeg, gTyp) + if err := dec.expectRuneType('{', jsonparse.RuneTypeObjectBeg, gTyp); err != nil { + return err + } _, t := dec.readRune() switch t { case jsonparse.RuneTypeObjectEnd: @@ -1069,7 +1071,9 @@ func DecodeArray(r io.RuneScanner, decodeMember func(r io.RuneScanner) error) (e } func (dec *Decoder) decodeArray(gTyp reflect.Type, decodeMember func() *DecodeError) *DecodeError { - dec.expectRuneType('[', jsonparse.RuneTypeArrayBeg, gTyp) + if err := dec.expectRuneType('[', jsonparse.RuneTypeArrayBeg, gTyp); err != nil { + return err + } _, t := dec.readRune() switch t { case jsonparse.RuneTypeArrayEnd: @@ -1093,7 +1097,9 @@ func (dec *Decoder) decodeArray(gTyp reflect.Type, decodeMember func() *DecodeEr } func (dec *Decoder) decodeString(gTyp reflect.Type, out fastio.RuneWriter) *DecodeError { - dec.expectRuneType('"', jsonparse.RuneTypeStringBeg, gTyp) + if err := dec.expectRuneType('"', jsonparse.RuneTypeStringBeg, gTyp); err != nil { + return err + } var uhex [4]byte for { c, t := dec.readRune() -- cgit v1.2.3-2-g168b From bdf0402da0d050f95a547da8a7a3752e9db0111b Mon Sep 17 00:00:00 2001 From: Luke Shumaker Date: Fri, 10 Feb 2023 18:57:23 -0700 Subject: decode: Add a .maybeDecodeNull helper This doesn't help much now, but it will help next commit when I add a *DecodeError return value from .peekRuneType(). --- decode.go | 42 ++++++++++++++++++++++++++---------------- 1 file changed, 26 insertions(+), 16 deletions(-) (limited to 'decode.go') diff --git a/decode.go b/decode.go index 60667c0..73d15c5 100644 --- a/decode.go +++ b/decode.go @@ -427,8 +427,8 @@ func (dec *Decoder) decode(val reflect.Value, nullOK bool) (_err *DecodeError) { return dec.newTypeError(t.JSONType(), reflect.PointerTo(typ), err) } case val.CanAddr() && reflect.PointerTo(typ).Implements(textUnmarshalerType): - if nullOK && dec.peekRuneType() == jsonparse.RuneTypeNullN { - return dec.decodeNull() + if ok, err := dec.maybeDecodeNull(nullOK); ok { + return err } var buf bytes.Buffer if err := dec.decodeString(reflect.PointerTo(typ), &buf); err != nil { @@ -441,8 +441,8 @@ func (dec *Decoder) decode(val reflect.Value, nullOK bool) (_err *DecodeError) { default: switch kind := typ.Kind(); kind { case reflect.Bool: - if nullOK && dec.peekRuneType() == jsonparse.RuneTypeNullN { - return dec.decodeNull() + if ok, err := dec.maybeDecodeNull(nullOK); ok { + return err } b, err := dec.decodeBool(typ) if err != nil { @@ -450,8 +450,8 @@ func (dec *Decoder) decode(val reflect.Value, nullOK bool) (_err *DecodeError) { } val.SetBool(b) case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: - if nullOK && dec.peekRuneType() == jsonparse.RuneTypeNullN { - return dec.decodeNull() + if ok, err := dec.maybeDecodeNull(nullOK); ok { + return err } var buf strings.Builder if err := dec.scanNumber(typ, &buf); err != nil { @@ -463,8 +463,8 @@ func (dec *Decoder) decode(val reflect.Value, nullOK bool) (_err *DecodeError) { } val.SetInt(n) case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: - if nullOK && dec.peekRuneType() == jsonparse.RuneTypeNullN { - return dec.decodeNull() + if ok, err := dec.maybeDecodeNull(nullOK); ok { + return err } var buf strings.Builder if err := dec.scanNumber(typ, &buf); err != nil { @@ -476,8 +476,8 @@ func (dec *Decoder) decode(val reflect.Value, nullOK bool) (_err *DecodeError) { } val.SetUint(n) case reflect.Float32, reflect.Float64: - if nullOK && dec.peekRuneType() == jsonparse.RuneTypeNullN { - return dec.decodeNull() + if ok, err := dec.maybeDecodeNull(nullOK); ok { + return err } var buf strings.Builder if err := dec.scanNumber(typ, &buf); err != nil { @@ -489,8 +489,8 @@ func (dec *Decoder) decode(val reflect.Value, nullOK bool) (_err *DecodeError) { } val.SetFloat(n) case reflect.String: - if nullOK && dec.peekRuneType() == jsonparse.RuneTypeNullN { - return dec.decodeNull() + if ok, err := dec.maybeDecodeNull(nullOK); ok { + return err } var buf strings.Builder if typ == numberType { @@ -559,8 +559,8 @@ func (dec *Decoder) decode(val reflect.Value, nullOK bool) (_err *DecodeError) { val.Set(reflect.ValueOf(v)) } case reflect.Struct: - if nullOK && dec.peekRuneType() == jsonparse.RuneTypeNullN { - return dec.decodeNull() + if ok, err := dec.maybeDecodeNull(nullOK); ok { + return err } index := jsonstruct.IndexStruct(typ) var nameBuf strings.Builder @@ -780,8 +780,8 @@ func (dec *Decoder) decode(val reflect.Value, nullOK bool) (_err *DecodeError) { } } case reflect.Array: - if nullOK && dec.peekRuneType() == jsonparse.RuneTypeNullN { - return dec.decodeNull() + if ok, err := dec.maybeDecodeNull(nullOK); ok { + return err } i := 0 n := val.Len() @@ -1212,3 +1212,13 @@ func (dec *Decoder) decodeNull() *DecodeError { dec.expectRune('l', jsonparse.RuneTypeNullL2) return nil } + +func (dec *Decoder) maybeDecodeNull(nullOK bool) (ok bool, err *DecodeError) { + if nullOK { + t := dec.peekRuneType() + if t == jsonparse.RuneTypeNullN { + return true, dec.decodeNull() + } + } + return false, nil +} -- cgit v1.2.3-2-g168b From aec0feb925614b0f878afa566b912d102ed9ccca Mon Sep 17 00:00:00 2001 From: Luke Shumaker Date: Fri, 10 Feb 2023 19:02:38 -0700 Subject: decode: Have .peekRuneType() return a *DecodeError --- decode.go | 104 ++++++++++++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 81 insertions(+), 23 deletions(-) (limited to 'decode.go') diff --git a/decode.go b/decode.go index 73d15c5..15ab766 100644 --- a/decode.go +++ b/decode.go @@ -289,10 +289,11 @@ func (dec *Decoder) unreadRune() { } } -func (dec *Decoder) peekRuneType() jsonparse.RuneType { +//nolint:unparam // It will start returning errors soon. +func (dec *Decoder) peekRuneType() (jsonparse.RuneType, *DecodeError) { _, t := dec.readRune() dec.unreadRune() - return t + return t, nil } func (dec *Decoder) expectRune(ec rune, et jsonparse.RuneType) { @@ -396,7 +397,10 @@ func (dec *Decoder) decode(val reflect.Value, nullOK bool) (_err *DecodeError) { typ := val.Type() switch { case val.CanAddr() && reflect.PointerTo(typ) == rawMessagePtrType: - t := dec.peekRuneType() + t, err := dec.peekRuneType() + if err != nil { + return err + } var buf bytes.Buffer if err := dec.scan(&buf); err != nil { return err @@ -405,7 +409,10 @@ func (dec *Decoder) decode(val reflect.Value, nullOK bool) (_err *DecodeError) { return dec.newTypeError(t.JSONType(), reflect.PointerTo(typ), err) } case val.CanAddr() && reflect.PointerTo(typ).Implements(decodableType): - t := dec.peekRuneType() + t, err := dec.peekRuneType() + if err != nil { + return err + } obj := val.Addr().Interface().(Decodable) return dec.withLimitingScanner(func(l io.RuneScanner) *DecodeError { if err := obj.DecodeJSON(l); err != nil { @@ -417,7 +424,10 @@ func (dec *Decoder) decode(val reflect.Value, nullOK bool) (_err *DecodeError) { return nil }) case val.CanAddr() && reflect.PointerTo(typ).Implements(jsonUnmarshalerType): - t := dec.peekRuneType() + t, err := dec.peekRuneType() + if err != nil { + return err + } var buf bytes.Buffer if err := dec.scan(&buf); err != nil { return err @@ -494,7 +504,10 @@ func (dec *Decoder) decode(val reflect.Value, nullOK bool) (_err *DecodeError) { } var buf strings.Builder if typ == numberType { - t := dec.peekRuneType() + t, err := dec.peekRuneType() + if err != nil { + return err + } if err := dec.scan(&buf); err != nil { return err } @@ -511,8 +524,12 @@ func (dec *Decoder) decode(val reflect.Value, nullOK bool) (_err *DecodeError) { val.SetString(buf.String()) } case reflect.Interface: + t, err := dec.peekRuneType() + if err != nil { + return err + } if typ.NumMethod() > 0 { - return dec.newTypeError(dec.peekRuneType().JSONType(), typ, ErrDecodeNonEmptyInterface) + return dec.newTypeError(t.JSONType(), typ, ErrDecodeNonEmptyInterface) } // If the interface stores a pointer, try to use the type information of the pointer. if !val.IsNil() && val.Elem().Kind() == reflect.Pointer { @@ -533,11 +550,11 @@ func (dec *Decoder) decode(val reflect.Value, nullOK bool) (_err *DecodeError) { // in the loop) because the only way it's possible is if there's // an interface in there, which'd break from the loop on its own. // - // ptr.CanSet() || dec.peekRuneType() != jsonparse.RuneTypeNullN + // ptr.CanSet() || t != jsonparse.RuneTypeNullN // // We only need the pointer itself to be settable if we're // decoding null. - if ptr.Elem() != val && (ptr.CanSet() || dec.peekRuneType() != jsonparse.RuneTypeNullN) { + if ptr.Elem() != val && (ptr.CanSet() || t != jsonparse.RuneTypeNullN) { if err := dec.decode(ptr, false); err != nil { return err } @@ -545,7 +562,7 @@ func (dec *Decoder) decode(val reflect.Value, nullOK bool) (_err *DecodeError) { } } // Couldn't get type information from a pointer; fall back to untyped mode. - switch dec.peekRuneType() { + switch t { case jsonparse.RuneTypeNullN: if err := dec.decodeNull(); err != nil { return err @@ -600,7 +617,11 @@ func (dec *Decoder) decode(val reflect.Value, nullOK bool) (_err *DecodeError) { fmt.Errorf("json: cannot set embedded pointer to unexported struct: %v", fVal.Type().Elem())) } - if dec.peekRuneType() != jsonparse.RuneTypeNullN { + t, err := dec.peekRuneType() + if err != nil { + return err + } + if t != jsonparse.RuneTypeNullN { if fVal.IsNil() { fVal.Set(reflect.New(fVal.Type().Elem())) } @@ -610,7 +631,11 @@ func (dec *Decoder) decode(val reflect.Value, nullOK bool) (_err *DecodeError) { fVal = fVal.Field(idx) } if field.Quote { - switch t := dec.peekRuneType(); t { + t, err := dec.peekRuneType() + if err != nil { + return err + } + switch t { case jsonparse.RuneTypeNullN: if err := dec.decodeNull(); err != nil { return err @@ -647,7 +672,11 @@ func (dec *Decoder) decode(val reflect.Value, nullOK bool) (_err *DecodeError) { } }) case reflect.Map: - switch t := dec.peekRuneType(); t { + t, err := dec.peekRuneType() + if err != nil { + return err + } + switch t { case jsonparse.RuneTypeNullN: if err := dec.decodeNull(); err != nil { return err @@ -713,12 +742,16 @@ func (dec *Decoder) decode(val reflect.Value, nullOK bool) (_err *DecodeError) { return dec.newTypeError(t.JSONType(), typ, nil) } case reflect.Slice: + t, err := dec.peekRuneType() + if err != nil { + return err + } switch { - case typ.Elem().Kind() == reflect.Uint8 && !(dec.peekRuneType() == jsonparse.RuneTypeArrayBeg && (false || + case typ.Elem().Kind() == reflect.Uint8 && !(t == jsonparse.RuneTypeArrayBeg && (false || reflect.PointerTo(typ.Elem()).Implements(decodableType) || reflect.PointerTo(typ.Elem()).Implements(jsonUnmarshalerType) || reflect.PointerTo(typ.Elem()).Implements(textUnmarshalerType))): - switch t := dec.peekRuneType(); t { + switch t { case jsonparse.RuneTypeNullN: if err := dec.decodeNull(); err != nil { return err @@ -748,7 +781,7 @@ func (dec *Decoder) decode(val reflect.Value, nullOK bool) (_err *DecodeError) { return dec.newTypeError(t.JSONType(), typ, nil) } default: - switch t := dec.peekRuneType(); t { + switch t { case jsonparse.RuneTypeNullN: if err := dec.decodeNull(); err != nil { return err @@ -810,7 +843,11 @@ func (dec *Decoder) decode(val reflect.Value, nullOK bool) (_err *DecodeError) { val.Index(i).Set(reflect.Zero(typ.Elem())) } case reflect.Pointer: - switch dec.peekRuneType() { + t, err := dec.peekRuneType() + if err != nil { + return err + } + switch t { case jsonparse.RuneTypeNullN: if err := dec.decodeNull(); err != nil { return err @@ -843,7 +880,11 @@ func (dec *Decoder) scan(out fastio.RuneWriter) *DecodeError { } func (dec *Decoder) scanNumber(gTyp reflect.Type, out fastio.RuneWriter) *DecodeError { - if t := dec.peekRuneType(); !t.IsNumber() { + t, err := dec.peekRuneType() + if err != nil { + return err + } + if !t.IsNumber() { return dec.newTypeError(t.JSONType(), gTyp, nil) } return dec.scan(out) @@ -971,7 +1012,10 @@ func DecodeObject(r io.RuneScanner, decodeKey, decodeVal func(io.RuneScanner) er func() *DecodeError { dec.posStackPush() defer dec.posStackPop() - t := dec.peekRuneType() + t, err := dec.peekRuneType() + if err != nil { + return err + } return dec.withLimitingScanner(func(l io.RuneScanner) *DecodeError { if err := decodeVal(l); err != nil { // TODO: Find a better Go type to use than `nil`. @@ -1052,7 +1096,10 @@ func DecodeArray(r io.RuneScanner, decodeMember func(r io.RuneScanner) error) (e if err := dec.decodeArray(nil, func() *DecodeError { dec.posStackPush() defer dec.posStackPop() - t := dec.peekRuneType() + t, err := dec.peekRuneType() + if err != nil { + return err + } return dec.withLimitingScanner(func(l io.RuneScanner) *DecodeError { if err := decodeMember(l); err != nil { // TODO: Find a better Go type to use than `nil`. @@ -1144,12 +1191,20 @@ func (dec *Decoder) decodeString(gTyp reflect.Type, out fastio.RuneWriter) *Deco rune(uhex[3])<<0 handleUnicode: if utf16.IsSurrogate(c) { - if dec.peekRuneType() != jsonparse.RuneTypeStringEsc { + t, err := dec.peekRuneType() + if err != nil { + return err + } + if t != jsonparse.RuneTypeStringEsc { _, _ = out.WriteRune(utf8.RuneError) break } dec.expectRune('\\', jsonparse.RuneTypeStringEsc) - if dec.peekRuneType() != jsonparse.RuneTypeStringEscU { + t, err = dec.peekRuneType() + if err != nil { + return err + } + if t != jsonparse.RuneTypeStringEscU { _, _ = out.WriteRune(utf8.RuneError) break } @@ -1215,7 +1270,10 @@ func (dec *Decoder) decodeNull() *DecodeError { func (dec *Decoder) maybeDecodeNull(nullOK bool) (ok bool, err *DecodeError) { if nullOK { - t := dec.peekRuneType() + t, err := dec.peekRuneType() + if err != nil { + return true, err + } if t == jsonparse.RuneTypeNullN { return true, dec.decodeNull() } -- cgit v1.2.3-2-g168b From 7da5e8c664c7f4900ee74e8113e61a003ecbbe13 Mon Sep 17 00:00:00 2001 From: Luke Shumaker Date: Fri, 10 Feb 2023 19:07:57 -0700 Subject: decode: Have .readRune() and .expectRune() return *DecodeError --- decode.go | 147 +++++++++++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 111 insertions(+), 36 deletions(-) (limited to 'decode.go') diff --git a/decode.go b/decode.go index 15ab766..9ec706f 100644 --- a/decode.go +++ b/decode.go @@ -268,17 +268,17 @@ func (dec *Decoder) newTypeError(jTyp string, gTyp reflect.Type, err error) *Dec } } -func (dec *Decoder) readRune() (rune, jsonparse.RuneType) { +func (dec *Decoder) readRune() (rune, jsonparse.RuneType, *DecodeError) { c, _, t, e := dec.io.ReadRuneType() if e != nil { - panic(decodeError{ + return 0, 0, &DecodeError{ Field: dec.structStackStr(), FieldParent: dec.structStackParent(), FieldName: dec.structStackName(), Err: e, - }) + } } - return c, t + return c, t, nil } func (dec *Decoder) unreadRune() { @@ -289,22 +289,31 @@ func (dec *Decoder) unreadRune() { } } -//nolint:unparam // It will start returning errors soon. func (dec *Decoder) peekRuneType() (jsonparse.RuneType, *DecodeError) { - _, t := dec.readRune() + _, t, err := dec.readRune() + if err != nil { + return 0, err + } dec.unreadRune() return t, nil } -func (dec *Decoder) expectRune(ec rune, et jsonparse.RuneType) { - ac, at := dec.readRune() +func (dec *Decoder) expectRune(ec rune, et jsonparse.RuneType) *DecodeError { + ac, at, err := dec.readRune() + if err != nil { + return err + } if ac != ec || at != et { panic("should not happen") } + return nil } func (dec *Decoder) expectRuneType(ec rune, et jsonparse.RuneType, gt reflect.Type) *DecodeError { - ac, at := dec.readRune() + ac, at, err := dec.readRune() + if err != nil { + return err + } if ac != ec || at != et { return dec.newTypeError(at.JSONType(), gt, nil) } @@ -869,7 +878,10 @@ func (dec *Decoder) decode(val reflect.Value, nullOK bool) (_err *DecodeError) { func (dec *Decoder) scan(out fastio.RuneWriter) *DecodeError { dec.io.PushReadBarrier() for { - c, t := dec.readRune() + c, t, err := dec.readRune() + if err != nil { + return err + } if t == jsonparse.RuneTypeEOF { break } @@ -891,7 +903,10 @@ func (dec *Decoder) scanNumber(gTyp reflect.Type, out fastio.RuneWriter) *Decode } func (dec *Decoder) decodeAny() (any, *DecodeError) { - c, _ := dec.readRune() + c, _, err := dec.readRune() + if err != nil { + return nil, err + } dec.unreadRune() switch c { case '{': @@ -1037,7 +1052,10 @@ func (dec *Decoder) decodeObject(gTyp reflect.Type, decodeKey, decodeVal func() if err := dec.expectRuneType('{', jsonparse.RuneTypeObjectBeg, gTyp); err != nil { return err } - _, t := dec.readRune() + _, t, err := dec.readRune() + if err != nil { + return err + } switch t { case jsonparse.RuneTypeObjectEnd: return nil @@ -1047,14 +1065,21 @@ func (dec *Decoder) decodeObject(gTyp reflect.Type, decodeKey, decodeVal func() if err := decodeKey(); err != nil { return err } - dec.expectRune(':', jsonparse.RuneTypeObjectColon) + if err := dec.expectRune(':', jsonparse.RuneTypeObjectColon); err != nil { + return err + } if err := decodeVal(); err != nil { return err } - _, t := dec.readRune() + _, t, err := dec.readRune() + if err != nil { + return err + } switch t { case jsonparse.RuneTypeObjectComma: - dec.expectRune('"', jsonparse.RuneTypeStringBeg) + if err := dec.expectRune('"', jsonparse.RuneTypeStringBeg); err != nil { + return err + } goto decodeMember case jsonparse.RuneTypeObjectEnd: return nil @@ -1121,7 +1146,10 @@ func (dec *Decoder) decodeArray(gTyp reflect.Type, decodeMember func() *DecodeEr if err := dec.expectRuneType('[', jsonparse.RuneTypeArrayBeg, gTyp); err != nil { return err } - _, t := dec.readRune() + _, t, err := dec.readRune() + if err != nil { + return err + } switch t { case jsonparse.RuneTypeArrayEnd: return nil @@ -1131,7 +1159,10 @@ func (dec *Decoder) decodeArray(gTyp reflect.Type, decodeMember func() *DecodeEr if err := decodeMember(); err != nil { return err } - _, t := dec.readRune() + _, t, err := dec.readRune() + if err != nil { + return err + } switch t { case jsonparse.RuneTypeArrayComma: goto decodeNextMember @@ -1149,7 +1180,10 @@ func (dec *Decoder) decodeString(gTyp reflect.Type, out fastio.RuneWriter) *Deco } var uhex [4]byte for { - c, t := dec.readRune() + c, t, err := dec.readRune() + if err != nil { + return err + } switch t { case jsonparse.RuneTypeStringChar: _, _ = out.WriteRune(c) @@ -1199,7 +1233,9 @@ func (dec *Decoder) decodeString(gTyp reflect.Type, out fastio.RuneWriter) *Deco _, _ = out.WriteRune(utf8.RuneError) break } - dec.expectRune('\\', jsonparse.RuneTypeStringEsc) + if err := dec.expectRune('\\', jsonparse.RuneTypeStringEsc); err != nil { + return err + } t, err = dec.peekRuneType() if err != nil { return err @@ -1208,15 +1244,29 @@ func (dec *Decoder) decodeString(gTyp reflect.Type, out fastio.RuneWriter) *Deco _, _ = out.WriteRune(utf8.RuneError) break } - dec.expectRune('u', jsonparse.RuneTypeStringEscU) + if err := dec.expectRune('u', jsonparse.RuneTypeStringEscU); err != nil { + return err + } - b, _ := dec.readRune() + b, _, err := dec.readRune() + if err != nil { + return err + } uhex[0], _ = jsonparse.HexToInt(b) - b, _ = dec.readRune() + b, _, err = dec.readRune() + if err != nil { + return err + } uhex[1], _ = jsonparse.HexToInt(b) - b, _ = dec.readRune() + b, _, err = dec.readRune() + if err != nil { + return err + } uhex[2], _ = jsonparse.HexToInt(b) - b, _ = dec.readRune() + b, _, err = dec.readRune() + if err != nil { + return err + } uhex[3], _ = jsonparse.HexToInt(b) c2 := 0 | rune(uhex[0])<<12 | @@ -1242,18 +1292,35 @@ func (dec *Decoder) decodeString(gTyp reflect.Type, out fastio.RuneWriter) *Deco } func (dec *Decoder) decodeBool(gTyp reflect.Type) (bool, *DecodeError) { - c, t := dec.readRune() + c, t, err := dec.readRune() + if err != nil { + return false, err + } switch c { case 't': - dec.expectRune('r', jsonparse.RuneTypeTrueR) - dec.expectRune('u', jsonparse.RuneTypeTrueU) - dec.expectRune('e', jsonparse.RuneTypeTrueE) + if err := dec.expectRune('r', jsonparse.RuneTypeTrueR); err != nil { + return false, err + } + if err := dec.expectRune('u', jsonparse.RuneTypeTrueU); err != nil { + return false, err + } + if err := dec.expectRune('e', jsonparse.RuneTypeTrueE); err != nil { + return false, err + } return true, nil case 'f': - dec.expectRune('a', jsonparse.RuneTypeFalseA) - dec.expectRune('l', jsonparse.RuneTypeFalseL) - dec.expectRune('s', jsonparse.RuneTypeFalseS) - dec.expectRune('e', jsonparse.RuneTypeFalseE) + if err := dec.expectRune('a', jsonparse.RuneTypeFalseA); err != nil { + return false, err + } + if err := dec.expectRune('l', jsonparse.RuneTypeFalseL); err != nil { + return false, err + } + if err := dec.expectRune('s', jsonparse.RuneTypeFalseS); err != nil { + return false, err + } + if err := dec.expectRune('e', jsonparse.RuneTypeFalseE); err != nil { + return false, err + } return false, nil default: return false, dec.newTypeError(t.JSONType(), gTyp, nil) @@ -1261,10 +1328,18 @@ func (dec *Decoder) decodeBool(gTyp reflect.Type) (bool, *DecodeError) { } func (dec *Decoder) decodeNull() *DecodeError { - dec.expectRune('n', jsonparse.RuneTypeNullN) - dec.expectRune('u', jsonparse.RuneTypeNullU) - dec.expectRune('l', jsonparse.RuneTypeNullL1) - dec.expectRune('l', jsonparse.RuneTypeNullL2) + if err := dec.expectRune('n', jsonparse.RuneTypeNullN); err != nil { + return err + } + if err := dec.expectRune('u', jsonparse.RuneTypeNullU); err != nil { + return err + } + if err := dec.expectRune('l', jsonparse.RuneTypeNullL1); err != nil { + return err + } + if err := dec.expectRune('l', jsonparse.RuneTypeNullL2); err != nil { + return err + } return nil } -- cgit v1.2.3-2-g168b From d525a9ad920c6678f1e193d121be677936289667 Mon Sep 17 00:00:00 2001 From: Luke Shumaker Date: Fri, 10 Feb 2023 19:11:54 -0700 Subject: decode: Remove now-superfluous recover blocks --- decode.go | 38 +++----------------------------------- 1 file changed, 3 insertions(+), 35 deletions(-) (limited to 'decode.go') diff --git a/decode.go b/decode.go index 9ec706f..07ca792 100644 --- a/decode.go +++ b/decode.go @@ -252,8 +252,6 @@ func (dec *Decoder) Decode(ptr any) (err error) { // io helpers ////////////////////////////////////////////////////////////////////////////////////// -type decodeError DecodeError - func (dec *Decoder) newTypeError(jTyp string, gTyp reflect.Type, err error) *DecodeError { return &DecodeError{ Field: dec.structStackStr(), @@ -390,17 +388,7 @@ var kind2bits = map[reflect.Kind]int{ reflect.Float64: 64, } -func (dec *Decoder) decode(val reflect.Value, nullOK bool) (_err *DecodeError) { - defer func() { - if r := recover(); r != nil { - if de, ok := r.(decodeError); ok { - pub := DecodeError(de) - _err = &pub - } else { - panic(r) - } - } - }() +func (dec *Decoder) decode(val reflect.Value, nullOK bool) *DecodeError { dec.posStackPush() defer dec.posStackPop() typ := val.Type() @@ -989,17 +977,7 @@ func (dec *Decoder) decodeAny() (any, *DecodeError) { // Outside of implementing Decodable.DecodeJSON methods, callers // should instead simply use NewDecoder(r).Decode(&val) rather than // attempting to call DecodeObject directly. -func DecodeObject(r io.RuneScanner, decodeKey, decodeVal func(io.RuneScanner) error) (err error) { - defer func() { - if r := recover(); r != nil { - if de, ok := r.(decodeError); ok { - pub := DecodeError(de) - err = &pub - } else { - panic(r) - } - } - }() +func DecodeObject(r io.RuneScanner, decodeKey, decodeVal func(io.RuneScanner) error) error { var dec *Decoder if dr, ok := r.(*decRuneScanner); ok { dec = dr.dec @@ -1099,17 +1077,7 @@ func (dec *Decoder) decodeObject(gTyp reflect.Type, decodeKey, decodeVal func() // Outside of implementing Decodable.DecodeJSON methods, callers // should instead simply use NewDecoder(r).Decode(&val) rather than // attempting to call DecodeArray directly. -func DecodeArray(r io.RuneScanner, decodeMember func(r io.RuneScanner) error) (err error) { - defer func() { - if r := recover(); r != nil { - if de, ok := r.(decodeError); ok { - pub := DecodeError(de) - err = &pub - } else { - panic(r) - } - } - }() +func DecodeArray(r io.RuneScanner, decodeMember func(r io.RuneScanner) error) error { var dec *Decoder if dr, ok := r.(*decRuneScanner); ok { dec = dr.dec -- cgit v1.2.3-2-g168b From dadafd9cfabbea5555c404b339bbf44252ee7e6b Mon Sep 17 00:00:00 2001 From: Luke Shumaker Date: Fri, 10 Feb 2023 20:48:21 -0700 Subject: decode: decodeAny: Use rune types rather that char literals --- decode.go | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) (limited to 'decode.go') diff --git a/decode.go b/decode.go index 07ca792..976cc6a 100644 --- a/decode.go +++ b/decode.go @@ -891,13 +891,12 @@ func (dec *Decoder) scanNumber(gTyp reflect.Type, out fastio.RuneWriter) *Decode } func (dec *Decoder) decodeAny() (any, *DecodeError) { - c, _, err := dec.readRune() + t, err := dec.peekRuneType() if err != nil { return nil, err } - dec.unreadRune() - switch c { - case '{': + switch t { + case jsonparse.RuneTypeObjectBeg: ret := make(map[string]any) typ := reflect.TypeOf(ret) var nameBuf strings.Builder @@ -922,7 +921,7 @@ func (dec *Decoder) decodeAny() (any, *DecodeError) { return nil, err } return ret, nil - case '[': + case jsonparse.RuneTypeArrayBeg: ret := []any{} typ := reflect.TypeOf(ret) if err := dec.decodeArray(typ, func() *DecodeError { @@ -940,13 +939,13 @@ func (dec *Decoder) decodeAny() (any, *DecodeError) { return nil, err } return ret, nil - case '"': + case jsonparse.RuneTypeStringBeg: var buf strings.Builder if err := dec.decodeString(nil, &buf); err != nil { return nil, err } return buf.String(), nil - case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9': + case jsonparse.RuneTypeNumberIntNeg, jsonparse.RuneTypeNumberIntZero, jsonparse.RuneTypeNumberIntDig: var buf strings.Builder if err := dec.scan(&buf); err != nil { return nil, err @@ -960,9 +959,9 @@ func (dec *Decoder) decodeAny() (any, *DecodeError) { return nil, dec.newTypeError("number "+buf.String(), float64Type, err) } return f64, nil - case 't', 'f': + case jsonparse.RuneTypeTrueT, jsonparse.RuneTypeFalseF: return dec.decodeBool(nil) - case 'n': + case jsonparse.RuneTypeNullN: return nil, dec.decodeNull() default: panic("should not happen") -- cgit v1.2.3-2-g168b