From 8b7c8d2f87f9c4d924d070926fb5ab9860d00c61 Mon Sep 17 00:00:00 2001 From: Luke Shumaker Date: Mon, 30 Jan 2023 14:29:27 -0700 Subject: decode: s/stack/structStack/ This should make the next commit less noisy. --- decode.go | 74 +++++++++++++++++++++++++++++++-------------------------------- 1 file changed, 37 insertions(+), 37 deletions(-) (limited to 'decode.go') diff --git a/decode.go b/decode.go index f351037..3c51c4b 100644 --- a/decode.go +++ b/decode.go @@ -90,8 +90,8 @@ type Decoder struct { useNumber bool // state - err error - stack []decodeStackItem + err error + structStack []decodeStackItem } const maxNestingDepth = 10000 @@ -150,40 +150,40 @@ func (dec *Decoder) More() bool { return e == nil && t != internal.RuneTypeEOF } -func (dec *Decoder) stackPush(par reflect.Type, idx any) { - dec.stack = append(dec.stack, decodeStackItem{par, idx}) +func (dec *Decoder) structStackPush(par reflect.Type, idx any) { + dec.structStack = append(dec.structStack, decodeStackItem{par, idx}) } -func (dec *Decoder) stackPop() { - dec.stack = dec.stack[:len(dec.stack)-1] +func (dec *Decoder) structStackPop() { + dec.structStack = dec.structStack[:len(dec.structStack)-1] } -func (dec *Decoder) stackStr() string { +func (dec *Decoder) structStackStr() string { var buf strings.Builder buf.WriteString("v") - for _, item := range dec.stack { + for _, item := range dec.structStack { fmt.Fprintf(&buf, "[%#v]", item.idx) } return buf.String() } -func (dec *Decoder) stackParent() string { - last := len(dec.stack) - 1 - if last > 0 && dec.stack[last].par.Kind() != reflect.Struct && dec.stack[last-1].par.Kind() == reflect.Struct { +func (dec *Decoder) structStackParent() string { + last := len(dec.structStack) - 1 + if last > 0 && dec.structStack[last].par.Kind() != reflect.Struct && dec.structStack[last-1].par.Kind() == reflect.Struct { last-- } - if last >= 0 && dec.stack[last].par.Kind() == reflect.Struct { - return dec.stack[last].par.Name() + if last >= 0 && dec.structStack[last].par.Kind() == reflect.Struct { + return dec.structStack[last].par.Name() } return "" } -func (dec *Decoder) stackName() string { - if dec.stackParent() == "" { +func (dec *Decoder) structStackName() string { + if dec.structStackParent() == "" { return "" } var fields []string - for _, elem := range dec.stack { + for _, elem := range dec.structStack { if elem.par.Kind() == reflect.Struct { fields = append(fields, elem.idx.(string)) } @@ -259,9 +259,9 @@ type decodeError DecodeError func (dec *Decoder) panicType(jTyp string, gTyp reflect.Type, err error) { panic(decodeError{ - Field: dec.stackStr(), - FieldParent: dec.stackParent(), - FieldName: dec.stackName(), + Field: dec.structStackStr(), + FieldParent: dec.structStackParent(), + FieldName: dec.structStackName(), Err: &DecodeTypeError{ GoType: gTyp, JSONType: jTyp, @@ -275,9 +275,9 @@ func (dec *Decoder) readRune() (rune, internal.RuneType) { c, _, t, e := dec.io.ReadRuneType() if e != nil { panic(decodeError{ - Field: dec.stackStr(), - FieldParent: dec.stackParent(), - FieldName: dec.stackName(), + Field: dec.structStackStr(), + FieldParent: dec.structStackParent(), + FieldName: dec.structStackName(), Err: e, }) } @@ -320,9 +320,9 @@ func (sc *decRuneTypeScanner) ReadRuneType() (rune, int, internal.RuneType, erro c, s, t, e := sc.dec.io.ReadRuneType() if e != nil { panic(decodeError{ - Field: sc.dec.stackStr(), - FieldParent: sc.dec.stackParent(), - FieldName: sc.dec.stackName(), + Field: sc.dec.structStackStr(), + FieldParent: sc.dec.structStackParent(), + FieldName: sc.dec.structStackName(), Err: e, }) } @@ -534,8 +534,8 @@ func (dec *Decoder) decode(val reflect.Value, nullOK bool) { dec.decodeString(nil, &nameBuf) }, func() { name := nameBuf.String() - dec.stackPush(typ, name) - defer dec.stackPop() + dec.structStackPush(typ, name) + defer dec.structStackPop() idx, ok := index.byName[name] if !ok { for oidx := range index.byPos { @@ -645,8 +645,8 @@ func (dec *Decoder) decode(val reflect.Value, nullOK bool) { dec.panicType("object", typ, &DecodeArgumentError{Type: nameValTyp}) } } - dec.stackPush(typ, nameValPtr.Elem()) - defer dec.stackPop() + dec.structStackPush(typ, nameValPtr.Elem()) + defer dec.structStackPop() fValPtr := reflect.New(typ.Elem()) dec.decode(fValPtr.Elem(), false) @@ -699,8 +699,8 @@ func (dec *Decoder) decode(val reflect.Value, nullOK bool) { } i := 0 dec.decodeArray(typ, func() { - dec.stackPush(typ, i) - defer dec.stackPop() + dec.structStackPush(typ, i) + defer dec.structStackPop() mValPtr := reflect.New(typ.Elem()) dec.decode(mValPtr.Elem(), false) val.Set(reflect.Append(val, mValPtr.Elem())) @@ -718,8 +718,8 @@ func (dec *Decoder) decode(val reflect.Value, nullOK bool) { i := 0 n := val.Len() dec.decodeArray(typ, func() { - dec.stackPush(typ, i) - defer dec.stackPop() + dec.structStackPush(typ, i) + defer dec.structStackPop() if i < n { mValPtr := reflect.New(typ.Elem()) dec.decode(mValPtr.Elem(), false) @@ -780,8 +780,8 @@ func (dec *Decoder) decodeAny() any { dec.decodeString(nil, &nameBuf) }, func() { name := nameBuf.String() - dec.stackPush(typ, name) - defer dec.stackPop() + dec.structStackPush(typ, name) + defer dec.structStackPop() ret[name] = dec.decodeAny() }) return ret @@ -789,8 +789,8 @@ func (dec *Decoder) decodeAny() any { ret := []any{} typ := reflect.TypeOf(ret) dec.decodeArray(typ, func() { - dec.stackPush(typ, len(ret)) - defer dec.stackPop() + dec.structStackPush(typ, len(ret)) + defer dec.structStackPop() ret = append(ret, dec.decodeAny()) }) return ret -- cgit v1.2.3-2-g168b From c24b34a47359ffb012b85e329f829b64d9d27215 Mon Sep 17 00:00:00 2001 From: Luke Shumaker Date: Mon, 30 Jan 2023 12:31:42 -0700 Subject: decode: Fix DecodeTypeError offsets --- decode.go | 56 ++++++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 48 insertions(+), 8 deletions(-) (limited to 'decode.go') 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 { -- cgit v1.2.3-2-g168b From 75a59f2b56982bc753d594a5af375b23ef786fdf Mon Sep 17 00:00:00 2001 From: Luke Shumaker Date: Mon, 30 Jan 2023 16:54:15 -0700 Subject: decode: Tidy up DecodeObject and DecodeArray --- decode.go | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'decode.go') diff --git a/decode.go b/decode.go index a7536f5..7ae723c 100644 --- a/decode.go +++ b/decode.go @@ -878,9 +878,11 @@ func DecodeObject(r io.RuneScanner, decodeKey, decodeVal func(io.RuneScanner) er 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")) } }, @@ -890,13 +892,15 @@ func DecodeObject(r io.RuneScanner, decodeKey, decodeVal func(io.RuneScanner) er 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 err + return nil } func (dec *Decoder) decodeObject(gTyp reflect.Type, decodeKey, decodeVal func()) { @@ -954,13 +958,15 @@ func DecodeArray(r io.RuneScanner, decodeMember func(r io.RuneScanner) error) (e 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 + return nil } func (dec *Decoder) decodeArray(gTyp reflect.Type, decodeMember func()) { -- cgit v1.2.3-2-g168b