summaryrefslogtreecommitdiff
path: root/decode.go
diff options
context:
space:
mode:
authorLuke Shumaker <lukeshu@lukeshu.com>2023-01-30 12:31:42 -0700
committerLuke Shumaker <lukeshu@lukeshu.com>2023-01-30 14:41:30 -0700
commitc24b34a47359ffb012b85e329f829b64d9d27215 (patch)
tree0a7acb802d5c9e3cf3ccde658b07f1034f680f52 /decode.go
parent8b7c8d2f87f9c4d924d070926fb5ab9860d00c61 (diff)
decode: Fix DecodeTypeError offsets
Diffstat (limited to 'decode.go')
-rw-r--r--decode.go56
1 files changed, 48 insertions, 8 deletions
diff --git a/decode.go b/decode.go
index 3c51c4b..a7536f5 100644
--- a/decode.go
+++ b/decode.go
@@ -91,6 +91,7 @@ type Decoder struct {
// state
err error
+ posStack []int64
structStack []decodeStackItem
}
@@ -150,6 +151,14 @@ func (dec *Decoder) More() bool {
return e == nil && t != internal.RuneTypeEOF
}
+func (dec *Decoder) posStackPush() {
+ dec.posStack = append(dec.posStack, dec.InputOffset())
+}
+
+func (dec *Decoder) posStackPop() {
+ dec.posStack = dec.posStack[:len(dec.posStack)-1]
+}
+
func (dec *Decoder) structStackPush(par reflect.Type, idx any) {
dec.structStack = append(dec.structStack, decodeStackItem{par, idx})
}
@@ -266,7 +275,7 @@ func (dec *Decoder) panicType(jTyp string, gTyp reflect.Type, err error) {
GoType: gTyp,
JSONType: jTyp,
Err: err,
- Offset: dec.InputOffset(),
+ Offset: dec.posStack[len(dec.posStack)-1],
},
})
}
@@ -381,6 +390,8 @@ var kind2bits = map[reflect.Kind]int{
}
func (dec *Decoder) decode(val reflect.Value, nullOK bool) {
+ dec.posStackPush()
+ defer dec.posStackPop()
typ := val.Type()
switch {
case val.CanAddr() && reflect.PointerTo(typ) == rawMessagePtrType:
@@ -388,17 +399,17 @@ func (dec *Decoder) decode(val reflect.Value, nullOK bool) {
var buf bytes.Buffer
dec.scan(&buf)
if err := val.Addr().Interface().(*json.RawMessage).UnmarshalJSON(buf.Bytes()); err != nil {
- dec.panicType(t.JSONType(), typ, err)
+ dec.panicType(t.JSONType(), reflect.PointerTo(typ), err)
}
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(), typ, err)
+ dec.panicType(t.JSONType(), reflect.PointerTo(typ), err)
}
if _, _, err := l.ReadRune(); err != io.EOF {
- dec.panicType(t.JSONType(), typ, fmt.Errorf("did not consume entire %s", t.JSONType()))
+ dec.panicType(t.JSONType(), reflect.PointerTo(typ), fmt.Errorf("did not consume entire %s", t.JSONType()))
}
case val.CanAddr() && reflect.PointerTo(typ).Implements(jsonUnmarshalerType):
t := dec.peekRuneType()
@@ -406,7 +417,7 @@ func (dec *Decoder) decode(val reflect.Value, nullOK bool) {
dec.scan(&buf)
obj := val.Addr().Interface().(json.Unmarshaler)
if err := obj.UnmarshalJSON(buf.Bytes()); err != nil {
- dec.panicType(t.JSONType(), typ, err)
+ dec.panicType(t.JSONType(), reflect.PointerTo(typ), err)
}
case val.CanAddr() && reflect.PointerTo(typ).Implements(textUnmarshalerType):
if nullOK && dec.peekRuneType() == internal.RuneTypeNullN {
@@ -530,9 +541,13 @@ func (dec *Decoder) decode(val reflect.Value, nullOK bool) {
index := indexStruct(typ)
var nameBuf strings.Builder
dec.decodeObject(typ, func() {
+ dec.posStackPush()
+ defer dec.posStackPop()
nameBuf.Reset()
dec.decodeString(nil, &nameBuf)
}, func() {
+ dec.posStackPush()
+ defer dec.posStackPop()
name := nameBuf.String()
dec.structStackPush(typ, name)
defer dec.structStackPop()
@@ -613,17 +628,19 @@ func (dec *Decoder) decode(val reflect.Value, nullOK bool) {
val.Set(reflect.MakeMap(typ))
}
var nameBuf bytes.Buffer
+ var nameValPtr reflect.Value
dec.decodeObject(typ, func() {
+ dec.posStackPush()
+ defer dec.posStackPop()
nameBuf.Reset()
dec.decodeString(nil, &nameBuf)
- }, func() {
nameValTyp := typ.Key()
- nameValPtr := reflect.New(nameValTyp)
+ nameValPtr = reflect.New(nameValTyp)
switch {
case reflect.PointerTo(nameValTyp).Implements(textUnmarshalerType):
obj := nameValPtr.Interface().(encoding.TextUnmarshaler)
if err := obj.UnmarshalText(nameBuf.Bytes()); err != nil {
- dec.panicType("string", nameValTyp, err)
+ dec.panicType("string", reflect.PointerTo(nameValTyp), err)
}
default:
switch nameValTyp.Kind() {
@@ -645,6 +662,9 @@ func (dec *Decoder) decode(val reflect.Value, nullOK bool) {
dec.panicType("object", typ, &DecodeArgumentError{Type: nameValTyp})
}
}
+ }, func() {
+ dec.posStackPush()
+ defer dec.posStackPop()
dec.structStackPush(typ, nameValPtr.Elem())
defer dec.structStackPop()
@@ -699,6 +719,8 @@ func (dec *Decoder) decode(val reflect.Value, nullOK bool) {
}
i := 0
dec.decodeArray(typ, func() {
+ dec.posStackPush()
+ defer dec.posStackPop()
dec.structStackPush(typ, i)
defer dec.structStackPop()
mValPtr := reflect.New(typ.Elem())
@@ -718,6 +740,8 @@ func (dec *Decoder) decode(val reflect.Value, nullOK bool) {
i := 0
n := val.Len()
dec.decodeArray(typ, func() {
+ dec.posStackPush()
+ defer dec.posStackPop()
dec.structStackPush(typ, i)
defer dec.structStackPop()
if i < n {
@@ -776,9 +800,13 @@ func (dec *Decoder) decodeAny() any {
typ := reflect.TypeOf(ret)
var nameBuf strings.Builder
dec.decodeObject(typ, func() {
+ dec.posStackPush()
+ defer dec.posStackPop()
nameBuf.Reset()
dec.decodeString(nil, &nameBuf)
}, func() {
+ dec.posStackPush()
+ defer dec.posStackPop()
name := nameBuf.String()
dec.structStackPush(typ, name)
defer dec.structStackPop()
@@ -789,6 +817,8 @@ func (dec *Decoder) decodeAny() any {
ret := []any{}
typ := reflect.TypeOf(ret)
dec.decodeArray(typ, func() {
+ dec.posStackPush()
+ defer dec.posStackPop()
dec.structStackPush(typ, len(ret))
defer dec.structStackPop()
ret = append(ret, dec.decodeAny())
@@ -840,8 +870,12 @@ func DecodeObject(r io.RuneScanner, decodeKey, decodeVal func(io.RuneScanner) er
}
}()
dec := NewDecoder(r)
+ dec.posStackPush()
+ defer dec.posStackPop()
dec.decodeObject(nil,
func() {
+ dec.posStackPush()
+ defer dec.posStackPop()
l := dec.limitingScanner()
if err := decodeKey(l); err != nil {
dec.panicType("string", nil, err)
@@ -851,6 +885,8 @@ func DecodeObject(r io.RuneScanner, decodeKey, decodeVal func(io.RuneScanner) er
}
},
func() {
+ dec.posStackPush()
+ defer dec.posStackPop()
t := dec.peekRuneType()
l := dec.limitingScanner()
if err := decodeVal(l); err != nil {
@@ -910,7 +946,11 @@ func DecodeArray(r io.RuneScanner, decodeMember func(r io.RuneScanner) error) (e
}
}()
dec := NewDecoder(r)
+ dec.posStackPush()
+ defer dec.posStackPop()
dec.decodeArray(nil, func() {
+ dec.posStackPush()
+ defer dec.posStackPop()
t := dec.peekRuneType()
l := dec.limitingScanner()
if err := decodeMember(l); err != nil {