1463 lines
31 KiB
Go
1463 lines
31 KiB
Go
package json
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding"
|
|
"encoding/json"
|
|
"fmt"
|
|
"math"
|
|
"reflect"
|
|
"strconv"
|
|
"time"
|
|
"unsafe"
|
|
|
|
"github.com/segmentio/asm/base64"
|
|
"github.com/segmentio/asm/keyset"
|
|
"github.com/segmentio/encoding/iso8601"
|
|
)
|
|
|
|
func (d decoder) decodeNull(b []byte, p unsafe.Pointer) ([]byte, error) {
|
|
if hasNullPrefix(b) {
|
|
return b[4:], nil
|
|
}
|
|
return d.inputError(b, nullType)
|
|
}
|
|
|
|
func (d decoder) decodeBool(b []byte, p unsafe.Pointer) ([]byte, error) {
|
|
switch {
|
|
case hasTruePrefix(b):
|
|
*(*bool)(p) = true
|
|
return b[4:], nil
|
|
|
|
case hasFalsePrefix(b):
|
|
*(*bool)(p) = false
|
|
return b[5:], nil
|
|
|
|
case hasNullPrefix(b):
|
|
return b[4:], nil
|
|
|
|
default:
|
|
return d.inputError(b, boolType)
|
|
}
|
|
}
|
|
|
|
func (d decoder) decodeInt(b []byte, p unsafe.Pointer) ([]byte, error) {
|
|
if hasNullPrefix(b) {
|
|
return b[4:], nil
|
|
}
|
|
|
|
v, r, err := d.parseInt(b, intType)
|
|
if err != nil {
|
|
return r, err
|
|
}
|
|
|
|
*(*int)(p) = int(v)
|
|
return r, nil
|
|
}
|
|
|
|
func (d decoder) decodeInt8(b []byte, p unsafe.Pointer) ([]byte, error) {
|
|
if hasNullPrefix(b) {
|
|
return b[4:], nil
|
|
}
|
|
|
|
v, r, err := d.parseInt(b, int8Type)
|
|
if err != nil {
|
|
return r, err
|
|
}
|
|
|
|
if v < math.MinInt8 || v > math.MaxInt8 {
|
|
return r, unmarshalOverflow(b[:len(b)-len(r)], int8Type)
|
|
}
|
|
|
|
*(*int8)(p) = int8(v)
|
|
return r, nil
|
|
}
|
|
|
|
func (d decoder) decodeInt16(b []byte, p unsafe.Pointer) ([]byte, error) {
|
|
if hasNullPrefix(b) {
|
|
return b[4:], nil
|
|
}
|
|
|
|
v, r, err := d.parseInt(b, int16Type)
|
|
if err != nil {
|
|
return r, err
|
|
}
|
|
|
|
if v < math.MinInt16 || v > math.MaxInt16 {
|
|
return r, unmarshalOverflow(b[:len(b)-len(r)], int16Type)
|
|
}
|
|
|
|
*(*int16)(p) = int16(v)
|
|
return r, nil
|
|
}
|
|
|
|
func (d decoder) decodeInt32(b []byte, p unsafe.Pointer) ([]byte, error) {
|
|
if hasNullPrefix(b) {
|
|
return b[4:], nil
|
|
}
|
|
|
|
v, r, err := d.parseInt(b, int32Type)
|
|
if err != nil {
|
|
return r, err
|
|
}
|
|
|
|
if v < math.MinInt32 || v > math.MaxInt32 {
|
|
return r, unmarshalOverflow(b[:len(b)-len(r)], int32Type)
|
|
}
|
|
|
|
*(*int32)(p) = int32(v)
|
|
return r, nil
|
|
}
|
|
|
|
func (d decoder) decodeInt64(b []byte, p unsafe.Pointer) ([]byte, error) {
|
|
if hasNullPrefix(b) {
|
|
return b[4:], nil
|
|
}
|
|
|
|
v, r, err := d.parseInt(b, int64Type)
|
|
if err != nil {
|
|
return r, err
|
|
}
|
|
|
|
*(*int64)(p) = v
|
|
return r, nil
|
|
}
|
|
|
|
func (d decoder) decodeUint(b []byte, p unsafe.Pointer) ([]byte, error) {
|
|
if hasNullPrefix(b) {
|
|
return b[4:], nil
|
|
}
|
|
|
|
v, r, err := d.parseUint(b, uintType)
|
|
if err != nil {
|
|
return r, err
|
|
}
|
|
|
|
*(*uint)(p) = uint(v)
|
|
return r, nil
|
|
}
|
|
|
|
func (d decoder) decodeUintptr(b []byte, p unsafe.Pointer) ([]byte, error) {
|
|
if hasNullPrefix(b) {
|
|
return b[4:], nil
|
|
}
|
|
|
|
v, r, err := d.parseUint(b, uintptrType)
|
|
if err != nil {
|
|
return r, err
|
|
}
|
|
|
|
*(*uintptr)(p) = uintptr(v)
|
|
return r, nil
|
|
}
|
|
|
|
func (d decoder) decodeUint8(b []byte, p unsafe.Pointer) ([]byte, error) {
|
|
if hasNullPrefix(b) {
|
|
return b[4:], nil
|
|
}
|
|
|
|
v, r, err := d.parseUint(b, uint8Type)
|
|
if err != nil {
|
|
return r, err
|
|
}
|
|
|
|
if v > math.MaxUint8 {
|
|
return r, unmarshalOverflow(b[:len(b)-len(r)], uint8Type)
|
|
}
|
|
|
|
*(*uint8)(p) = uint8(v)
|
|
return r, nil
|
|
}
|
|
|
|
func (d decoder) decodeUint16(b []byte, p unsafe.Pointer) ([]byte, error) {
|
|
if hasNullPrefix(b) {
|
|
return b[4:], nil
|
|
}
|
|
|
|
v, r, err := d.parseUint(b, uint16Type)
|
|
if err != nil {
|
|
return r, err
|
|
}
|
|
|
|
if v > math.MaxUint16 {
|
|
return r, unmarshalOverflow(b[:len(b)-len(r)], uint16Type)
|
|
}
|
|
|
|
*(*uint16)(p) = uint16(v)
|
|
return r, nil
|
|
}
|
|
|
|
func (d decoder) decodeUint32(b []byte, p unsafe.Pointer) ([]byte, error) {
|
|
if hasNullPrefix(b) {
|
|
return b[4:], nil
|
|
}
|
|
|
|
v, r, err := d.parseUint(b, uint32Type)
|
|
if err != nil {
|
|
return r, err
|
|
}
|
|
|
|
if v > math.MaxUint32 {
|
|
return r, unmarshalOverflow(b[:len(b)-len(r)], uint32Type)
|
|
}
|
|
|
|
*(*uint32)(p) = uint32(v)
|
|
return r, nil
|
|
}
|
|
|
|
func (d decoder) decodeUint64(b []byte, p unsafe.Pointer) ([]byte, error) {
|
|
if hasNullPrefix(b) {
|
|
return b[4:], nil
|
|
}
|
|
|
|
v, r, err := d.parseUint(b, uint64Type)
|
|
if err != nil {
|
|
return r, err
|
|
}
|
|
|
|
*(*uint64)(p) = v
|
|
return r, nil
|
|
}
|
|
|
|
func (d decoder) decodeFloat32(b []byte, p unsafe.Pointer) ([]byte, error) {
|
|
if hasNullPrefix(b) {
|
|
return b[4:], nil
|
|
}
|
|
|
|
v, r, _, err := d.parseNumber(b)
|
|
if err != nil {
|
|
return d.inputError(b, float32Type)
|
|
}
|
|
|
|
f, err := strconv.ParseFloat(*(*string)(unsafe.Pointer(&v)), 32)
|
|
if err != nil {
|
|
return d.inputError(b, float32Type)
|
|
}
|
|
|
|
*(*float32)(p) = float32(f)
|
|
return r, nil
|
|
}
|
|
|
|
func (d decoder) decodeFloat64(b []byte, p unsafe.Pointer) ([]byte, error) {
|
|
if hasNullPrefix(b) {
|
|
return b[4:], nil
|
|
}
|
|
|
|
v, r, _, err := d.parseNumber(b)
|
|
if err != nil {
|
|
return d.inputError(b, float64Type)
|
|
}
|
|
|
|
f, err := strconv.ParseFloat(*(*string)(unsafe.Pointer(&v)), 64)
|
|
if err != nil {
|
|
return d.inputError(b, float64Type)
|
|
}
|
|
|
|
*(*float64)(p) = f
|
|
return r, nil
|
|
}
|
|
|
|
func (d decoder) decodeNumber(b []byte, p unsafe.Pointer) ([]byte, error) {
|
|
if hasNullPrefix(b) {
|
|
return b[4:], nil
|
|
}
|
|
|
|
v, r, _, err := d.parseNumber(b)
|
|
if err != nil {
|
|
return d.inputError(b, numberType)
|
|
}
|
|
|
|
if (d.flags & DontCopyNumber) != 0 {
|
|
*(*Number)(p) = *(*Number)(unsafe.Pointer(&v))
|
|
} else {
|
|
*(*Number)(p) = Number(v)
|
|
}
|
|
|
|
return r, nil
|
|
}
|
|
|
|
func (d decoder) decodeString(b []byte, p unsafe.Pointer) ([]byte, error) {
|
|
if hasNullPrefix(b) {
|
|
return b[4:], nil
|
|
}
|
|
|
|
s, r, new, err := d.parseStringUnquote(b, nil)
|
|
if err != nil {
|
|
if len(b) == 0 || b[0] != '"' {
|
|
return d.inputError(b, stringType)
|
|
}
|
|
return r, err
|
|
}
|
|
|
|
if new || (d.flags&DontCopyString) != 0 {
|
|
*(*string)(p) = *(*string)(unsafe.Pointer(&s))
|
|
} else {
|
|
*(*string)(p) = string(s)
|
|
}
|
|
|
|
return r, nil
|
|
}
|
|
|
|
func (d decoder) decodeFromString(b []byte, p unsafe.Pointer, decode decodeFunc) ([]byte, error) {
|
|
if hasNullPrefix(b) {
|
|
return decode(d, b, p)
|
|
}
|
|
|
|
v, b, _, err := d.parseStringUnquote(b, nil)
|
|
if err != nil {
|
|
return d.inputError(v, stringType)
|
|
}
|
|
|
|
if v, err = decode(d, v, p); err != nil {
|
|
return b, err
|
|
}
|
|
|
|
if v = skipSpaces(v); len(v) != 0 {
|
|
return b, syntaxError(v, "unexpected trailing tokens after string value")
|
|
}
|
|
|
|
return b, nil
|
|
}
|
|
|
|
func (d decoder) decodeFromStringToInt(b []byte, p unsafe.Pointer, t reflect.Type, decode decodeFunc) ([]byte, error) {
|
|
if hasNullPrefix(b) {
|
|
return decode(d, b, p)
|
|
}
|
|
|
|
if len(b) > 0 && b[0] != '"' {
|
|
v, r, k, err := d.parseNumber(b)
|
|
if err == nil {
|
|
// The encoding/json package will return a *json.UnmarshalTypeError if
|
|
// the input was a floating point number representation, even tho a
|
|
// string is expected here.
|
|
if k == Float {
|
|
_, err := strconv.ParseFloat(*(*string)(unsafe.Pointer(&v)), 64)
|
|
if err != nil {
|
|
return r, unmarshalTypeError(v, t)
|
|
}
|
|
}
|
|
}
|
|
return r, fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal unquoted value into int")
|
|
}
|
|
|
|
if len(b) > 1 && b[0] == '"' && b[1] == '"' {
|
|
return b, fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal \"\" into int")
|
|
}
|
|
|
|
v, b, _, err := d.parseStringUnquote(b, nil)
|
|
if err != nil {
|
|
return d.inputError(v, t)
|
|
}
|
|
|
|
if hasLeadingZeroes(v) {
|
|
// In this context the encoding/json package accepts leading zeroes because
|
|
// it is not constrained by the JSON syntax, remove them so the parsing
|
|
// functions don't return syntax errors.
|
|
u := make([]byte, 0, len(v))
|
|
i := 0
|
|
|
|
if i < len(v) && v[i] == '-' || v[i] == '+' {
|
|
u = append(u, v[i])
|
|
i++
|
|
}
|
|
|
|
for (i+1) < len(v) && v[i] == '0' && '0' <= v[i+1] && v[i+1] <= '9' {
|
|
i++
|
|
}
|
|
|
|
v = append(u, v[i:]...)
|
|
}
|
|
|
|
if r, err := decode(d, v, p); err != nil {
|
|
if _, isSyntaxError := err.(*SyntaxError); isSyntaxError {
|
|
if hasPrefix(v, "-") {
|
|
// The standard library interprets sequences of '-' characters
|
|
// as numbers but still returns type errors in this case...
|
|
return b, unmarshalTypeError(v, t)
|
|
}
|
|
return b, fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into int", prefix(v))
|
|
}
|
|
// When the input value was a valid number representation we retain the
|
|
// error returned by the decoder.
|
|
if _, _, _, err := d.parseNumber(v); err != nil {
|
|
// When the input value valid JSON we mirror the behavior of the
|
|
// encoding/json package and return a generic error.
|
|
if _, _, _, err := d.parseValue(v); err == nil {
|
|
return b, fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into int", prefix(v))
|
|
}
|
|
}
|
|
return b, err
|
|
} else if len(r) != 0 {
|
|
return r, unmarshalTypeError(v, t)
|
|
}
|
|
|
|
return b, nil
|
|
}
|
|
|
|
func (d decoder) decodeBytes(b []byte, p unsafe.Pointer) ([]byte, error) {
|
|
if hasNullPrefix(b) {
|
|
*(*[]byte)(p) = nil
|
|
return b[4:], nil
|
|
}
|
|
|
|
if len(b) < 2 {
|
|
return d.inputError(b, bytesType)
|
|
}
|
|
|
|
if b[0] != '"' {
|
|
// Go 1.7- behavior: bytes slices may be decoded from array of integers.
|
|
if len(b) > 0 && b[0] == '[' {
|
|
return d.decodeSlice(b, p, 1, bytesType, decoder.decodeUint8)
|
|
}
|
|
return d.inputError(b, bytesType)
|
|
}
|
|
|
|
// The input string contains escaped sequences, we need to parse it before
|
|
// decoding it to match the encoding/json package behvaior.
|
|
src, r, _, err := d.parseStringUnquote(b, nil)
|
|
if err != nil {
|
|
return d.inputError(b, bytesType)
|
|
}
|
|
|
|
dst := make([]byte, base64.StdEncoding.DecodedLen(len(src)))
|
|
|
|
n, err := base64.StdEncoding.Decode(dst, src)
|
|
if err != nil {
|
|
return r, err
|
|
}
|
|
|
|
*(*[]byte)(p) = dst[:n]
|
|
return r, nil
|
|
}
|
|
|
|
func (d decoder) decodeDuration(b []byte, p unsafe.Pointer) ([]byte, error) {
|
|
if hasNullPrefix(b) {
|
|
return b[4:], nil
|
|
}
|
|
|
|
// in order to inter-operate with the stdlib, we must be able to interpret
|
|
// durations passed as integer values. there's some discussion about being
|
|
// flexible on how durations are formatted, but for the time being, it's
|
|
// been punted to go2 at the earliest: https://github.com/golang/go/issues/4712
|
|
if len(b) > 0 && b[0] != '"' {
|
|
v, r, err := d.parseInt(b, durationType)
|
|
if err != nil {
|
|
return d.inputError(b, int32Type)
|
|
}
|
|
|
|
if v < math.MinInt64 || v > math.MaxInt64 {
|
|
return r, unmarshalOverflow(b[:len(b)-len(r)], int32Type)
|
|
}
|
|
|
|
*(*time.Duration)(p) = time.Duration(v)
|
|
return r, nil
|
|
}
|
|
|
|
if len(b) < 2 || b[0] != '"' {
|
|
return d.inputError(b, durationType)
|
|
}
|
|
|
|
i := bytes.IndexByte(b[1:], '"') + 1
|
|
if i <= 0 {
|
|
return d.inputError(b, durationType)
|
|
}
|
|
|
|
s := b[1:i] // trim quotes
|
|
|
|
v, err := time.ParseDuration(*(*string)(unsafe.Pointer(&s)))
|
|
if err != nil {
|
|
return d.inputError(b, durationType)
|
|
}
|
|
|
|
*(*time.Duration)(p) = v
|
|
return b[i+1:], nil
|
|
}
|
|
|
|
func (d decoder) decodeTime(b []byte, p unsafe.Pointer) ([]byte, error) {
|
|
if hasNullPrefix(b) {
|
|
return b[4:], nil
|
|
}
|
|
|
|
if len(b) < 2 || b[0] != '"' {
|
|
return d.inputError(b, timeType)
|
|
}
|
|
|
|
i := bytes.IndexByte(b[1:], '"') + 1
|
|
if i <= 0 {
|
|
return d.inputError(b, timeType)
|
|
}
|
|
|
|
s := b[1:i] // trim quotes
|
|
|
|
v, err := iso8601.Parse(*(*string)(unsafe.Pointer(&s)))
|
|
if err != nil {
|
|
return d.inputError(b, timeType)
|
|
}
|
|
|
|
*(*time.Time)(p) = v
|
|
return b[i+1:], nil
|
|
}
|
|
|
|
func (d decoder) decodeArray(b []byte, p unsafe.Pointer, n int, size uintptr, t reflect.Type, decode decodeFunc) ([]byte, error) {
|
|
if hasNullPrefix(b) {
|
|
return b[4:], nil
|
|
}
|
|
|
|
if len(b) < 2 || b[0] != '[' {
|
|
return d.inputError(b, t)
|
|
}
|
|
b = b[1:]
|
|
|
|
var err error
|
|
for i := 0; i < n; i++ {
|
|
b = skipSpaces(b)
|
|
|
|
if i != 0 {
|
|
if len(b) == 0 {
|
|
return b, syntaxError(b, "unexpected EOF after array element")
|
|
}
|
|
switch b[0] {
|
|
case ',':
|
|
b = skipSpaces(b[1:])
|
|
case ']':
|
|
return b[1:], nil
|
|
default:
|
|
return b, syntaxError(b, "expected ',' after array element but found '%c'", b[0])
|
|
}
|
|
}
|
|
|
|
b, err = decode(d, b, unsafe.Pointer(uintptr(p)+(uintptr(i)*size)))
|
|
if err != nil {
|
|
if e, ok := err.(*UnmarshalTypeError); ok {
|
|
e.Struct = t.String() + e.Struct
|
|
e.Field = d.prependField(strconv.Itoa(i), e.Field)
|
|
}
|
|
return b, err
|
|
}
|
|
}
|
|
|
|
// The encoding/json package ignores extra elements found when decoding into
|
|
// array types (which have a fixed size).
|
|
for {
|
|
b = skipSpaces(b)
|
|
|
|
if len(b) == 0 {
|
|
return b, syntaxError(b, "missing closing ']' in array value")
|
|
}
|
|
|
|
switch b[0] {
|
|
case ',':
|
|
b = skipSpaces(b[1:])
|
|
case ']':
|
|
return b[1:], nil
|
|
}
|
|
|
|
_, b, _, err = d.parseValue(b)
|
|
if err != nil {
|
|
return b, err
|
|
}
|
|
}
|
|
}
|
|
|
|
var (
|
|
// This is a placeholder used to consturct non-nil empty slices.
|
|
empty struct{}
|
|
)
|
|
|
|
func (d decoder) decodeSlice(b []byte, p unsafe.Pointer, size uintptr, t reflect.Type, decode decodeFunc) ([]byte, error) {
|
|
if hasNullPrefix(b) {
|
|
*(*slice)(p) = slice{}
|
|
return b[4:], nil
|
|
}
|
|
|
|
if len(b) < 2 {
|
|
return d.inputError(b, t)
|
|
}
|
|
|
|
if b[0] != '[' {
|
|
// Go 1.7- behavior: fallback to decoding as a []byte if the element
|
|
// type is byte; allow conversions from JSON strings even tho the
|
|
// underlying type implemented unmarshaler interfaces.
|
|
if t.Elem().Kind() == reflect.Uint8 {
|
|
return d.decodeBytes(b, p)
|
|
}
|
|
return d.inputError(b, t)
|
|
}
|
|
|
|
input := b
|
|
b = b[1:]
|
|
|
|
s := (*slice)(p)
|
|
s.len = 0
|
|
|
|
var err error
|
|
for {
|
|
b = skipSpaces(b)
|
|
|
|
if len(b) != 0 && b[0] == ']' {
|
|
if s.data == nil {
|
|
s.data = unsafe.Pointer(&empty)
|
|
}
|
|
return b[1:], nil
|
|
}
|
|
|
|
if s.len != 0 {
|
|
if len(b) == 0 {
|
|
return b, syntaxError(b, "unexpected EOF after array element")
|
|
}
|
|
if b[0] != ',' {
|
|
return b, syntaxError(b, "expected ',' after array element but found '%c'", b[0])
|
|
}
|
|
b = skipSpaces(b[1:])
|
|
}
|
|
|
|
if s.len == s.cap {
|
|
c := s.cap
|
|
|
|
if c == 0 {
|
|
c = 10
|
|
} else {
|
|
c *= 2
|
|
}
|
|
|
|
*s = extendSlice(t, s, c)
|
|
}
|
|
|
|
b, err = decode(d, b, unsafe.Pointer(uintptr(s.data)+(uintptr(s.len)*size)))
|
|
if err != nil {
|
|
if _, r, _, err := d.parseValue(input); err != nil {
|
|
return r, err
|
|
} else {
|
|
b = r
|
|
}
|
|
if e, ok := err.(*UnmarshalTypeError); ok {
|
|
e.Struct = t.String() + e.Struct
|
|
e.Field = d.prependField(strconv.Itoa(s.len), e.Field)
|
|
}
|
|
return b, err
|
|
}
|
|
|
|
s.len++
|
|
}
|
|
}
|
|
|
|
func (d decoder) decodeMap(b []byte, p unsafe.Pointer, t, kt, vt reflect.Type, kz, vz reflect.Value, decodeKey, decodeValue decodeFunc) ([]byte, error) {
|
|
if hasNullPrefix(b) {
|
|
*(*unsafe.Pointer)(p) = nil
|
|
return b[4:], nil
|
|
}
|
|
|
|
if len(b) < 2 || b[0] != '{' {
|
|
return d.inputError(b, t)
|
|
}
|
|
i := 0
|
|
m := reflect.NewAt(t, p).Elem()
|
|
|
|
k := reflect.New(kt).Elem()
|
|
v := reflect.New(vt).Elem()
|
|
|
|
kptr := (*iface)(unsafe.Pointer(&k)).ptr
|
|
vptr := (*iface)(unsafe.Pointer(&v)).ptr
|
|
input := b
|
|
|
|
if m.IsNil() {
|
|
m = reflect.MakeMap(t)
|
|
}
|
|
|
|
var err error
|
|
b = b[1:]
|
|
for {
|
|
k.Set(kz)
|
|
v.Set(vz)
|
|
b = skipSpaces(b)
|
|
|
|
if len(b) != 0 && b[0] == '}' {
|
|
*(*unsafe.Pointer)(p) = unsafe.Pointer(m.Pointer())
|
|
return b[1:], nil
|
|
}
|
|
|
|
if i != 0 {
|
|
if len(b) == 0 {
|
|
return b, syntaxError(b, "unexpected end of JSON input after object field value")
|
|
}
|
|
if b[0] != ',' {
|
|
return b, syntaxError(b, "expected ',' after object field value but found '%c'", b[0])
|
|
}
|
|
b = skipSpaces(b[1:])
|
|
}
|
|
|
|
if hasNullPrefix(b) {
|
|
return b, syntaxError(b, "cannot decode object key string from 'null' value")
|
|
}
|
|
|
|
if b, err = decodeKey(d, b, kptr); err != nil {
|
|
return objectKeyError(b, err)
|
|
}
|
|
b = skipSpaces(b)
|
|
|
|
if len(b) == 0 {
|
|
return b, syntaxError(b, "unexpected end of JSON input after object field key")
|
|
}
|
|
if b[0] != ':' {
|
|
return b, syntaxError(b, "expected ':' after object field key but found '%c'", b[0])
|
|
}
|
|
b = skipSpaces(b[1:])
|
|
|
|
if b, err = decodeValue(d, b, vptr); err != nil {
|
|
if _, r, _, err := d.parseValue(input); err != nil {
|
|
return r, err
|
|
} else {
|
|
b = r
|
|
}
|
|
if e, ok := err.(*UnmarshalTypeError); ok {
|
|
e.Struct = "map[" + kt.String() + "]" + vt.String() + "{" + e.Struct + "}"
|
|
e.Field = d.prependField(fmt.Sprint(k.Interface()), e.Field)
|
|
}
|
|
return b, err
|
|
}
|
|
|
|
m.SetMapIndex(k, v)
|
|
i++
|
|
}
|
|
}
|
|
|
|
func (d decoder) decodeMapStringInterface(b []byte, p unsafe.Pointer) ([]byte, error) {
|
|
if hasNullPrefix(b) {
|
|
*(*unsafe.Pointer)(p) = nil
|
|
return b[4:], nil
|
|
}
|
|
|
|
if len(b) < 2 || b[0] != '{' {
|
|
return d.inputError(b, mapStringInterfaceType)
|
|
}
|
|
|
|
i := 0
|
|
m := *(*map[string]interface{})(p)
|
|
|
|
if m == nil {
|
|
m = make(map[string]interface{}, 64)
|
|
}
|
|
|
|
var err error
|
|
var key string
|
|
var val interface{}
|
|
var input = b
|
|
|
|
b = b[1:]
|
|
for {
|
|
key = ""
|
|
val = nil
|
|
|
|
b = skipSpaces(b)
|
|
|
|
if len(b) != 0 && b[0] == '}' {
|
|
*(*unsafe.Pointer)(p) = *(*unsafe.Pointer)(unsafe.Pointer(&m))
|
|
return b[1:], nil
|
|
}
|
|
|
|
if i != 0 {
|
|
if len(b) == 0 {
|
|
return b, syntaxError(b, "unexpected end of JSON input after object field value")
|
|
}
|
|
if b[0] != ',' {
|
|
return b, syntaxError(b, "expected ',' after object field value but found '%c'", b[0])
|
|
}
|
|
b = skipSpaces(b[1:])
|
|
}
|
|
|
|
if hasNullPrefix(b) {
|
|
return b, syntaxError(b, "cannot decode object key string from 'null' value")
|
|
}
|
|
|
|
b, err = d.decodeString(b, unsafe.Pointer(&key))
|
|
if err != nil {
|
|
return objectKeyError(b, err)
|
|
}
|
|
b = skipSpaces(b)
|
|
|
|
if len(b) == 0 {
|
|
return b, syntaxError(b, "unexpected end of JSON input after object field key")
|
|
}
|
|
if b[0] != ':' {
|
|
return b, syntaxError(b, "expected ':' after object field key but found '%c'", b[0])
|
|
}
|
|
b = skipSpaces(b[1:])
|
|
|
|
b, err = d.decodeInterface(b, unsafe.Pointer(&val))
|
|
if err != nil {
|
|
if _, r, _, err := d.parseValue(input); err != nil {
|
|
return r, err
|
|
} else {
|
|
b = r
|
|
}
|
|
if e, ok := err.(*UnmarshalTypeError); ok {
|
|
e.Struct = mapStringInterfaceType.String() + e.Struct
|
|
e.Field = d.prependField(key, e.Field)
|
|
}
|
|
return b, err
|
|
}
|
|
|
|
m[key] = val
|
|
i++
|
|
}
|
|
}
|
|
|
|
func (d decoder) decodeMapStringRawMessage(b []byte, p unsafe.Pointer) ([]byte, error) {
|
|
if hasNullPrefix(b) {
|
|
*(*unsafe.Pointer)(p) = nil
|
|
return b[4:], nil
|
|
}
|
|
|
|
if len(b) < 2 || b[0] != '{' {
|
|
return d.inputError(b, mapStringRawMessageType)
|
|
}
|
|
|
|
i := 0
|
|
m := *(*map[string]RawMessage)(p)
|
|
|
|
if m == nil {
|
|
m = make(map[string]RawMessage, 64)
|
|
}
|
|
|
|
var err error
|
|
var key string
|
|
var val RawMessage
|
|
var input = b
|
|
|
|
b = b[1:]
|
|
for {
|
|
key = ""
|
|
val = nil
|
|
|
|
b = skipSpaces(b)
|
|
|
|
if len(b) != 0 && b[0] == '}' {
|
|
*(*unsafe.Pointer)(p) = *(*unsafe.Pointer)(unsafe.Pointer(&m))
|
|
return b[1:], nil
|
|
}
|
|
|
|
if i != 0 {
|
|
if len(b) == 0 {
|
|
return b, syntaxError(b, "unexpected end of JSON input after object field value")
|
|
}
|
|
if b[0] != ',' {
|
|
return b, syntaxError(b, "expected ',' after object field value but found '%c'", b[0])
|
|
}
|
|
b = skipSpaces(b[1:])
|
|
}
|
|
|
|
if hasNullPrefix(b) {
|
|
return b, syntaxError(b, "cannot decode object key string from 'null' value")
|
|
}
|
|
|
|
b, err = d.decodeString(b, unsafe.Pointer(&key))
|
|
if err != nil {
|
|
return objectKeyError(b, err)
|
|
}
|
|
b = skipSpaces(b)
|
|
|
|
if len(b) == 0 {
|
|
return b, syntaxError(b, "unexpected end of JSON input after object field key")
|
|
}
|
|
if b[0] != ':' {
|
|
return b, syntaxError(b, "expected ':' after object field key but found '%c'", b[0])
|
|
}
|
|
b = skipSpaces(b[1:])
|
|
|
|
b, err = d.decodeRawMessage(b, unsafe.Pointer(&val))
|
|
if err != nil {
|
|
if _, r, _, err := d.parseValue(input); err != nil {
|
|
return r, err
|
|
} else {
|
|
b = r
|
|
}
|
|
if e, ok := err.(*UnmarshalTypeError); ok {
|
|
e.Struct = mapStringRawMessageType.String() + e.Struct
|
|
e.Field = d.prependField(key, e.Field)
|
|
}
|
|
return b, err
|
|
}
|
|
|
|
m[key] = val
|
|
i++
|
|
}
|
|
}
|
|
|
|
func (d decoder) decodeMapStringString(b []byte, p unsafe.Pointer) ([]byte, error) {
|
|
if hasNullPrefix(b) {
|
|
*(*unsafe.Pointer)(p) = nil
|
|
return b[4:], nil
|
|
}
|
|
|
|
if len(b) < 2 || b[0] != '{' {
|
|
return d.inputError(b, mapStringStringType)
|
|
}
|
|
|
|
i := 0
|
|
m := *(*map[string]string)(p)
|
|
|
|
if m == nil {
|
|
m = make(map[string]string, 64)
|
|
}
|
|
|
|
var err error
|
|
var key string
|
|
var val string
|
|
var input = b
|
|
|
|
b = b[1:]
|
|
for {
|
|
key = ""
|
|
val = ""
|
|
|
|
b = skipSpaces(b)
|
|
|
|
if len(b) != 0 && b[0] == '}' {
|
|
*(*unsafe.Pointer)(p) = *(*unsafe.Pointer)(unsafe.Pointer(&m))
|
|
return b[1:], nil
|
|
}
|
|
|
|
if i != 0 {
|
|
if len(b) == 0 {
|
|
return b, syntaxError(b, "unexpected end of JSON input after object field value")
|
|
}
|
|
if b[0] != ',' {
|
|
return b, syntaxError(b, "expected ',' after object field value but found '%c'", b[0])
|
|
}
|
|
b = skipSpaces(b[1:])
|
|
}
|
|
|
|
if hasNullPrefix(b) {
|
|
return b, syntaxError(b, "cannot decode object key string from 'null' value")
|
|
}
|
|
|
|
b, err = d.decodeString(b, unsafe.Pointer(&key))
|
|
if err != nil {
|
|
return objectKeyError(b, err)
|
|
}
|
|
b = skipSpaces(b)
|
|
|
|
if len(b) == 0 {
|
|
return b, syntaxError(b, "unexpected end of JSON input after object field key")
|
|
}
|
|
if b[0] != ':' {
|
|
return b, syntaxError(b, "expected ':' after object field key but found '%c'", b[0])
|
|
}
|
|
b = skipSpaces(b[1:])
|
|
|
|
b, err = d.decodeString(b, unsafe.Pointer(&val))
|
|
if err != nil {
|
|
if _, r, _, err := d.parseValue(input); err != nil {
|
|
return r, err
|
|
} else {
|
|
b = r
|
|
}
|
|
if e, ok := err.(*UnmarshalTypeError); ok {
|
|
e.Struct = mapStringStringType.String() + e.Struct
|
|
e.Field = d.prependField(key, e.Field)
|
|
}
|
|
return b, err
|
|
}
|
|
|
|
m[key] = val
|
|
i++
|
|
}
|
|
}
|
|
|
|
func (d decoder) decodeMapStringStringSlice(b []byte, p unsafe.Pointer) ([]byte, error) {
|
|
if hasNullPrefix(b) {
|
|
*(*unsafe.Pointer)(p) = nil
|
|
return b[4:], nil
|
|
}
|
|
|
|
if len(b) < 2 || b[0] != '{' {
|
|
return d.inputError(b, mapStringStringSliceType)
|
|
}
|
|
|
|
i := 0
|
|
m := *(*map[string][]string)(p)
|
|
|
|
if m == nil {
|
|
m = make(map[string][]string, 64)
|
|
}
|
|
|
|
var err error
|
|
var key string
|
|
var buf []string
|
|
var input = b
|
|
var stringSize = unsafe.Sizeof("")
|
|
|
|
b = b[1:]
|
|
for {
|
|
key = ""
|
|
buf = buf[:0]
|
|
|
|
b = skipSpaces(b)
|
|
|
|
if len(b) != 0 && b[0] == '}' {
|
|
*(*unsafe.Pointer)(p) = *(*unsafe.Pointer)(unsafe.Pointer(&m))
|
|
return b[1:], nil
|
|
}
|
|
|
|
if i != 0 {
|
|
if len(b) == 0 {
|
|
return b, syntaxError(b, "unexpected end of JSON input after object field value")
|
|
}
|
|
if b[0] != ',' {
|
|
return b, syntaxError(b, "expected ',' after object field value but found '%c'", b[0])
|
|
}
|
|
b = skipSpaces(b[1:])
|
|
}
|
|
|
|
if hasNullPrefix(b) {
|
|
return b, syntaxError(b, "cannot decode object key string from 'null' value")
|
|
}
|
|
|
|
b, err = d.decodeString(b, unsafe.Pointer(&key))
|
|
if err != nil {
|
|
return objectKeyError(b, err)
|
|
}
|
|
b = skipSpaces(b)
|
|
|
|
if len(b) == 0 {
|
|
return b, syntaxError(b, "unexpected end of JSON input after object field key")
|
|
}
|
|
if b[0] != ':' {
|
|
return b, syntaxError(b, "expected ':' after object field key but found '%c'", b[0])
|
|
}
|
|
b = skipSpaces(b[1:])
|
|
|
|
b, err = d.decodeSlice(b, unsafe.Pointer(&buf), stringSize, sliceStringType, decoder.decodeString)
|
|
if err != nil {
|
|
if _, r, _, err := d.parseValue(input); err != nil {
|
|
return r, err
|
|
} else {
|
|
b = r
|
|
}
|
|
if e, ok := err.(*UnmarshalTypeError); ok {
|
|
e.Struct = mapStringStringType.String() + e.Struct
|
|
e.Field = d.prependField(key, e.Field)
|
|
}
|
|
return b, err
|
|
}
|
|
|
|
val := make([]string, len(buf))
|
|
copy(val, buf)
|
|
|
|
m[key] = val
|
|
i++
|
|
}
|
|
}
|
|
|
|
func (d decoder) decodeMapStringBool(b []byte, p unsafe.Pointer) ([]byte, error) {
|
|
if hasNullPrefix(b) {
|
|
*(*unsafe.Pointer)(p) = nil
|
|
return b[4:], nil
|
|
}
|
|
|
|
if len(b) < 2 || b[0] != '{' {
|
|
return d.inputError(b, mapStringBoolType)
|
|
}
|
|
|
|
i := 0
|
|
m := *(*map[string]bool)(p)
|
|
|
|
if m == nil {
|
|
m = make(map[string]bool, 64)
|
|
}
|
|
|
|
var err error
|
|
var key string
|
|
var val bool
|
|
var input = b
|
|
|
|
b = b[1:]
|
|
for {
|
|
key = ""
|
|
val = false
|
|
|
|
b = skipSpaces(b)
|
|
|
|
if len(b) != 0 && b[0] == '}' {
|
|
*(*unsafe.Pointer)(p) = *(*unsafe.Pointer)(unsafe.Pointer(&m))
|
|
return b[1:], nil
|
|
}
|
|
|
|
if i != 0 {
|
|
if len(b) == 0 {
|
|
return b, syntaxError(b, "unexpected end of JSON input after object field value")
|
|
}
|
|
if b[0] != ',' {
|
|
return b, syntaxError(b, "expected ',' after object field value but found '%c'", b[0])
|
|
}
|
|
b = skipSpaces(b[1:])
|
|
}
|
|
|
|
if hasNullPrefix(b) {
|
|
return b, syntaxError(b, "cannot decode object key string from 'null' value")
|
|
}
|
|
|
|
b, err = d.decodeString(b, unsafe.Pointer(&key))
|
|
if err != nil {
|
|
return objectKeyError(b, err)
|
|
}
|
|
b = skipSpaces(b)
|
|
|
|
if len(b) == 0 {
|
|
return b, syntaxError(b, "unexpected end of JSON input after object field key")
|
|
}
|
|
if b[0] != ':' {
|
|
return b, syntaxError(b, "expected ':' after object field key but found '%c'", b[0])
|
|
}
|
|
b = skipSpaces(b[1:])
|
|
|
|
b, err = d.decodeBool(b, unsafe.Pointer(&val))
|
|
if err != nil {
|
|
if _, r, _, err := d.parseValue(input); err != nil {
|
|
return r, err
|
|
} else {
|
|
b = r
|
|
}
|
|
if e, ok := err.(*UnmarshalTypeError); ok {
|
|
e.Struct = mapStringStringType.String() + e.Struct
|
|
e.Field = d.prependField(key, e.Field)
|
|
}
|
|
return b, err
|
|
}
|
|
|
|
m[key] = val
|
|
i++
|
|
}
|
|
}
|
|
|
|
func (d decoder) decodeStruct(b []byte, p unsafe.Pointer, st *structType) ([]byte, error) {
|
|
if hasNullPrefix(b) {
|
|
return b[4:], nil
|
|
}
|
|
|
|
if len(b) < 2 || b[0] != '{' {
|
|
return d.inputError(b, st.typ)
|
|
}
|
|
|
|
var err error
|
|
var k []byte
|
|
var i int
|
|
|
|
// memory buffer used to convert short field names to lowercase
|
|
var buf [64]byte
|
|
var key []byte
|
|
var input = b
|
|
|
|
b = b[1:]
|
|
for {
|
|
b = skipSpaces(b)
|
|
|
|
if len(b) != 0 && b[0] == '}' {
|
|
return b[1:], nil
|
|
}
|
|
|
|
if i != 0 {
|
|
if len(b) == 0 {
|
|
return b, syntaxError(b, "unexpected end of JSON input after object field value")
|
|
}
|
|
if b[0] != ',' {
|
|
return b, syntaxError(b, "expected ',' after object field value but found '%c'", b[0])
|
|
}
|
|
b = skipSpaces(b[1:])
|
|
}
|
|
i++
|
|
|
|
if hasNullPrefix(b) {
|
|
return b, syntaxError(b, "cannot decode object key string from 'null' value")
|
|
}
|
|
|
|
k, b, _, err = d.parseStringUnquote(b, nil)
|
|
if err != nil {
|
|
return objectKeyError(b, err)
|
|
}
|
|
b = skipSpaces(b)
|
|
|
|
if len(b) == 0 {
|
|
return b, syntaxError(b, "unexpected end of JSON input after object field key")
|
|
}
|
|
if b[0] != ':' {
|
|
return b, syntaxError(b, "expected ':' after object field key but found '%c'", b[0])
|
|
}
|
|
b = skipSpaces(b[1:])
|
|
|
|
var f *structField
|
|
if len(st.keyset) != 0 {
|
|
if n := keyset.Lookup(st.keyset, k); n < len(st.fields) {
|
|
f = &st.fields[n]
|
|
}
|
|
} else {
|
|
f = st.fieldsIndex[string(k)]
|
|
}
|
|
|
|
if f == nil && (d.flags&DontMatchCaseInsensitiveStructFields) == 0 {
|
|
key = appendToLower(buf[:0], k)
|
|
f = st.ficaseIndex[string(key)]
|
|
}
|
|
|
|
if f == nil {
|
|
if (d.flags & DisallowUnknownFields) != 0 {
|
|
return b, fmt.Errorf("json: unknown field %q", k)
|
|
}
|
|
if _, b, _, err = d.parseValue(b); err != nil {
|
|
return b, err
|
|
}
|
|
continue
|
|
}
|
|
|
|
if b, err = f.codec.decode(d, b, unsafe.Pointer(uintptr(p)+f.offset)); err != nil {
|
|
if _, r, _, err := d.parseValue(input); err != nil {
|
|
return r, err
|
|
} else {
|
|
b = r
|
|
}
|
|
if e, ok := err.(*UnmarshalTypeError); ok {
|
|
e.Struct = st.typ.String() + e.Struct
|
|
e.Field = d.prependField(string(k), e.Field)
|
|
}
|
|
return b, err
|
|
}
|
|
}
|
|
}
|
|
|
|
func (d decoder) decodeEmbeddedStructPointer(b []byte, p unsafe.Pointer, t reflect.Type, unexported bool, offset uintptr, decode decodeFunc) ([]byte, error) {
|
|
v := *(*unsafe.Pointer)(p)
|
|
|
|
if v == nil {
|
|
if unexported {
|
|
return nil, fmt.Errorf("json: cannot set embedded pointer to unexported struct: %s", t)
|
|
}
|
|
v = unsafe.Pointer(reflect.New(t).Pointer())
|
|
*(*unsafe.Pointer)(p) = v
|
|
}
|
|
|
|
return decode(d, b, unsafe.Pointer(uintptr(v)+offset))
|
|
}
|
|
|
|
func (d decoder) decodePointer(b []byte, p unsafe.Pointer, t reflect.Type, decode decodeFunc) ([]byte, error) {
|
|
if hasNullPrefix(b) {
|
|
pp := *(*unsafe.Pointer)(p)
|
|
if pp != nil && t.Kind() == reflect.Ptr {
|
|
return decode(d, b, pp)
|
|
}
|
|
*(*unsafe.Pointer)(p) = nil
|
|
return b[4:], nil
|
|
}
|
|
|
|
v := *(*unsafe.Pointer)(p)
|
|
if v == nil {
|
|
v = unsafe.Pointer(reflect.New(t).Pointer())
|
|
*(*unsafe.Pointer)(p) = v
|
|
}
|
|
|
|
return decode(d, b, v)
|
|
}
|
|
|
|
func (d decoder) decodeInterface(b []byte, p unsafe.Pointer) ([]byte, error) {
|
|
val := *(*interface{})(p)
|
|
*(*interface{})(p) = nil
|
|
|
|
if t := reflect.TypeOf(val); t != nil && t.Kind() == reflect.Ptr {
|
|
if v := reflect.ValueOf(val); v.IsNil() || t.Elem().Kind() != reflect.Ptr {
|
|
// If the destination is nil the only value that is OK to decode is
|
|
// `null`, and the encoding/json package always nils the destination
|
|
// interface value in this case.
|
|
if hasNullPrefix(b) {
|
|
*(*interface{})(p) = nil
|
|
return b[4:], nil
|
|
}
|
|
}
|
|
|
|
b, err := Parse(b, val, d.flags)
|
|
if err == nil {
|
|
*(*interface{})(p) = val
|
|
}
|
|
return b, err
|
|
}
|
|
|
|
v, b, k, err := d.parseValue(b)
|
|
if err != nil {
|
|
return b, err
|
|
}
|
|
|
|
switch k.Class() {
|
|
case Object:
|
|
m := make(map[string]interface{})
|
|
v, err = d.decodeMapStringInterface(v, unsafe.Pointer(&m))
|
|
val = m
|
|
|
|
case Array:
|
|
a := make([]interface{}, 0, 10)
|
|
v, err = d.decodeSlice(v, unsafe.Pointer(&a), unsafe.Sizeof(a[0]), sliceInterfaceType, decoder.decodeInterface)
|
|
val = a
|
|
|
|
case String:
|
|
s := ""
|
|
v, err = d.decodeString(v, unsafe.Pointer(&s))
|
|
val = s
|
|
|
|
case Null:
|
|
v, val = nil, nil
|
|
|
|
case Bool:
|
|
v, val = nil, k == True
|
|
|
|
case Num:
|
|
if (d.flags & UseNumber) != 0 {
|
|
n := Number("")
|
|
v, err = d.decodeNumber(v, unsafe.Pointer(&n))
|
|
val = n
|
|
} else {
|
|
f := 0.0
|
|
v, err = d.decodeFloat64(v, unsafe.Pointer(&f))
|
|
val = f
|
|
}
|
|
|
|
default:
|
|
return b, syntaxError(v, "expected token but found '%c'", v[0])
|
|
}
|
|
|
|
if err != nil {
|
|
return b, err
|
|
}
|
|
|
|
if v = skipSpaces(v); len(v) != 0 {
|
|
return b, syntaxError(v, "unexpected trailing trailing tokens after json value")
|
|
}
|
|
|
|
*(*interface{})(p) = val
|
|
return b, nil
|
|
}
|
|
|
|
func (d decoder) decodeMaybeEmptyInterface(b []byte, p unsafe.Pointer, t reflect.Type) ([]byte, error) {
|
|
if hasNullPrefix(b) {
|
|
*(*interface{})(p) = nil
|
|
return b[4:], nil
|
|
}
|
|
|
|
if x := reflect.NewAt(t, p).Elem(); !x.IsNil() {
|
|
if e := x.Elem(); e.Kind() == reflect.Ptr {
|
|
return Parse(b, e.Interface(), d.flags)
|
|
}
|
|
} else if t.NumMethod() == 0 { // empty interface
|
|
return Parse(b, (*interface{})(p), d.flags)
|
|
}
|
|
|
|
return d.decodeUnmarshalTypeError(b, p, t)
|
|
}
|
|
|
|
func (d decoder) decodeUnmarshalTypeError(b []byte, p unsafe.Pointer, t reflect.Type) ([]byte, error) {
|
|
v, b, _, err := d.parseValue(b)
|
|
if err != nil {
|
|
return b, err
|
|
}
|
|
return b, &UnmarshalTypeError{
|
|
Value: string(v),
|
|
Type: t,
|
|
}
|
|
}
|
|
|
|
func (d decoder) decodeRawMessage(b []byte, p unsafe.Pointer) ([]byte, error) {
|
|
v, r, _, err := d.parseValue(b)
|
|
if err != nil {
|
|
return d.inputError(b, rawMessageType)
|
|
}
|
|
|
|
if (d.flags & DontCopyRawMessage) == 0 {
|
|
v = append(make([]byte, 0, len(v)), v...)
|
|
}
|
|
|
|
*(*RawMessage)(p) = json.RawMessage(v)
|
|
return r, err
|
|
}
|
|
|
|
func (d decoder) decodeJSONUnmarshaler(b []byte, p unsafe.Pointer, t reflect.Type, pointer bool) ([]byte, error) {
|
|
v, b, _, err := d.parseValue(b)
|
|
if err != nil {
|
|
return b, err
|
|
}
|
|
|
|
u := reflect.NewAt(t, p)
|
|
if !pointer {
|
|
u = u.Elem()
|
|
t = t.Elem()
|
|
}
|
|
if u.IsNil() {
|
|
u.Set(reflect.New(t))
|
|
}
|
|
|
|
return b, u.Interface().(Unmarshaler).UnmarshalJSON(v)
|
|
}
|
|
|
|
func (d decoder) decodeTextUnmarshaler(b []byte, p unsafe.Pointer, t reflect.Type, pointer bool) ([]byte, error) {
|
|
var value string
|
|
|
|
v, b, k, err := d.parseValue(b)
|
|
if err != nil {
|
|
return b, err
|
|
}
|
|
if len(v) == 0 {
|
|
return d.inputError(v, t)
|
|
}
|
|
|
|
switch k.Class() {
|
|
case Null:
|
|
return b, err
|
|
|
|
case String:
|
|
s, _, _, err := d.parseStringUnquote(v, nil)
|
|
if err != nil {
|
|
return b, err
|
|
}
|
|
u := reflect.NewAt(t, p)
|
|
if !pointer {
|
|
u = u.Elem()
|
|
t = t.Elem()
|
|
}
|
|
if u.IsNil() {
|
|
u.Set(reflect.New(t))
|
|
}
|
|
return b, u.Interface().(encoding.TextUnmarshaler).UnmarshalText(s)
|
|
|
|
case Bool:
|
|
if k == True {
|
|
value = "true"
|
|
} else {
|
|
value = "false"
|
|
}
|
|
|
|
case Num:
|
|
value = "number"
|
|
|
|
case Object:
|
|
value = "object"
|
|
|
|
case Array:
|
|
value = "array"
|
|
}
|
|
|
|
return b, &UnmarshalTypeError{Value: value, Type: reflect.PtrTo(t)}
|
|
}
|
|
|
|
func (d decoder) prependField(key, field string) string {
|
|
if field != "" {
|
|
return key + "." + field
|
|
}
|
|
return key
|
|
}
|
|
|
|
func (d decoder) inputError(b []byte, t reflect.Type) ([]byte, error) {
|
|
if len(b) == 0 {
|
|
return nil, unexpectedEOF(b)
|
|
}
|
|
_, r, _, err := d.parseValue(b)
|
|
if err != nil {
|
|
return r, err
|
|
}
|
|
return skipSpaces(r), unmarshalTypeError(b, t)
|
|
}
|