summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLuke Shumaker <lukeshu@lukeshu.com>2023-02-10 18:31:41 -0700
committerLuke Shumaker <lukeshu@lukeshu.com>2023-02-10 21:49:02 -0700
commitd287a39cb902713ab0e5dff2f300c4e161ceb3d7 (patch)
treedb973fde261b9639a59aeb4d1c31ab5146d2d15e
parent0a1e3f5174191d78513fbcc5fb5bf7fa93032469 (diff)
decode: Replace .panicType() with .newTypeError()
-rw-r--r--decode.go74
1 files changed, 38 insertions, 36 deletions
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))
}
}