"bytes"
"encoding"
"encoding/base64"
- "errors"
"fmt"
"reflect"
"strconv"
return d.off - 1
}
-// errPhase is used for errors that should not happen unless
-// there is a bug in the JSON decoder or something is editing
-// the data slice while the decoder executes.
-var errPhase = errors.New("JSON decoder out of sync - data changing underfoot?")
+// phasePanicMsg is used as a panic message when we end up with something that
+// shouldn't happen. It can indicate a bug in the JSON decoder, or that
+// something is editing the data slice while the decoder executes.
+const phasePanicMsg = "JSON decoder out of sync - data changing underfoot?"
func (d *decodeState) init(data []byte) *decodeState {
d.data = data
func (d *decodeState) value(v reflect.Value) error {
switch d.opcode {
default:
- return errPhase
+ panic(phasePanicMsg)
case scanBeginArray:
if v.IsValid() {
// quoted string literal or literal null into an interface value.
// If it finds anything other than a quoted string literal or null,
// valueQuoted returns unquotedValue{}.
-func (d *decodeState) valueQuoted() (interface{}, error) {
+func (d *decodeState) valueQuoted() interface{} {
switch d.opcode {
default:
- return nil, errPhase
+ panic(phasePanicMsg)
case scanBeginArray, scanBeginObject:
d.skip()
d.scanNext()
case scanBeginLiteral:
- v, err := d.literalInterface()
- if err != nil {
- return nil, err
- }
+ v := d.literalInterface()
switch v.(type) {
case nil, string:
- return v, nil
+ return v
}
}
- return unquotedValue{}, nil
+ return unquotedValue{}
}
// indirect walks down v allocating pointers as needed,
case reflect.Interface:
if v.NumMethod() == 0 {
// Decoding into nil interface? Switch to non-reflect code.
- ai, err := d.arrayInterface()
- if err != nil {
- return err
- }
+ ai := d.arrayInterface()
v.Set(reflect.ValueOf(ai))
return nil
}
break
}
if d.opcode != scanArrayValue {
- return errPhase
+ panic(phasePanicMsg)
}
}
// Decoding into nil interface? Switch to non-reflect code.
if v.Kind() == reflect.Interface && v.NumMethod() == 0 {
- oi, err := d.objectInterface()
- if err != nil {
- return err
- }
+ oi := d.objectInterface()
v.Set(reflect.ValueOf(oi))
return nil
}
break
}
if d.opcode != scanBeginLiteral {
- return errPhase
+ panic(phasePanicMsg)
}
// Read key.
item := d.data[start:d.readIndex()]
key, ok := unquoteBytes(item)
if !ok {
- return errPhase
+ panic(phasePanicMsg)
}
// Figure out field corresponding to key.
d.scanWhile(scanSkipSpace)
}
if d.opcode != scanObjectKey {
- return errPhase
+ panic(phasePanicMsg)
}
d.scanWhile(scanSkipSpace)
if destring {
- q, err := d.valueQuoted()
- if err != nil {
- return err
- }
- switch qv := q.(type) {
+ switch qv := d.valueQuoted().(type) {
case nil:
if err := d.literalStore(nullLiteral, subv, false); err != nil {
return err
break
}
if d.opcode != scanObjectValue {
- return errPhase
+ panic(phasePanicMsg)
}
d.errorContext = originalErrorContext
if fromQuoted {
return fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type())
}
- return errPhase
+ panic(phasePanicMsg)
}
return ut.UnmarshalText(s)
}
if fromQuoted {
return fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type())
}
- return errPhase
+ panic(phasePanicMsg)
}
switch v.Kind() {
default:
if fromQuoted {
return fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type())
}
- return errPhase
+ panic(phasePanicMsg)
}
s := string(item)
switch v.Kind() {
// but they avoid the weight of reflection in this common case.
// valueInterface is like value but returns interface{}
-func (d *decodeState) valueInterface() (val interface{}, err error) {
+func (d *decodeState) valueInterface() (val interface{}) {
switch d.opcode {
default:
- err = errPhase
+ panic(phasePanicMsg)
case scanBeginArray:
- val, err = d.arrayInterface()
+ val = d.arrayInterface()
d.scanNext()
case scanBeginObject:
- val, err = d.objectInterface()
+ val = d.objectInterface()
d.scanNext()
case scanBeginLiteral:
- val, err = d.literalInterface()
+ val = d.literalInterface()
}
return
}
// arrayInterface is like array but returns []interface{}.
-func (d *decodeState) arrayInterface() ([]interface{}, error) {
+func (d *decodeState) arrayInterface() []interface{} {
var v = make([]interface{}, 0)
for {
// Look ahead for ] - can only happen on first iteration.
break
}
- vi, err := d.valueInterface()
- if err != nil {
- return nil, err
- }
- v = append(v, vi)
+ v = append(v, d.valueInterface())
// Next token must be , or ].
if d.opcode == scanSkipSpace {
break
}
if d.opcode != scanArrayValue {
- return nil, errPhase
+ panic(phasePanicMsg)
}
}
- return v, nil
+ return v
}
// objectInterface is like object but returns map[string]interface{}.
-func (d *decodeState) objectInterface() (map[string]interface{}, error) {
+func (d *decodeState) objectInterface() map[string]interface{} {
m := make(map[string]interface{})
for {
// Read opening " of string key or closing }.
break
}
if d.opcode != scanBeginLiteral {
- return nil, errPhase
+ panic(phasePanicMsg)
}
// Read string key.
item := d.data[start:d.readIndex()]
key, ok := unquote(item)
if !ok {
- return nil, errPhase
+ panic(phasePanicMsg)
}
// Read : before value.
d.scanWhile(scanSkipSpace)
}
if d.opcode != scanObjectKey {
- return nil, errPhase
+ panic(phasePanicMsg)
}
d.scanWhile(scanSkipSpace)
// Read value.
- vi, err := d.valueInterface()
- if err != nil {
- return nil, err
- }
- m[key] = vi
+ m[key] = d.valueInterface()
// Next token must be , or }.
if d.opcode == scanSkipSpace {
break
}
if d.opcode != scanObjectValue {
- return nil, errPhase
+ panic(phasePanicMsg)
}
}
- return m, nil
+ return m
}
// literalInterface consumes and returns a literal from d.data[d.off-1:] and
// it reads the following byte ahead. The first byte of the literal has been
// read already (that's how the caller knows it's a literal).
-func (d *decodeState) literalInterface() (interface{}, error) {
+func (d *decodeState) literalInterface() interface{} {
// All bytes inside literal return scanContinue op code.
start := d.readIndex()
d.scanWhile(scanContinue)
switch c := item[0]; c {
case 'n': // null
- return nil, nil
+ return nil
case 't', 'f': // true, false
- return c == 't', nil
+ return c == 't'
case '"': // string
s, ok := unquote(item)
if !ok {
- return nil, errPhase
+ panic(phasePanicMsg)
}
- return s, nil
+ return s
default: // number
if c != '-' && (c < '0' || c > '9') {
- return nil, errPhase
+ panic(phasePanicMsg)
}
n, err := d.convertNumber(string(item))
if err != nil {
d.saveError(err)
}
- return n, nil
+ return n
}
}