From b00178cc98f3e215d841a0f42db21461d8363012 Mon Sep 17 00:00:00 2001 From: Luke Shumaker Date: Thu, 23 Feb 2023 19:07:17 -0700 Subject: decode: withLimitingScanner: Reduce boilerplate --- decode.go | 75 +++++++++++++++------------------------------------------------ 1 file changed, 18 insertions(+), 57 deletions(-) (limited to 'decode.go') diff --git a/decode.go b/decode.go index 10b3685..8c26a80 100644 --- a/decode.go +++ b/decode.go @@ -356,7 +356,11 @@ func (sc *decRuneScanner) UnreadRune() error { return sc.dec.io.UnreadRune() } -func (dec *Decoder) withLimitingScanner(fn func(io.RuneScanner) *DecodeError) (err *DecodeError) { +func (dec *Decoder) withLimitingScanner(gTyp reflect.Type, fn func(io.RuneScanner) error) (err *DecodeError) { + t, err := dec.peekRuneType() + if err != nil { + return err + } dec.io.PushReadBarrier() defer func() { if r := recover(); r != nil { @@ -367,8 +371,12 @@ func (dec *Decoder) withLimitingScanner(fn func(io.RuneScanner) *DecodeError) (e } } }() - if err := fn(&decRuneScanner{dec: dec}); err != nil { - return err + l := &decRuneScanner{dec: dec} + if err := fn(l); err != nil { + return dec.newTypeError(t.JSONType(), gTyp, err) + } + if _, _, err := l.ReadRune(); err != io.EOF { + return dec.newTypeError(t.JSONType(), gTyp, fmt.Errorf("did not consume entire %s", t.JSONType())) } return nil } @@ -412,20 +420,8 @@ func (dec *Decoder) decode(val reflect.Value, nullOK bool) *DecodeError { return dec.newTypeError(t.JSONType(), reflect.PointerTo(typ), err) } case val.CanAddr() && reflect.PointerTo(typ).Implements(decodableType): - 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 { - return dec.newTypeError(t.JSONType(), reflect.PointerTo(typ), err) - } - if _, _, err := l.ReadRune(); err != io.EOF { - return dec.newTypeError(t.JSONType(), reflect.PointerTo(typ), fmt.Errorf("did not consume entire %s", t.JSONType())) - } - return nil - }) + return dec.withLimitingScanner(reflect.PointerTo(typ), obj.DecodeJSON) case val.CanAddr() && reflect.PointerTo(typ).Implements(jsonUnmarshalerType): t, err := dec.peekRuneType() if err != nil { @@ -995,36 +991,14 @@ func DecodeObject(r io.RuneScanner, decodeKey, decodeVal func(io.RuneScanner) er func() *DecodeError { dec.posStackPush() defer dec.posStackPop() - return dec.withLimitingScanner(func(l io.RuneScanner) *DecodeError { - if err := decodeKey(l); err != nil { - // TODO: Find a better Go type to use than `nil`. - return dec.newTypeError("string", nil, err) - } - if _, _, err := l.ReadRune(); err != io.EOF { - // TODO: Find a better Go type to use than `nil`. - return dec.newTypeError("string", nil, fmt.Errorf("did not consume entire string")) - } - return nil - }) + // TODO: Find a better Go type to use than `nil`. + return dec.withLimitingScanner(nil, decodeKey) }, func() *DecodeError { dec.posStackPush() defer dec.posStackPop() - 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`. - return dec.newTypeError(t.JSONType(), nil, err) - } - if _, _, err := l.ReadRune(); err != io.EOF { - // TODO: Find a better Go type to use than `nil`. - return dec.newTypeError(t.JSONType(), nil, fmt.Errorf("did not consume entire %s", t.JSONType())) - } - return nil - }) + // TODO: Find a better Go type to use than `nil`. + return dec.withLimitingScanner(nil, decodeVal) }); err != nil { return err } @@ -1094,21 +1068,8 @@ func DecodeArray(r io.RuneScanner, decodeMember func(r io.RuneScanner) error) er if err := dec.decodeArray(nil, func() *DecodeError { dec.posStackPush() defer dec.posStackPop() - 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`. - return dec.newTypeError(t.JSONType(), nil, err) - } - if _, _, err := l.ReadRune(); err != io.EOF { - // TODO: Find a better Go type to use than `nil`. - return dec.newTypeError(t.JSONType(), nil, fmt.Errorf("did not consume entire %s", t.JSONType())) - } - return nil - }) + // TODO: Find a better Go type to use than `nil`. + return dec.withLimitingScanner(nil, decodeMember) }); err != nil { return err } -- cgit v1.2.3-2-g168b