You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

1031 lines
27 KiB

//
// DISCLAIMER
//
// Copyright 2017 ArangoDB GmbH, Cologne, Germany
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// Copyright holder is ArangoDB GmbH, Cologne, Germany
//
// Author Ewout Prangsma
//
// This code is heavily inspired by the Go sources.
// See https://golang.org/src/encoding/json/
package velocypack
import (
"bytes"
"encoding"
"encoding/base64"
"encoding/json"
"fmt"
"io"
"reflect"
"runtime"
"strconv"
)
// A Decoder decodes velocypack values into Go structures.
type Decoder struct {
r io.Reader
}
// Unmarshaler is implemented by types that can convert themselves from Velocypack.
type Unmarshaler interface {
UnmarshalVPack(Slice) error
}
// NewDecoder creates a new Decoder that reads data from the given reader.
func NewDecoder(r io.Reader) *Decoder {
return &Decoder{
r: r,
}
}
// Unmarshal reads v from the given Velocypack encoded data slice.
//
// Unmarshal uses the inverse of the encodings that
// Marshal uses, allocating maps, slices, and pointers as necessary,
// with the following additional rules:
//
// To unmarshal VelocyPack into a pointer, Unmarshal first handles the case of
// the VelocyPack being the VelocyPack literal Null. In that case, Unmarshal sets
// the pointer to nil. Otherwise, Unmarshal unmarshals the VelocyPack into
// the value pointed at by the pointer. If the pointer is nil, Unmarshal
// allocates a new value for it to point to.
//
// To unmarshal VelocyPack into a value implementing the Unmarshaler interface,
// Unmarshal calls that value's UnmarshalVPack method, including
// when the input is a VelocyPack Null.
// Otherwise, if the value implements encoding.TextUnmarshaler
// and the input is a VelocyPack quoted string, Unmarshal calls that value's
// UnmarshalText method with the unquoted form of the string.
//
// To unmarshal VelocyPack into a struct, Unmarshal matches incoming object
// keys to the keys used by Marshal (either the struct field name or its tag),
// preferring an exact match but also accepting a case-insensitive match.
// Unmarshal will only set exported fields of the struct.
//
// To unmarshal VelocyPack into an interface value,
// Unmarshal stores one of these in the interface value:
//
// bool, for VelocyPack Bool's
// float64 for VelocyPack Double's
// uint64 for VelocyPack UInt's
// int64 for VelocyPack Int's
// string, for VelocyPack String's
// []interface{}, for VelocyPack Array's
// map[string]interface{}, for VelocyPack Object's
// nil for VelocyPack Null.
// []byte for VelocyPack Binary.
//
// To unmarshal a VelocyPack array into a slice, Unmarshal resets the slice length
// to zero and then appends each element to the slice.
// As a special case, to unmarshal an empty VelocyPack array into a slice,
// Unmarshal replaces the slice with a new empty slice.
//
// To unmarshal a VelocyPack array into a Go array, Unmarshal decodes
// VelocyPack array elements into corresponding Go array elements.
// If the Go array is smaller than the VelocyPack array,
// the additional VelocyPack array elements are discarded.
// If the VelocyPack array is smaller than the Go array,
// the additional Go array elements are set to zero values.
//
// To unmarshal a VelocyPack object into a map, Unmarshal first establishes a map to
// use. If the map is nil, Unmarshal allocates a new map. Otherwise Unmarshal
// reuses the existing map, keeping existing entries. Unmarshal then stores
// key-value pairs from the VelocyPack object into the map. The map's key type must
// either be a string, an integer, or implement encoding.TextUnmarshaler.
//
// If a VelocyPack value is not appropriate for a given target type,
// or if a VelocyPack number overflows the target type, Unmarshal
// skips that field and completes the unmarshaling as best it can.
// If no more serious errors are encountered, Unmarshal returns
// an UnmarshalTypeError describing the earliest such error.
//
// The VelocyPack Null value unmarshals into an interface, map, pointer, or slice
// by setting that Go value to nil. Because null is often used in VelocyPack to mean
// ``not present,'' unmarshaling a VelocyPack Null into any other Go type has no effect
// on the value and produces no error.
//
func Unmarshal(data Slice, v interface{}) error {
if err := unmarshalSlice(data, v); err != nil {
return WithStack(err)
}
return nil
}
// Decode reads v from the decoder stream.
func (e *Decoder) Decode(v interface{}) error {
s, err := SliceFromReader(e.r)
if err != nil {
return WithStack(err)
}
if err := unmarshalSlice(s, v); err != nil {
return WithStack(err)
}
return nil
}
// unmarshalSlice reads v from the given slice.
func unmarshalSlice(data Slice, v interface{}) (err error) {
defer func() {
if r := recover(); r != nil {
if _, ok := r.(runtime.Error); ok {
panic(r)
}
err = r.(error)
}
}()
rv := reflect.ValueOf(v)
if rv.Kind() != reflect.Ptr || rv.IsNil() {
return &InvalidUnmarshalError{reflect.TypeOf(v)}
}
d := &decodeState{}
// We decode rv not rv.Elem because the Unmarshaler interface
// test must be applied at the top level of the value.
d.unmarshalValue(data, rv)
return d.savedError
}
var (
textUnmarshalerType = reflect.TypeOf(new(encoding.TextUnmarshaler)).Elem()
numberType = reflect.TypeOf(json.Number(""))
)
type decodeState struct {
useNumber bool
errorContext struct { // provides context for type errors
Struct string
Field string
}
savedError error
}
// error aborts the decoding by panicking with err.
func (d *decodeState) error(err error) {
panic(d.addErrorContext(err))
}
// saveError saves the first err it is called with,
// for reporting at the end of the unmarshal.
func (d *decodeState) saveError(err error) {
if d.savedError == nil {
d.savedError = d.addErrorContext(err)
}
}
// addErrorContext returns a new error enhanced with information from d.errorContext
func (d *decodeState) addErrorContext(err error) error {
if d.errorContext.Struct != "" || d.errorContext.Field != "" {
switch err := err.(type) {
case *UnmarshalTypeError:
err.Struct = d.errorContext.Struct
err.Field = d.errorContext.Field
return err
}
}
return err
}
// unmarshalValue unmarshals any slice into given v.
func (d *decodeState) unmarshalValue(data Slice, v reflect.Value) {
if !v.IsValid() {
return
}
switch data.Type() {
case Array:
d.unmarshalArray(data, v)
case Object:
d.unmarshalObject(data, v)
case Bool, Int, SmallInt, UInt, Double, Binary, BCD, String:
d.unmarshalLiteral(data, v)
}
}
// indirect walks down v allocating pointers as needed,
// until it gets to a non-pointer.
// if it encounters an Unmarshaler, indirect stops and returns that.
// if decodingNull is true, indirect stops at the last pointer so it can be set to nil.
func (d *decodeState) indirect(v reflect.Value, decodingNull bool) (Unmarshaler, json.Unmarshaler, encoding.TextUnmarshaler, reflect.Value) {
// If v is a named type and is addressable,
// start with its address, so that if the type has pointer methods,
// we find them.
if v.Kind() != reflect.Ptr && v.Type().Name() != "" && v.CanAddr() {
v = v.Addr()
}
for {
// Load value from interface, but only if the result will be
// usefully addressable.
if v.Kind() == reflect.Interface && !v.IsNil() {
e := v.Elem()
if e.Kind() == reflect.Ptr && !e.IsNil() && (!decodingNull || e.Elem().Kind() == reflect.Ptr) {
v = e
continue
}
}
if v.Kind() != reflect.Ptr {
break
}
if v.Elem().Kind() != reflect.Ptr && decodingNull && v.CanSet() {
break
}
if v.IsNil() {
v.Set(reflect.New(v.Type().Elem()))
}
if v.Type().NumMethod() > 0 {
if u, ok := v.Interface().(Unmarshaler); ok {
return u, nil, nil, reflect.Value{}
}
if u, ok := v.Interface().(json.Unmarshaler); ok {
return nil, u, nil, reflect.Value{}
}
if !decodingNull {
if u, ok := v.Interface().(encoding.TextUnmarshaler); ok {
return nil, nil, u, reflect.Value{}
}
}
}
v = v.Elem()
}
return nil, nil, nil, v
}
// unmarshalArray unmarshals an array slice into given v.
func (d *decodeState) unmarshalArray(data Slice, v reflect.Value) {
// Check for unmarshaler.
u, ju, ut, pv := d.indirect(v, false)
if u != nil {
if err := u.UnmarshalVPack(data); err != nil {
d.error(err)
}
return
}
if ju != nil {
json, err := data.JSONString()
if err != nil {
d.error(err)
} else {
if err := ju.UnmarshalJSON([]byte(json)); err != nil {
d.error(err)
}
}
return
}
if ut != nil {
d.saveError(&UnmarshalTypeError{Value: "array", Type: v.Type()})
return
}
v = pv
// Check type of target.
switch v.Kind() {
case reflect.Interface:
if v.NumMethod() == 0 {
// Decoding into nil interface? Switch to non-reflect code.
v.Set(reflect.ValueOf(d.arrayInterface(data)))
return
}
// Otherwise it's invalid.
fallthrough
default:
d.saveError(&UnmarshalTypeError{Value: "array", Type: v.Type()})
return
case reflect.Array:
case reflect.Slice:
break
}
i := 0
it, err := NewArrayIterator(data)
if err != nil {
d.error(err)
}
for it.IsValid() {
value, err := it.Value()
if err != nil {
d.error(err)
}
// Get element of array, growing if necessary.
if v.Kind() == reflect.Slice {
// Grow slice if necessary
if i >= v.Cap() {
newcap := v.Cap() + v.Cap()/2
if newcap < 4 {
newcap = 4
}
newv := reflect.MakeSlice(v.Type(), v.Len(), newcap)
reflect.Copy(newv, v)
v.Set(newv)
}
if i >= v.Len() {
v.SetLen(i + 1)
}
}
if i < v.Len() {
// Decode into element.
d.unmarshalValue(value, v.Index(i))
}
i++
if err := it.Next(); err != nil {
d.error(err)
}
}
if i < v.Len() {
if v.Kind() == reflect.Array {
// Array. Zero the rest.
z := reflect.Zero(v.Type().Elem())
for ; i < v.Len(); i++ {
v.Index(i).Set(z)
}
} else {
v.SetLen(i)
}
}
if i == 0 && v.Kind() == reflect.Slice {
v.Set(reflect.MakeSlice(v.Type(), 0, 0))
}
}
// unmarshalObject unmarshals an object slice into given v.
func (d *decodeState) unmarshalObject(data Slice, v reflect.Value) {
// Check for unmarshaler.
u, ju, ut, pv := d.indirect(v, false)
if u != nil {
if err := u.UnmarshalVPack(data); err != nil {
d.error(err)
}
return
}
if ju != nil {
json, err := data.JSONString()
if err != nil {
d.error(err)
} else {
if err := ju.UnmarshalJSON([]byte(json)); err != nil {
d.error(err)
}
}
return
}
if ut != nil {
d.saveError(&UnmarshalTypeError{Value: "object", Type: v.Type()})
return
}
v = pv
// Decoding into nil interface? Switch to non-reflect code.
if v.Kind() == reflect.Interface && v.NumMethod() == 0 {
v.Set(reflect.ValueOf(d.objectInterface(data)))
return
}
// Check type of target:
// struct or
// map[T1]T2 where T1 is string, an integer type,
// or an encoding.TextUnmarshaler
switch v.Kind() {
case reflect.Map:
// Map key must either have string kind, have an integer kind,
// or be an encoding.TextUnmarshaler.
t := v.Type()
switch t.Key().Kind() {
case reflect.String,
reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
default:
if !reflect.PtrTo(t.Key()).Implements(textUnmarshalerType) {
d.saveError(&UnmarshalTypeError{Value: "object", Type: v.Type()})
return
}
}
if v.IsNil() {
v.Set(reflect.MakeMap(t))
}
case reflect.Struct:
// ok
default:
d.saveError(&UnmarshalTypeError{Value: "object", Type: v.Type()})
return
}
var mapElem reflect.Value
it, err := NewObjectIterator(data)
if err != nil {
d.error(err)
}
for it.IsValid() {
key, err := it.Key(true)
if err != nil {
d.error(err)
}
keyUTF8, err := key.GetStringUTF8()
if err != nil {
d.error(err)
}
value, err := it.Value()
if err != nil {
d.error(err)
}
// Figure out field corresponding to key.
var subv reflect.Value
destring := false // whether the value is wrapped in a string to be decoded first
if v.Kind() == reflect.Map {
elemType := v.Type().Elem()
if !mapElem.IsValid() {
mapElem = reflect.New(elemType).Elem()
} else {
mapElem.Set(reflect.Zero(elemType))
}
subv = mapElem
} else {
var f *field
fields := cachedTypeFields(v.Type())
for i := range fields {
ff := &fields[i]
if bytes.Equal(ff.nameBytes, key) {
f = ff
break
}
if f == nil && ff.equalFold(ff.nameBytes, keyUTF8) {
f = ff
}
}
if f != nil {
subv = v
destring = f.quoted
for _, i := range f.index {
if subv.Kind() == reflect.Ptr {
if subv.IsNil() {
subv.Set(reflect.New(subv.Type().Elem()))
}
subv = subv.Elem()
}
subv = subv.Field(i)
}
d.errorContext.Field = f.name
d.errorContext.Struct = v.Type().Name()
}
}
if destring {
// Value should be a string that we'll decode as JSON
valueUTF8, err := value.GetStringUTF8()
if err != nil {
d.saveError(fmt.Errorf("json: invalid use of ,string struct tag, expected string, got %s in %v (%v)", value.Type(), subv.Type(), err))
}
v, err := ParseJSONFromUTF8(valueUTF8)
if err != nil {
d.saveError(err)
} else {
d.unmarshalValue(v, subv)
}
} else {
d.unmarshalValue(value, subv)
}
// Write value back to map;
// if using struct, subv points into struct already.
if v.Kind() == reflect.Map {
kt := v.Type().Key()
var kv reflect.Value
switch {
case kt.Kind() == reflect.String:
kv = reflect.ValueOf(keyUTF8).Convert(kt)
case reflect.PtrTo(kt).Implements(textUnmarshalerType):
kv = reflect.New(v.Type().Key())
d.literalStore(key, kv, true)
kv = kv.Elem()
default:
keyStr := string(keyUTF8)
switch kt.Kind() {
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
n, err := strconv.ParseInt(keyStr, 10, 64)
if err != nil || reflect.Zero(kt).OverflowInt(n) {
d.saveError(&UnmarshalTypeError{Value: "number " + keyStr, Type: kt})
return
}
kv = reflect.ValueOf(n).Convert(kt)
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
n, err := strconv.ParseUint(keyStr, 10, 64)
if err != nil || reflect.Zero(kt).OverflowUint(n) {
d.saveError(&UnmarshalTypeError{Value: "number " + keyStr, Type: kt})
return
}
kv = reflect.ValueOf(n).Convert(kt)
default:
panic("json: Unexpected key type") // should never occur
}
}
v.SetMapIndex(kv, subv)
}
d.errorContext.Struct = ""
d.errorContext.Field = ""
if err := it.Next(); err != nil {
d.error(err)
}
}
}
// unmarshalLiteral unmarshals a literal slice into given v.
func (d *decodeState) unmarshalLiteral(data Slice, v reflect.Value) {
d.literalStore(data, v, false)
}
// The xxxInterface routines build up a value to be stored
// in an empty interface. They are not strictly necessary,
// but they avoid the weight of reflection in this common case.
// valueInterface is like value but returns interface{}
func (d *decodeState) valueInterface(data Slice) interface{} {
switch data.Type() {
case Array:
return d.arrayInterface(data)
case Object:
return d.objectInterface(data)
default:
return d.literalInterface(data)
}
}
// arrayInterface is like array but returns []interface{}.
func (d *decodeState) arrayInterface(data Slice) []interface{} {
l, err := data.Length()
if err != nil {
d.error(err)
}
v := make([]interface{}, 0, l)
it, err := NewArrayIterator(data)
if err != nil {
d.error(err)
}
for it.IsValid() {
value, err := it.Value()
if err != nil {
d.error(err)
}
v = append(v, d.valueInterface(value))
// Move to next field
if err := it.Next(); err != nil {
d.error(err)
}
}
return v
}
// objectInterface is like object but returns map[string]interface{}.
func (d *decodeState) objectInterface(data Slice) map[string]interface{} {
m := make(map[string]interface{})
it, err := NewObjectIterator(data)
if err != nil {
d.error(err)
}
for it.IsValid() {
key, err := it.Key(true)
if err != nil {
d.error(err)
}
keyStr, err := key.GetString()
if err != nil {
d.error(err)
}
value, err := it.Value()
if err != nil {
d.error(err)
}
// Read value.
m[keyStr] = d.valueInterface(value)
// Move to next field
if err := it.Next(); err != nil {
d.error(err)
}
}
return m
}
// literalInterface is like literal but returns an interface value.
func (d *decodeState) literalInterface(data Slice) interface{} {
switch data.Type() {
case Null:
return nil
case Bool:
v, err := data.GetBool()
if err != nil {
d.error(err)
}
return v
case String:
v, err := data.GetString()
if err != nil {
d.error(err)
}
return v
case Double:
v, err := data.GetDouble()
if err != nil {
d.error(err)
}
return v
case Int, SmallInt:
v, err := data.GetInt()
if err != nil {
d.error(err)
}
intV := int(v)
if int64(intV) == v {
// Value fits in int
return intV
}
return v
case UInt:
v, err := data.GetUInt()
if err != nil {
d.error(err)
}
return v
case Binary:
v, err := data.GetBinary()
if err != nil {
d.error(err)
}
return v
default: // ??
d.error(fmt.Errorf("unknown literal type: %s", data.Type()))
return nil
}
}
// literalStore decodes a literal stored in item into v.
//
// fromQuoted indicates whether this literal came from unwrapping a
// string from the ",string" struct tag option. this is used only to
// produce more helpful error messages.
func (d *decodeState) literalStore(item Slice, v reflect.Value, fromQuoted bool) {
// Check for unmarshaler.
if len(item) == 0 {
//Empty string given
d.saveError(fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal empty slice into %v", v.Type()))
return
}
isNull := item.IsNull() // null
u, ju, ut, pv := d.indirect(v, isNull)
if u != nil {
if err := u.UnmarshalVPack(item); err != nil {
d.error(err)
}
return
}
if ju != nil {
json, err := item.JSONString()
if err != nil {
d.error(err)
} else {
if err := ju.UnmarshalJSON([]byte(json)); err != nil {
d.error(err)
}
}
return
}
if ut != nil {
if !item.IsString() {
//if item[0] != '"' {
if fromQuoted {
d.saveError(fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal Slice of type %s into %v", item.Type(), v.Type()))
} else {
val := item.Type().String()
d.saveError(&UnmarshalTypeError{Value: val, Type: v.Type()})
}
return
}
s, err := item.GetStringUTF8()
if err != nil {
if fromQuoted {
d.error(fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal slice of type %s into %v", item.Type(), v.Type()))
} else {
d.error(InternalError) // Out of sync
}
}
if err := ut.UnmarshalText(s); err != nil {
d.error(err)
}
return
}
v = pv
switch item.Type() {
case Null: // null
// The main parser checks that only true and false can reach here,
// but if this was a quoted string input, it could be anything.
if fromQuoted /*&& string(item) != "null"*/ {
d.saveError(fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type()))
break
}
switch v.Kind() {
case reflect.Interface, reflect.Ptr, reflect.Map, reflect.Slice:
v.Set(reflect.Zero(v.Type()))
// otherwise, ignore null for primitives/string
}
case Bool: // true, false
value, err := item.GetBool()
if err != nil {
d.error(err)
}
// The main parser checks that only true and false can reach here,
// but if this was a quoted string input, it could be anything.
if fromQuoted /*&& string(item) != "true" && string(item) != "false"*/ {
d.saveError(fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type()))
break
}
switch v.Kind() {
default:
if fromQuoted {
d.saveError(fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type()))
} else {
d.saveError(&UnmarshalTypeError{Value: "bool", Type: v.Type()})
}
case reflect.Bool:
v.SetBool(value)
case reflect.Interface:
if v.NumMethod() == 0 {
v.Set(reflect.ValueOf(value))
} else {
d.saveError(&UnmarshalTypeError{Value: "bool", Type: v.Type()})
}
}
case String: // string
s, err := item.GetString()
if err != nil {
d.error(err)
}
switch v.Kind() {
default:
d.saveError(&UnmarshalTypeError{Value: "string", Type: v.Type()})
case reflect.Slice:
if v.Type().Elem().Kind() != reflect.Uint8 {
d.saveError(&UnmarshalTypeError{Value: "string", Type: v.Type()})
break
}
b, err := base64.StdEncoding.DecodeString(s)
if err != nil {
d.saveError(err)
break
}
v.SetBytes(b)
case reflect.String:
v.SetString(string(s))
case reflect.Interface:
if v.NumMethod() == 0 {
v.Set(reflect.ValueOf(string(s)))
} else {
d.saveError(&UnmarshalTypeError{Value: "string", Type: v.Type()})
}
}
case Double:
value, err := item.GetDouble()
if err != nil {
d.error(err)
}
switch v.Kind() {
default:
if v.Kind() == reflect.String && v.Type() == numberType {
s, err := item.JSONString()
if err != nil {
d.error(err)
}
v.SetString(s)
break
}
if fromQuoted {
d.error(fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type()))
} else {
d.error(&UnmarshalTypeError{Value: "number", Type: v.Type()})
}
case reflect.Interface:
n, err := d.convertNumber(value)
if err != nil {
d.saveError(err)
break
}
if v.NumMethod() != 0 {
d.saveError(&UnmarshalTypeError{Value: "number", Type: v.Type()})
break
}
v.Set(reflect.ValueOf(n))
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
n := int64(value)
if err != nil || v.OverflowInt(n) {
d.saveError(&UnmarshalTypeError{Value: fmt.Sprintf("number %v", value), Type: v.Type()})
break
}
v.SetInt(n)
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
n := uint64(value)
if err != nil || v.OverflowUint(n) {
d.saveError(&UnmarshalTypeError{Value: fmt.Sprintf("number %v", value), Type: v.Type()})
break
}
v.SetUint(n)
case reflect.Float32, reflect.Float64:
n := value
v.SetFloat(n)
}
case Int, SmallInt:
value, err := item.GetInt()
if err != nil {
d.error(err)
}
switch v.Kind() {
default:
if v.Kind() == reflect.String && v.Type() == numberType {
s, err := item.JSONString()
if err != nil {
d.error(err)
}
v.SetString(s)
break
}
if fromQuoted {
d.error(fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type()))
} else {
d.error(&UnmarshalTypeError{Value: "number", Type: v.Type()})
}
case reflect.Interface:
var n interface{}
intValue := int(value)
if int64(intValue) == value {
// When the value fits in an int, use int type.
n, err = d.convertNumber(intValue)
} else {
n, err = d.convertNumber(value)
}
if err != nil {
d.saveError(err)
break
}
if v.NumMethod() != 0 {
d.saveError(&UnmarshalTypeError{Value: "number", Type: v.Type()})
break
}
v.Set(reflect.ValueOf(n))
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
n := value
if err != nil || v.OverflowInt(n) {
d.saveError(&UnmarshalTypeError{Value: fmt.Sprintf("number %v", value), Type: v.Type()})
break
}
v.SetInt(n)
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
n := uint64(value)
if err != nil || v.OverflowUint(n) {
d.saveError(&UnmarshalTypeError{Value: fmt.Sprintf("number %v", value), Type: v.Type()})
break
}
v.SetUint(n)
case reflect.Float32, reflect.Float64:
n := float64(value)
if err != nil || v.OverflowFloat(n) {
d.saveError(&UnmarshalTypeError{Value: fmt.Sprintf("number %v", value), Type: v.Type()})
break
}
v.SetFloat(n)
}
case UInt:
value, err := item.GetUInt()
if err != nil {
d.error(err)
}
switch v.Kind() {
default:
if v.Kind() == reflect.String && v.Type() == numberType {
s, err := item.JSONString()
if err != nil {
d.error(err)
}
v.SetString(s)
break
}
if fromQuoted {
d.error(fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type()))
} else {
d.error(&UnmarshalTypeError{Value: "number", Type: v.Type()})
}
case reflect.Interface:
n, err := d.convertNumber(value)
if err != nil {
d.saveError(err)
break
}
if v.NumMethod() != 0 {
d.saveError(&UnmarshalTypeError{Value: "number", Type: v.Type()})
break
}
v.Set(reflect.ValueOf(n))
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
n := int64(value)
if err != nil || v.OverflowInt(n) {
d.saveError(&UnmarshalTypeError{Value: fmt.Sprintf("number %v", value), Type: v.Type()})
break
}
v.SetInt(n)
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
n := value
if err != nil || v.OverflowUint(n) {
d.saveError(&UnmarshalTypeError{Value: fmt.Sprintf("number %v", value), Type: v.Type()})
break
}
v.SetUint(n)
case reflect.Float32, reflect.Float64:
n := float64(value)
if err != nil || v.OverflowFloat(n) {
d.saveError(&UnmarshalTypeError{Value: fmt.Sprintf("number %v", value), Type: v.Type()})
break
}
v.SetFloat(n)
}
case Binary:
value, err := item.GetBinary()
if err != nil {
d.error(err)
}
switch v.Kind() {
default:
d.saveError(&UnmarshalTypeError{Value: "string", Type: v.Type()})
case reflect.Slice:
if v.Type().Elem().Kind() != reflect.Uint8 {
d.saveError(&UnmarshalTypeError{Value: "binary", Type: v.Type()})
break
}
v.SetBytes(value)
case reflect.Interface:
if v.NumMethod() == 0 {
v.Set(reflect.ValueOf(value))
} else {
d.saveError(&UnmarshalTypeError{Value: "binary", Type: v.Type()})
}
}
default: // number
d.error(fmt.Errorf("Unknown type %s", item.Type()))
}
}
// convertNumber converts the number literal s to a float64 or a Number
// depending on the setting of d.useNumber.
func (d *decodeState) convertNumber(s interface{}) (interface{}, error) {
if d.useNumber {
return json.Number(fmt.Sprintf("%v", s)), nil
}
return s, nil
}