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(-) 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