summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLuke Shumaker <lukeshu@lukeshu.com>2023-02-23 19:07:17 -0700
committerLuke Shumaker <lukeshu@lukeshu.com>2023-02-23 19:07:17 -0700
commitb00178cc98f3e215d841a0f42db21461d8363012 (patch)
tree0949ad0345a4cd3e7370c3372036885f547578f0
parentd8a66ffc3907f1fa6d67dcc65f2d688c8b27b71c (diff)
decode: withLimitingScanner: Reduce boilerplate
-rw-r--r--decode.go75
1 files changed, 18 insertions, 57 deletions
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
}