コード例 #1
0
ファイル: decode.go プロジェクト: kezhuw/toml
func unmarshalInteger(i int64, v reflect.Value) {
	switch v.Kind() {
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		if v.OverflowInt(i) {
			panic(&UnmarshalOverflowError{"integer " + strconv.FormatInt(i, 10), v.Type()})
		}
		v.SetInt(i)
	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
		if i < 0 {
			panic(&UnmarshalOverflowError{"integer " + strconv.FormatInt(i, 10), v.Type()})
		}
		u := uint64(i)
		if v.OverflowUint(u) {
			panic(&UnmarshalOverflowError{"integer " + strconv.FormatUint(u, 10), v.Type()})
		}
		v.SetUint(u)
	case reflect.Interface:
		if v.NumMethod() == 0 {
			v.Set(reflect.ValueOf(i))
			return
		}
		fallthrough
	default:
		panic(&UnmarshalTypeError{"integer " + strconv.FormatInt(i, 10), v.Type()})
	}
}
コード例 #2
0
ファイル: decoder.go プロジェクト: solefaucet/sole-server
func (d *decoder) unmarshalUint(size uint, offset uint, result reflect.Value, uintType uint) (uint, error) {
	if size > uintType/8 {
		return 0, newInvalidDatabaseError("the MaxMind DB file's data section contains bad data (uint%v size of %v)", uintType, size)
	}

	value, newOffset, err := d.decodeUint(size, offset)
	if err != nil {
		return 0, err
	}

	switch result.Kind() {
	default:
		return newOffset, newUnmarshalTypeError(value, result.Type())
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		n := int64(value)
		if result.OverflowInt(n) {
			return 0, newUnmarshalTypeError(value, result.Type())
		}
		result.SetInt(n)
		return newOffset, nil
	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
		if result.OverflowUint(value) {
			return 0, newUnmarshalTypeError(value, result.Type())
		}
		result.SetUint(value)
		return newOffset, nil
	case reflect.Interface:
		result.Set(reflect.ValueOf(value))
		return newOffset, nil
	}
}
コード例 #3
0
ファイル: cbor.go プロジェクト: semantic-machines/veda
func setUint(rv reflect.Value, u uint64) error {
	switch rv.Kind() {
	case reflect.Ptr:
		if rv.IsNil() {
			if rv.CanSet() {
				rv.Set(reflect.New(rv.Type().Elem()))
				// fall through to set indirect below
			} else {
				return fmt.Errorf("trying to put uint into unsettable nil ptr")
			}
		}
		return setUint(reflect.Indirect(rv), u)
	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
		if rv.OverflowUint(u) {
			return fmt.Errorf("value %d does not fit into target of type %s", u, rv.Kind().String())
		}
		rv.SetUint(u)
		return nil
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		if (u == 0xffffffffffffffff) || rv.OverflowInt(int64(u)) {
			return fmt.Errorf("value %d does not fit into target of type %s", u, rv.Kind().String())
		}
		rv.SetInt(int64(u))
		return nil
	case reflect.Interface:
		rv.Set(reflect.ValueOf(u))
		return nil
	default:
		return fmt.Errorf("cannot assign uint into Kind=%s Type=%#v %#v", rv.Kind().String(), rv.Type(), rv)
	}
}
コード例 #4
0
ファイル: decoder.go プロジェクト: TykTechnologies/tyk
func (d *decoder) unmarshalInt32(size uint, offset uint, result reflect.Value) (uint, error) {
	if size > 4 {
		return 0, newInvalidDatabaseError("the MaxMind DB file's data section contains bad data (int32 size of %v)", size)
	}
	value, newOffset, err := d.decodeInt(size, offset)
	if err != nil {
		return 0, err
	}

	switch result.Kind() {
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		n := int64(value)
		if !result.OverflowInt(n) {
			result.SetInt(n)
			return newOffset, nil
		}
	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
		n := uint64(value)
		if !result.OverflowUint(n) {
			result.SetUint(n)
			return newOffset, nil
		}
	case reflect.Interface:
		if result.NumMethod() == 0 {
			result.Set(reflect.ValueOf(value))
			return newOffset, nil
		}
	}
	return newOffset, newUnmarshalTypeError(value, result.Type())
}
コード例 #5
0
ファイル: decode.go プロジェクト: LindenY/gomdise
func numberDecoder(node RMNode, data interface{}, v reflect.Value) {
	val, err := redis.String(data, nil)
	if err != nil {
		panic(err)
	}

	switch v.Kind() {
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		n, err := strconv.ParseInt(val, 10, 64)
		if err != nil || v.OverflowInt(n) {
			panic(fmt.Sprintf("Unable to convert int: %s \n", val))
		}
		v.SetInt(n)

	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
		n, err := strconv.ParseUint(val, 10, 64)
		if err != nil || v.OverflowUint(n) {
			panic(fmt.Sprintf("Unable to convert uint: %s \n", val))
		}
		v.SetUint(n)

	case reflect.Float32, reflect.Float64:
		n, err := strconv.ParseFloat(val, v.Type().Bits())
		if err != nil || v.OverflowFloat(n) {
			panic(fmt.Sprintf("Unable to convert float: %s \n", val))
		}
		v.SetFloat(n)

	default:
		panic(fmt.Sprintf("Unsupported number convertion for type[%v] with value[%v]", v.Type(), data))
	}
}
コード例 #6
0
ファイル: set.go プロジェクト: sunfmin/reflectutils
func setStringValue(v reflect.Value, value string) (err error) {
	s := value

	// if type is []byte
	if v.Kind() == reflect.Slice && v.Type().Elem().Kind() == reflect.Uint8 {
		v.SetBytes([]byte(s))
		return
	}

	switch v.Kind() {
	case reflect.String:
		v.SetString(s)
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		var n int64
		n, err = strconv.ParseInt(s, 10, 64)
		if err != nil {
			return
		}
		if v.OverflowInt(n) {
			err = fmt.Errorf("overflow int64 for %d.", n)
			return
		}
		v.SetInt(n)
	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
		var n uint64
		n, err = strconv.ParseUint(s, 10, 64)
		if err != nil {
			return
		}
		if v.OverflowUint(n) {
			err = fmt.Errorf("overflow uint64 for %d.", n)
			return
		}
		v.SetUint(n)
	case reflect.Float32, reflect.Float64:
		var n float64
		n, err = strconv.ParseFloat(s, v.Type().Bits())
		if err != nil {
			return
		}
		if v.OverflowFloat(n) {
			err = fmt.Errorf("overflow float64 for %d.", n)
			return
		}
		v.SetFloat(n)
	case reflect.Bool:
		var n bool
		n, err = strconv.ParseBool(s)
		if err != nil {
			return
		}
		v.SetBool(n)
	default:
		err = errors.New(fmt.Sprintf("value %+v can only been set to primary type but was %+v", value, v))
	}

	return
}
コード例 #7
0
func (d *Decoder) decodeNumber(n *string, v reflect.Value) error {
	switch v.Kind() {
	case reflect.Interface:
		i, err := d.decodeNumberToInterface(n)
		if err != nil {
			return err
		}
		v.Set(reflect.ValueOf(i))
		return nil
	case reflect.String:
		if v.Type() == numberType { // Support Number value type
			v.Set(reflect.ValueOf(Number(*n)))
			return nil
		}
		v.Set(reflect.ValueOf(*n))
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		i, err := strconv.ParseInt(*n, 10, 64)
		if err != nil {
			return err
		}
		if v.OverflowInt(i) {
			return &UnmarshalTypeError{
				Value: fmt.Sprintf("number overflow, %s", *n),
				Type:  v.Type(),
			}
		}
		v.SetInt(i)
	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
		i, err := strconv.ParseUint(*n, 10, 64)
		if err != nil {
			return err
		}
		if v.OverflowUint(i) {
			return &UnmarshalTypeError{
				Value: fmt.Sprintf("number overflow, %s", *n),
				Type:  v.Type(),
			}
		}
		v.SetUint(i)
	case reflect.Float32, reflect.Float64:
		i, err := strconv.ParseFloat(*n, 64)
		if err != nil {
			return err
		}
		if v.OverflowFloat(i) {
			return &UnmarshalTypeError{
				Value: fmt.Sprintf("number overflow, %s", *n),
				Type:  v.Type(),
			}
		}
		v.SetFloat(i)
	default:
		return &UnmarshalTypeError{Value: "number", Type: v.Type()}
	}

	return nil
}
コード例 #8
0
ファイル: option.go プロジェクト: drewwells/writ
func decodeUint(rval reflect.Value, arg string) error {
	v, err := strconv.ParseUint(arg, 10, 64)
	if err != nil {
		return err
	}
	if rval.OverflowUint(v) {
		return fmt.Errorf("value %d would overflow %s", v, rval.Kind())
	}
	rval.Set(reflect.ValueOf(v).Convert(rval.Type()))
	return nil
}
コード例 #9
0
ファイル: hack.go プロジェクト: btbxbob/wechat
func unmarshalStringToNumberOrBoolean(d *decodeState, s []byte, v reflect.Value, fromQuoted bool) {
	if fromQuoted {
		d.saveError(&UnmarshalTypeError{"string", v.Type(), int64(d.off)})
		return
	}
	switch {
	default:
		d.saveError(&UnmarshalTypeError{"string", v.Type(), int64(d.off)})
	case isValidNumberBytes(s):
		switch v.Kind() {
		default:
			d.saveError(&UnmarshalTypeError{"string", v.Type(), int64(d.off)})
		case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
			s := string(s)
			n, err := strconv.ParseInt(s, 10, 64)
			if err != nil || v.OverflowInt(n) {
				d.saveError(&UnmarshalTypeError{"string " + s, v.Type(), int64(d.off)})
				break
			}
			v.SetInt(n)
		case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
			s := string(s)
			n, err := strconv.ParseUint(s, 10, 64)
			if err != nil || v.OverflowUint(n) {
				d.saveError(&UnmarshalTypeError{"string " + s, v.Type(), int64(d.off)})
				break
			}
			v.SetUint(n)
		case reflect.Float32, reflect.Float64:
			s := string(s)
			n, err := strconv.ParseFloat(s, v.Type().Bits())
			if err != nil || v.OverflowFloat(n) {
				d.saveError(&UnmarshalTypeError{"string " + s, v.Type(), int64(d.off)})
				break
			}
			v.SetFloat(n)
		}
	case bytes.Equal(s, trueLiteral):
		switch v.Kind() {
		default:
			d.saveError(&UnmarshalTypeError{"string", v.Type(), int64(d.off)})
		case reflect.Bool:
			v.SetBool(true)
		}
	case bytes.Equal(s, falseLiteral):
		switch v.Kind() {
		default:
			d.saveError(&UnmarshalTypeError{"string", v.Type(), int64(d.off)})
		case reflect.Bool:
			v.SetBool(false)
		}
	}
}
コード例 #10
0
ファイル: resolver.go プロジェクト: khwang1/candiedyaml
func resolve_uint(val string, v reflect.Value) error {
	val = strings.Replace(val, "_", "", -1)
	var value uint64

	if val[0] == '-' {
		return errors.New("Unsigned int with negative value: " + val)
	}

	if val[0] == '+' {
		val = val[1:]
	}

	base := 10
	if val == "0" {
		v.Set(reflect.Zero(v.Type()))
		return nil
	}

	if strings.HasPrefix(val, "0b") {
		base = 2
		val = val[2:]
	} else if strings.HasPrefix(val, "0x") {
		base = 16
		val = val[2:]
	} else if val[0] == '0' {
		base = 8
		val = val[1:]
	} else if strings.Contains(val, ":") {
		digits := strings.Split(val, ":")
		bes := uint64(1)
		for j := len(digits) - 1; j >= 0; j-- {
			n, err := strconv.ParseUint(digits[j], 10, 64)
			n *= bes
			if err != nil || v.OverflowUint(n) {
				return errors.New("Unsigned Integer: " + val)
			}
			value += n
			bes *= 60
		}

		v.SetUint(value)
		return nil
	}

	value, err := strconv.ParseUint(val, base, 64)
	if err != nil || v.OverflowUint(value) {
		return errors.New("Unsigned Integer: " + val)
	}

	v.SetUint(value)
	return nil
}
コード例 #11
0
ファイル: resolver.go プロジェクト: ChristianKniep/swarmkit
func resolve_uint(val string, v reflect.Value, useNumber bool, event yaml_event_t) (string, error) {
	original := val
	val = strings.Replace(val, "_", "", -1)
	var value uint64

	isNumberValue := v.Type() == numberType

	if val[0] == '-' {
		return "", fmt.Errorf("Unsigned int with negative value: '%s' at %s", original, event.start_mark)
	}

	if val[0] == '+' {
		val = val[1:]
	}

	base := 0
	if val == "0" {
		if isNumberValue {
			v.SetString("0")
		} else {
			v.Set(reflect.Zero(v.Type()))
		}

		return yaml_INT_TAG, nil
	}

	if strings.HasPrefix(val, "0o") {
		base = 8
		val = val[2:]
	}

	value, err := strconv.ParseUint(val, base, 64)
	if err != nil {
		return "", fmt.Errorf("Invalid unsigned integer: '%s' at %s", val, event.start_mark)
	}

	if isNumberValue {
		v.SetString(strconv.FormatUint(value, 10))
	} else {
		if v.OverflowUint(value) {
			return "", fmt.Errorf("Invalid unsigned integer: '%s' at %s", val, event.start_mark)
		}

		v.SetUint(value)
	}

	return yaml_INT_TAG, nil
}
コード例 #12
0
ファイル: decode.go プロジェクト: nsf/libtorgo
// called when 'i' was consumed
func (d *decoder) parse_int(v reflect.Value) {
	start := d.offset - 1
	d.read_until('e')
	if d.buf.Len() == 0 {
		panic(&SyntaxError{
			Offset: start,
			what:   "empty integer value",
		})
	}

	switch v.Kind() {
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		n, err := strconv.ParseInt(d.buf.String(), 10, 64)
		check_for_int_parse_error(err, start)

		if v.OverflowInt(n) {
			panic(&UnmarshalTypeError{
				Value: "integer " + d.buf.String(),
				Type:  v.Type(),
			})
		}
		v.SetInt(n)
	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
		n, err := strconv.ParseUint(d.buf.String(), 10, 64)
		check_for_int_parse_error(err, start)

		if v.OverflowUint(n) {
			panic(&UnmarshalTypeError{
				Value: "integer " + d.buf.String(),
				Type:  v.Type(),
			})
		}
		v.SetUint(n)
	case reflect.Bool:
		if d.buf.Len() == 1 && d.buf.Bytes()[0] == '0' {
			v.SetBool(false)
		}
		v.SetBool(true)
	default:
		panic(&UnmarshalTypeError{
			Value: "integer " + d.buf.String(),
			Type:  v.Type(),
		})
	}
	d.buf.Reset()
}
コード例 #13
0
ファイル: decode.go プロジェクト: CaptainIlu/cloud-torrent
// called when 'i' was consumed
func (d *decoder) parse_int(v reflect.Value) {
	start := d.offset - 1
	d.read_until('e')
	if d.buf.Len() == 0 {
		panic(&SyntaxError{
			Offset: start,
			What:   errors.New("empty integer value"),
		})
	}

	s := d.buf.String()

	switch v.Kind() {
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		n, err := strconv.ParseInt(s, 10, 64)
		check_for_int_parse_error(err, start)

		if v.OverflowInt(n) {
			panic(&UnmarshalTypeError{
				Value: "integer " + s,
				Type:  v.Type(),
			})
		}
		v.SetInt(n)
	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
		n, err := strconv.ParseUint(s, 10, 64)
		check_for_int_parse_error(err, start)

		if v.OverflowUint(n) {
			panic(&UnmarshalTypeError{
				Value: "integer " + s,
				Type:  v.Type(),
			})
		}
		v.SetUint(n)
	case reflect.Bool:
		v.SetBool(s != "0")
	default:
		panic(&UnmarshalTypeError{
			Value: "integer " + s,
			Type:  v.Type(),
		})
	}
	d.buf.Reset()
}
コード例 #14
0
ファイル: decode.go プロジェクト: egonelbre/spexs2
func (d *decodeState) numberStore(item []byte, v reflect.Value, fromQuoted bool) {
	s := string(item)
	switch v.Kind() {
	default:
		if v.Kind() == reflect.String && v.Type() == numberType {
			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()))
		}
		d.error(&UnmarshalTypeError{"number", v.Type()})
	case reflect.Interface:
		n, err := d.convertNumber(string(item))
		if err != nil {
			d.saveError(err)
			break
		}
		v.Set(reflect.ValueOf(n))

	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		n, err := strconv.ParseInt(s, 10, 64)
		if err != nil || v.OverflowInt(n) {
			d.saveError(&UnmarshalTypeError{"number " + s, v.Type()})
			break
		}
		v.SetInt(n)

	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
		n, err := strconv.ParseUint(s, 10, 64)
		if err != nil || v.OverflowUint(n) {
			d.saveError(&UnmarshalTypeError{"number " + s, v.Type()})
			break
		}
		v.SetUint(n)

	case reflect.Float32, reflect.Float64:
		n, err := strconv.ParseFloat(s, v.Type().Bits())
		if err != nil || v.OverflowFloat(n) {
			d.saveError(&UnmarshalTypeError{"number " + s, v.Type()})
			break
		}
		v.SetFloat(n)
	}
}
コード例 #15
0
ファイル: decode.go プロジェクト: zackbloom/go-ini
// Set Value with given string
func (d *decodeState) setValue(v reflect.Value, s string) {
	//fmt.Printf("SET(kind:%s, %s)\n", v.Kind(), s)

	switch v.Kind() {

	case reflect.String:
		v.SetString(s)

	case reflect.Bool:
		v.SetBool(boolValue(s))

	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		n, err := strconv.ParseInt(s, 10, 64)
		if err != nil || v.OverflowInt(n) {
			d.saveError(&IniError{d.lineNum, d.line, "Invalid int"})
			return
		}
		v.SetInt(n)

	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
		n, err := strconv.ParseUint(s, 10, 64)
		if err != nil || v.OverflowUint(n) {
			d.saveError(&IniError{d.lineNum, d.line, "Invalid uint"})
			return
		}
		v.SetUint(n)

	case reflect.Float32, reflect.Float64:
		n, err := strconv.ParseFloat(s, v.Type().Bits())
		if err != nil || v.OverflowFloat(n) {
			d.saveError(&IniError{d.lineNum, d.line, "Invalid float"})
			return
		}
		v.SetFloat(n)

	case reflect.Slice:
		d.sliceValue(v, s)

	default:
		d.saveError(&IniError{d.lineNum, d.line, fmt.Sprintf("Can't set value of type %s", v.Kind())})
	}

}
コード例 #16
0
ファイル: bson_decode.go プロジェクト: teopeurt/go-mongo
func decodeUint(d *decodeState, kind int, v reflect.Value) {
	var n uint64
	switch kind {
	default:
		d.saveErrorAndSkip(kind, v.Type())
		return
	case kindInt64, kindTimestamp, kindDateTime:
		n = uint64(d.scanInt64())
	case kindInt32:
		n = uint64(d.scanInt32())
	case kindFloat:
		n = uint64(d.scanFloat())
	}
	if v.OverflowUint(n) {
		d.saveError(&DecodeConvertError{kind, v.Type()})
		return
	}
	v.SetUint(n)
}
コード例 #17
0
ファイル: decode.go プロジェクト: kezhuw/toml
func unmarshalQuoted(s string, v reflect.Value) {
	switch v.Kind() {
	case reflect.Bool:
		b, err := strconv.ParseBool(s)
		if err != nil {
			panic(err)
		}
		v.SetBool(b)
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		i, err := strconv.ParseInt(s, 10, 64)
		if err != nil {
			panic(err)
		}
		if v.OverflowInt(i) {
			goto overflowError
		}
		v.SetInt(i)
	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
		u, err := strconv.ParseUint(s, 10, 64)
		if err != nil {
			panic(err)
		}
		if v.OverflowUint(u) {
			goto overflowError
		}
		v.SetUint(u)
	case reflect.Float32, reflect.Float64:
		f, err := strconv.ParseFloat(s, 64)
		if err != nil {
			panic(err)
		}
		if v.OverflowFloat(f) {
			goto overflowError
		}
		v.SetFloat(f)
	default:
		panic("toml: unexpected type for quoted string")
	}
	return
overflowError:
	panic(&UnmarshalOverflowError{"string " + strconv.Quote(s), v.Type()})
}
コード例 #18
0
ファイル: cbor.go プロジェクト: jbenet/go-cbor-incomplete
func setUint(rv reflect.Value, u uint64) error {
	switch rv.Kind() {
	case reflect.Ptr:
		return setUint(reflect.Indirect(rv), u)
	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
		if rv.OverflowUint(u) {
			return fmt.Errorf("value %d does not fit into target of type %s", u, rv.Kind().String())
		}
		rv.SetUint(u)
		return nil
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		if (u == 0xffffffffffffffff) || rv.OverflowInt(int64(u)) {
			return fmt.Errorf("value %d does not fit into target of type %s", u, rv.Kind().String())
		}
		rv.SetInt(int64(u))
		return nil
	case reflect.Interface:
		rv.Set(reflect.ValueOf(u))
		return nil
	default:
		return fmt.Errorf("cannot assign uint into Kind=%s Type=%#v %#v", rv.Kind().String(), rv.Type(), rv)
	}
}
コード例 #19
0
ファイル: decode.go プロジェクト: alfatraining/json5
// 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 []byte, 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 %q into %v", item, v.Type()))
		return
	}
	wantptr := item[0] == 'n' // null
	u, ut, pv := d.indirect(v, wantptr)
	if u != nil {
		err := u.UnmarshalJSON(item)
		if err != nil {
			d.error(err)
		}
		return
	}
	if ut != nil {
		if item[0] != '"' {
			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{"string", v.Type()})
			}
		}
		s, ok := unquoteBytes(item)
		if !ok {
			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(errPhase)
			}
		}
		err := ut.UnmarshalText(s)
		if err != nil {
			d.error(err)
		}
		return
	}

	v = pv

	switch c := item[0]; c {
	case 'n': // null
		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 't', 'f': // true, false
		value := c == 't'
		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{"bool", v.Type()})
			}
		case reflect.Bool:
			v.SetBool(value)
		case reflect.Interface:
			if v.NumMethod() == 0 {
				v.Set(reflect.ValueOf(value))
			} else {
				d.saveError(&UnmarshalTypeError{"bool", v.Type()})
			}
		}

	case '"': // string
		s, ok := unquoteBytes(item)
		if !ok {
			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(errPhase)
			}
		}
		switch v.Kind() {
		default:
			d.saveError(&UnmarshalTypeError{"string", v.Type()})
		case reflect.Slice:
			if v.Type() != byteSliceType {
				d.saveError(&UnmarshalTypeError{"string", v.Type()})
				break
			}
			b := make([]byte, base64.StdEncoding.DecodedLen(len(s)))
			n, err := base64.StdEncoding.Decode(b, s)
			if err != nil {
				d.saveError(err)
				break
			}
			v.Set(reflect.ValueOf(b[0:n]))
		case reflect.String:
			v.SetString(string(s))
		case reflect.Interface:
			if v.NumMethod() == 0 {
				v.Set(reflect.ValueOf(string(s)))
			} else {
				d.saveError(&UnmarshalTypeError{"string", v.Type()})
			}
		}

	default: // number
		if c != '-' && (c < '0' || c > '9') {
			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(errPhase)
			}
		}
		s := string(item)
		switch v.Kind() {
		default:
			if v.Kind() == reflect.String && v.Type() == numberType {
				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{"number", v.Type()})
			}
		case reflect.Interface:
			n, err := d.convertNumber(s)
			if err != nil {
				d.saveError(err)
				break
			}
			if v.NumMethod() != 0 {
				d.saveError(&UnmarshalTypeError{"number", v.Type()})
				break
			}
			v.Set(reflect.ValueOf(n))

		case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
			n, err := strconv.ParseInt(s, 10, 64)
			if err != nil || v.OverflowInt(n) {
				d.saveError(&UnmarshalTypeError{"number " + s, v.Type()})
				break
			}
			v.SetInt(n)

		case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
			n, err := strconv.ParseUint(s, 10, 64)
			if err != nil || v.OverflowUint(n) {
				d.saveError(&UnmarshalTypeError{"number " + s, v.Type()})
				break
			}
			v.SetUint(n)

		case reflect.Float32, reflect.Float64:
			n, err := strconv.ParseFloat(s, v.Type().Bits())
			if err != nil || v.OverflowFloat(n) {
				d.saveError(&UnmarshalTypeError{"number " + s, v.Type()})
				break
			}
			v.SetFloat(n)
		}
	}
}
コード例 #20
0
ファイル: pls_impl.go プロジェクト: tetrafolium/gae
func loadInner(codec *structCodec, structValue reflect.Value, index int, name string, p Property, requireSlice bool) string {
	var v reflect.Value
	// Traverse a struct's struct-typed fields.
	for {
		fieldIndex, ok := codec.byName[name]
		if !ok {
			return "no such struct field"
		}
		v = structValue.Field(fieldIndex)

		st := codec.byIndex[fieldIndex]
		if st.substructCodec == nil {
			break
		}

		if v.Kind() == reflect.Slice {
			for v.Len() <= index {
				v.Set(reflect.Append(v, reflect.New(v.Type().Elem()).Elem()))
			}
			structValue = v.Index(index)
			requireSlice = false
		} else {
			structValue = v
		}
		// Strip the "I." from "I.X".
		name = name[len(st.name):]
		codec = st.substructCodec
	}

	doConversion := func(v reflect.Value) (string, bool) {
		a := v.Addr()
		if conv, ok := a.Interface().(PropertyConverter); ok {
			err := conv.FromProperty(p)
			if err != nil {
				return err.Error(), true
			}
			return "", true
		}
		return "", false
	}

	if ret, ok := doConversion(v); ok {
		return ret
	}

	var slice reflect.Value
	if v.Kind() == reflect.Slice && v.Type().Elem().Kind() != reflect.Uint8 {
		slice = v
		v = reflect.New(v.Type().Elem()).Elem()
	} else if requireSlice {
		return "multiple-valued property requires a slice field type"
	}

	if ret, ok := doConversion(v); ok {
		if ret != "" {
			return ret
		}
	} else {
		knd := v.Kind()

		project := PTNull
		overflow := (func(interface{}) bool)(nil)
		set := (func(interface{}))(nil)

		switch knd {
		case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
			project = PTInt
			overflow = func(x interface{}) bool { return v.OverflowInt(x.(int64)) }
			set = func(x interface{}) { v.SetInt(x.(int64)) }
		case reflect.Uint8, reflect.Uint16, reflect.Uint32:
			project = PTInt
			overflow = func(x interface{}) bool {
				xi := x.(int64)
				return xi < 0 || v.OverflowUint(uint64(xi))
			}
			set = func(x interface{}) { v.SetUint(uint64(x.(int64))) }
		case reflect.Bool:
			project = PTBool
			set = func(x interface{}) { v.SetBool(x.(bool)) }
		case reflect.String:
			project = PTString
			set = func(x interface{}) { v.SetString(x.(string)) }
		case reflect.Float32, reflect.Float64:
			project = PTFloat
			overflow = func(x interface{}) bool { return v.OverflowFloat(x.(float64)) }
			set = func(x interface{}) { v.SetFloat(x.(float64)) }
		case reflect.Ptr:
			project = PTKey
			set = func(x interface{}) {
				if k, ok := x.(*Key); ok {
					v.Set(reflect.ValueOf(k))
				}
			}
		case reflect.Struct:
			switch v.Type() {
			case typeOfTime:
				project = PTTime
				set = func(x interface{}) { v.Set(reflect.ValueOf(x)) }
			case typeOfGeoPoint:
				project = PTGeoPoint
				set = func(x interface{}) { v.Set(reflect.ValueOf(x)) }
			default:
				panic(fmt.Errorf("helper: impossible: %s", typeMismatchReason(p.Value(), v)))
			}
		case reflect.Slice:
			project = PTBytes
			set = func(x interface{}) {
				v.SetBytes(reflect.ValueOf(x).Bytes())
			}
		default:
			panic(fmt.Errorf("helper: impossible: %s", typeMismatchReason(p.Value(), v)))
		}

		pVal, err := p.Project(project)
		if err != nil {
			return typeMismatchReason(p.Value(), v)
		}
		if overflow != nil && overflow(pVal) {
			return fmt.Sprintf("value %v overflows struct field of type %v", pVal, v.Type())
		}
		set(pVal)
	}
	if slice.IsValid() {
		slice.Set(reflect.Append(slice, v))
	}
	return ""
}
コード例 #21
0
ファイル: decode.go プロジェクト: danprince/yaml
func (d *decoder) scalar(n *node, out reflect.Value) (good bool) {
	var tag string
	var resolved interface{}
	if n.tag == "" && !n.implicit {
		tag = yaml_STR_TAG
		resolved = n.value
	} else {
		tag, resolved = resolve(n.tag, n.value)
		if tag == yaml_BINARY_TAG {
			data, err := base64.StdEncoding.DecodeString(resolved.(string))
			if err != nil {
				failf("!!binary value contains invalid base64 data")
			}
			resolved = string(data)
		}
	}
	if resolved == nil {
		if out.Kind() == reflect.Map && !out.CanAddr() {
			resetMap(out)
		} else {
			out.Set(reflect.Zero(out.Type()))
		}
		return true
	}
	if s, ok := resolved.(string); ok && out.CanAddr() {
		if u, ok := out.Addr().Interface().(encoding.TextUnmarshaler); ok {
			err := u.UnmarshalText([]byte(s))
			if err != nil {
				fail(err)
			}
			return true
		}
	}
	switch out.Kind() {
	case reflect.String:
		if tag == yaml_BINARY_TAG {
			out.SetString(resolved.(string))
			good = true
		} else if resolved != nil {
			out.SetString(n.value)
			good = true
		}
	case reflect.Interface:
		if resolved == nil {
			out.Set(reflect.Zero(out.Type()))
		} else {
			out.Set(reflect.ValueOf(resolved))
		}
		good = true
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		switch resolved := resolved.(type) {
		case int:
			if !out.OverflowInt(int64(resolved)) {
				out.SetInt(int64(resolved))
				good = true
			}
		case int64:
			if !out.OverflowInt(resolved) {
				out.SetInt(resolved)
				good = true
			}
		case uint64:
			if resolved <= math.MaxInt64 && !out.OverflowInt(int64(resolved)) {
				out.SetInt(int64(resolved))
				good = true
			}
		case float64:
			if resolved <= math.MaxInt64 && !out.OverflowInt(int64(resolved)) {
				out.SetInt(int64(resolved))
				good = true
			}
		case string:
			if out.Type() == durationType {
				d, err := time.ParseDuration(resolved)
				if err == nil {
					out.SetInt(int64(d))
					good = true
				}
			}
		}
	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
		switch resolved := resolved.(type) {
		case int:
			if resolved >= 0 && !out.OverflowUint(uint64(resolved)) {
				out.SetUint(uint64(resolved))
				good = true
			}
		case int64:
			if resolved >= 0 && !out.OverflowUint(uint64(resolved)) {
				out.SetUint(uint64(resolved))
				good = true
			}
		case uint64:
			if !out.OverflowUint(uint64(resolved)) {
				out.SetUint(uint64(resolved))
				good = true
			}
		case float64:
			if resolved <= math.MaxUint64 && !out.OverflowUint(uint64(resolved)) {
				out.SetUint(uint64(resolved))
				good = true
			}
		}
	case reflect.Bool:
		switch resolved := resolved.(type) {
		case bool:
			out.SetBool(resolved)
			good = true
		}
	case reflect.Float32, reflect.Float64:
		switch resolved := resolved.(type) {
		case int:
			out.SetFloat(float64(resolved))
			good = true
		case int64:
			out.SetFloat(float64(resolved))
			good = true
		case uint64:
			out.SetFloat(float64(resolved))
			good = true
		case float64:
			out.SetFloat(resolved)
			good = true
		}
	case reflect.Ptr:
		if out.Type().Elem() == reflect.TypeOf(resolved) {
			// TODO DOes this make sense? When is out a Ptr except when decoding a nil value?
			elem := reflect.New(out.Type().Elem())
			elem.Elem().Set(reflect.ValueOf(resolved))
			out.Set(elem)
			good = true
		}
	}
	if !good {
		d.terror(n, tag, out)
	}
	return good
}
コード例 #22
0
ファイル: decode.go プロジェクト: cesanta/ubjson
// literalStore decodes a literal stored in item into v.
func (d *decodeState) literal(v reflect.Value, op int) {
	// Check for unmarshaler.
	wantptr := op == scanNull // null
	u, ut, pv := d.indirect(v, wantptr)
	if u != nil {
		d.off--
		d.scan.undo(op)
		b := d.next()
		if err := u.UnmarshalUBJSON(b); err != nil {
			d.error(err)
		}
		return
	}
	if ut != nil {
		if op != scanString {
			d.saveError(&UnmarshalTypeError{"string", v.Type(), int64(d.off)})
			return
		}
		s, err := d.scanString()
		if err != nil {
			glog.V(3).Infof("invalid string: %s", err)
			d.error(errPhase)
		}
		err = ut.UnmarshalText([]byte(s))
		if err != nil {
			d.error(err)
		}
		return
	}

	v = pv

	switch op {
	default:
		d.saveError(&UnmarshalTypeError{scanToName[op], v.Type(), int64(d.off)})
	case scanNull:
		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 scanTrue, scanFalse:
		value := op == scanTrue
		switch v.Kind() {
		default:
			d.saveError(&UnmarshalTypeError{"bool", v.Type(), int64(d.off)})
		case reflect.Bool:
			v.SetBool(value)
		case reflect.Interface:
			if v.NumMethod() == 0 {
				v.Set(reflect.ValueOf(value))
			} else {
				d.saveError(&UnmarshalTypeError{"bool", v.Type(), int64(d.off)})
			}
		}

	case scanString:
		s, err := d.scanString()
		if err != nil {
			glog.V(3).Infof("invalid string: %s", err)
			d.error(errPhase)
		}
		switch v.Kind() {
		default:
			d.saveError(&UnmarshalTypeError{"string", v.Type(), int64(d.off)})
		case reflect.Slice:
			if v.Type().Elem().Kind() != reflect.Uint8 {
				d.saveError(&UnmarshalTypeError{"string", v.Type(), int64(d.off)})
				break
			}
			b := []byte(s)
			v.Set(reflect.ValueOf(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{"string", v.Type(), int64(d.off)})
			}
		}

	case scanInt8, scanUint8, scanInt16, scanInt32, scanInt64:
		n, err := d.scanInt(op)
		if err != nil {
			d.error(err)
			break
		}
		switch v.Kind() {
		default:
			d.error(&UnmarshalTypeError{"number", v.Type(), int64(d.off)})
		case reflect.Interface:
			if v.NumMethod() != 0 {
				d.saveError(&UnmarshalTypeError{"number", v.Type(), int64(d.off)})
				break
			}
			v.Set(reflect.ValueOf(n))

		case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
			if v.OverflowInt(n) {
				d.saveError(&UnmarshalTypeError{"number", v.Type(), int64(d.off)})
				break
			}
			v.SetInt(n)

		case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
			if v.OverflowUint(uint64(n)) {
				d.saveError(&UnmarshalTypeError{"number ", v.Type(), int64(d.off)})
				break
			}
			v.SetUint(uint64(n))
		case reflect.Float32, reflect.Float64:
			if v.OverflowFloat(float64(n)) {
				d.saveError(&UnmarshalTypeError{"number ", v.Type(), int64(d.off)})
				break
			}
			v.SetFloat(float64(n))
		}
	case scanFloat32:
		b, err := d.scanPayload()
		if err != nil {
			d.error(err)
			return
		}
		var n float32
		if err := binary.Read(bytes.NewBuffer(b), binary.BigEndian, &n); err != nil {
			d.error(err)
			return
		}
		switch v.Kind() {
		default:
			d.error(&UnmarshalTypeError{"number", v.Type(), int64(d.off)})
		case reflect.Interface:
			if v.NumMethod() != 0 {
				d.saveError(&UnmarshalTypeError{"number", v.Type(), int64(d.off)})
				break
			}
			v.Set(reflect.ValueOf(n))

		case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
			if v.OverflowInt(int64(n)) {
				d.saveError(&UnmarshalTypeError{"number", v.Type(), int64(d.off)})
				break
			}
			v.SetInt(int64(n))

		case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
			if v.OverflowUint(uint64(n)) {
				d.saveError(&UnmarshalTypeError{"number ", v.Type(), int64(d.off)})
				break
			}
			v.SetUint(uint64(n))
		case reflect.Float32, reflect.Float64:
			if v.OverflowFloat(float64(n)) {
				d.saveError(&UnmarshalTypeError{"number ", v.Type(), int64(d.off)})
				break
			}
			v.SetFloat(float64(n))
		}
	case scanFloat64:
		b, err := d.scanPayload()
		if err != nil {
			d.error(err)
			return
		}
		var n float64
		if err := binary.Read(bytes.NewBuffer(b), binary.BigEndian, &n); err != nil {
			d.error(err)
			return
		}
		switch v.Kind() {
		default:
			d.error(&UnmarshalTypeError{"number", v.Type(), int64(d.off)})
		case reflect.Interface:
			if v.NumMethod() != 0 {
				d.saveError(&UnmarshalTypeError{"number", v.Type(), int64(d.off)})
				break
			}
			v.Set(reflect.ValueOf(n))

		case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
			if v.OverflowInt(int64(n)) {
				d.saveError(&UnmarshalTypeError{"number", v.Type(), int64(d.off)})
				break
			}
			v.SetInt(int64(n))

		case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
			if v.OverflowUint(uint64(n)) {
				d.saveError(&UnmarshalTypeError{"number ", v.Type(), int64(d.off)})
				break
			}
			v.SetUint(uint64(n))
		case reflect.Float32, reflect.Float64:
			if v.OverflowFloat(n) {
				d.saveError(&UnmarshalTypeError{"number ", v.Type(), int64(d.off)})
				break
			}
			v.SetFloat(n)
		}
	}
}
コード例 #23
0
ファイル: decode.go プロジェクト: Christeefym/lantern
func (d *decoder) scalar(n *node, out reflect.Value) (good bool) {
	var tag string
	var resolved interface{}
	if n.tag == "" && !n.implicit {
		tag = "!!str"
		resolved = n.value
	} else {
		tag, resolved = resolve(n.tag, n.value)
	}
	if set := d.setter(tag, &out, &good); set != nil {
		defer set()
	}
	switch out.Kind() {
	case reflect.String:
		if resolved != nil {
			out.SetString(n.value)
			good = true
		}
	case reflect.Interface:
		if resolved == nil {
			out.Set(reflect.Zero(out.Type()))
		} else {
			out.Set(reflect.ValueOf(resolved))
		}
		good = true
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		switch resolved := resolved.(type) {
		case int:
			if !out.OverflowInt(int64(resolved)) {
				out.SetInt(int64(resolved))
				good = true
			}
		case int64:
			if !out.OverflowInt(resolved) {
				out.SetInt(resolved)
				good = true
			}
		case float64:
			if resolved < 1<<63-1 && !out.OverflowInt(int64(resolved)) {
				out.SetInt(int64(resolved))
				good = true
			}
		case string:
			if out.Type() == durationType {
				d, err := time.ParseDuration(resolved)
				if err == nil {
					out.SetInt(int64(d))
					good = true
				}
			}
		}
	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
		switch resolved := resolved.(type) {
		case int:
			if resolved >= 0 {
				out.SetUint(uint64(resolved))
				good = true
			}
		case int64:
			if resolved >= 0 {
				out.SetUint(uint64(resolved))
				good = true
			}
		case float64:
			if resolved < 1<<64-1 && !out.OverflowUint(uint64(resolved)) {
				out.SetUint(uint64(resolved))
				good = true
			}
		}
	case reflect.Bool:
		switch resolved := resolved.(type) {
		case bool:
			out.SetBool(resolved)
			good = true
		}
	case reflect.Float32, reflect.Float64:
		switch resolved := resolved.(type) {
		case int:
			out.SetFloat(float64(resolved))
			good = true
		case int64:
			out.SetFloat(float64(resolved))
			good = true
		case float64:
			out.SetFloat(resolved)
			good = true
		}
	case reflect.Ptr:
		switch resolved.(type) {
		case nil:
			out.Set(reflect.Zero(out.Type()))
			good = true
		default:
			if out.Type().Elem() == reflect.TypeOf(resolved) {
				elem := reflect.New(out.Type().Elem())
				elem.Elem().Set(reflect.ValueOf(resolved))
				out.Set(elem)
				good = true
			}
		}
	}
	return good
}
コード例 #24
0
ファイル: decode.go プロジェクト: achanda/go
// 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 []byte, 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 %q into %v", item, v.Type()))
		return
	}
	isNull := item[0] == 'n' // null
	u, ut, pv := d.indirect(v, isNull)
	if u != nil {
		err := u.UnmarshalJSON(item)
		if err != nil {
			d.error(err)
		}
		return
	}
	if ut != nil {
		if item[0] != '"' {
			if fromQuoted {
				d.saveError(fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type()))
			} else {
				var val string
				switch item[0] {
				case 'n':
					val = "null"
				case 't', 'f':
					val = "bool"
				default:
					val = "number"
				}
				d.saveError(&UnmarshalTypeError{Value: val, Type: v.Type(), Offset: int64(d.off)})
			}
			return
		}
		s, ok := unquoteBytes(item)
		if !ok {
			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(errPhase)
			}
		}
		err := ut.UnmarshalText(s)
		if err != nil {
			d.error(err)
		}
		return
	}

	v = pv

	switch c := item[0]; c {
	case 'n': // 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 't', 'f': // true, false
		value := item[0] == 't'
		// 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(), Offset: int64(d.off)})
			}
		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(), Offset: int64(d.off)})
			}
		}

	case '"': // string
		s, ok := unquoteBytes(item)
		if !ok {
			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(errPhase)
			}
		}
		switch v.Kind() {
		default:
			d.saveError(&UnmarshalTypeError{Value: "string", Type: v.Type(), Offset: int64(d.off)})
		case reflect.Slice:
			if v.Type().Elem().Kind() != reflect.Uint8 {
				d.saveError(&UnmarshalTypeError{Value: "string", Type: v.Type(), Offset: int64(d.off)})
				break
			}
			b := make([]byte, base64.StdEncoding.DecodedLen(len(s)))
			n, err := base64.StdEncoding.Decode(b, s)
			if err != nil {
				d.saveError(err)
				break
			}
			v.SetBytes(b[:n])
		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(), Offset: int64(d.off)})
			}
		}

	default: // number
		if c != '-' && (c < '0' || c > '9') {
			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(errPhase)
			}
		}
		s := string(item)
		switch v.Kind() {
		default:
			if v.Kind() == reflect.String && v.Type() == numberType {
				v.SetString(s)
				if !isValidNumber(s) {
					d.error(fmt.Errorf("json: invalid number literal, trying to unmarshal %q into Number", item))
				}
				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(), Offset: int64(d.off)})
			}
		case reflect.Interface:
			n, err := d.convertNumber(s)
			if err != nil {
				d.saveError(err)
				break
			}
			if v.NumMethod() != 0 {
				d.saveError(&UnmarshalTypeError{Value: "number", Type: v.Type(), Offset: int64(d.off)})
				break
			}
			v.Set(reflect.ValueOf(n))

		case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
			n, err := strconv.ParseInt(s, 10, 64)
			if err != nil || v.OverflowInt(n) {
				d.saveError(&UnmarshalTypeError{Value: "number " + s, Type: v.Type(), Offset: int64(d.off)})
				break
			}
			v.SetInt(n)

		case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
			n, err := strconv.ParseUint(s, 10, 64)
			if err != nil || v.OverflowUint(n) {
				d.saveError(&UnmarshalTypeError{Value: "number " + s, Type: v.Type(), Offset: int64(d.off)})
				break
			}
			v.SetUint(n)

		case reflect.Float32, reflect.Float64:
			n, err := strconv.ParseFloat(s, v.Type().Bits())
			if err != nil || v.OverflowFloat(n) {
				d.saveError(&UnmarshalTypeError{Value: "number " + s, Type: v.Type(), Offset: int64(d.off)})
				break
			}
			v.SetFloat(n)
		}
	}
}
コード例 #25
0
ファイル: cmdparse.go プロジェクト: Roasbeef/btcd
// assignField is the main workhorse for the NewCmd function which handles
// assigning the provided source value to the destination field.  It supports
// direct type assignments, indirection, conversion of numeric types, and
// unmarshaling of strings into arrays, slices, structs, and maps via
// json.Unmarshal.
func assignField(paramNum int, fieldName string, dest reflect.Value, src reflect.Value) error {
	// Just error now when the types have no chance of being compatible.
	destBaseType, destIndirects := baseType(dest.Type())
	srcBaseType, srcIndirects := baseType(src.Type())
	if !typesMaybeCompatible(destBaseType, srcBaseType) {
		str := fmt.Sprintf("parameter #%d '%s' must be type %v (got "+
			"%v)", paramNum, fieldName, destBaseType, srcBaseType)
		return makeError(ErrInvalidType, str)
	}

	// Check if it's possible to simply set the dest to the provided source.
	// This is the case when the base types are the same or they are both
	// pointers that can be indirected to be the same without needing to
	// create pointers for the destination field.
	if destBaseType == srcBaseType && srcIndirects >= destIndirects {
		for i := 0; i < srcIndirects-destIndirects; i++ {
			src = src.Elem()
		}
		dest.Set(src)
		return nil
	}

	// When the destination has more indirects than the source, the extra
	// pointers have to be created.  Only create enough pointers to reach
	// the same level of indirection as the source so the dest can simply be
	// set to the provided source when the types are the same.
	destIndirectsRemaining := destIndirects
	if destIndirects > srcIndirects {
		indirectDiff := destIndirects - srcIndirects
		for i := 0; i < indirectDiff; i++ {
			dest.Set(reflect.New(dest.Type().Elem()))
			dest = dest.Elem()
			destIndirectsRemaining--
		}
	}

	if destBaseType == srcBaseType {
		dest.Set(src)
		return nil
	}

	// Make any remaining pointers needed to get to the base dest type since
	// the above direct assign was not possible and conversions are done
	// against the base types.
	for i := 0; i < destIndirectsRemaining; i++ {
		dest.Set(reflect.New(dest.Type().Elem()))
		dest = dest.Elem()
	}

	// Indirect through to the base source value.
	for src.Kind() == reflect.Ptr {
		src = src.Elem()
	}

	// Perform supported type conversions.
	switch src.Kind() {
	// Source value is a signed integer of various magnitude.
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32,
		reflect.Int64:

		switch dest.Kind() {
		// Destination is a signed integer of various magnitude.
		case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32,
			reflect.Int64:

			srcInt := src.Int()
			if dest.OverflowInt(srcInt) {
				str := fmt.Sprintf("parameter #%d '%s' "+
					"overflows destination type %v",
					paramNum, fieldName, destBaseType)
				return makeError(ErrInvalidType, str)
			}

			dest.SetInt(srcInt)

		// Destination is an unsigned integer of various magnitude.
		case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32,
			reflect.Uint64:

			srcInt := src.Int()
			if srcInt < 0 || dest.OverflowUint(uint64(srcInt)) {
				str := fmt.Sprintf("parameter #%d '%s' "+
					"overflows destination type %v",
					paramNum, fieldName, destBaseType)
				return makeError(ErrInvalidType, str)
			}
			dest.SetUint(uint64(srcInt))

		default:
			str := fmt.Sprintf("parameter #%d '%s' must be type "+
				"%v (got %v)", paramNum, fieldName, destBaseType,
				srcBaseType)
			return makeError(ErrInvalidType, str)
		}

	// Source value is an unsigned integer of various magnitude.
	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32,
		reflect.Uint64:

		switch dest.Kind() {
		// Destination is a signed integer of various magnitude.
		case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32,
			reflect.Int64:

			srcUint := src.Uint()
			if srcUint > uint64(1<<63)-1 {
				str := fmt.Sprintf("parameter #%d '%s' "+
					"overflows destination type %v",
					paramNum, fieldName, destBaseType)
				return makeError(ErrInvalidType, str)
			}
			if dest.OverflowInt(int64(srcUint)) {
				str := fmt.Sprintf("parameter #%d '%s' "+
					"overflows destination type %v",
					paramNum, fieldName, destBaseType)
				return makeError(ErrInvalidType, str)
			}
			dest.SetInt(int64(srcUint))

		// Destination is an unsigned integer of various magnitude.
		case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32,
			reflect.Uint64:

			srcUint := src.Uint()
			if dest.OverflowUint(srcUint) {
				str := fmt.Sprintf("parameter #%d '%s' "+
					"overflows destination type %v",
					paramNum, fieldName, destBaseType)
				return makeError(ErrInvalidType, str)
			}
			dest.SetUint(srcUint)

		default:
			str := fmt.Sprintf("parameter #%d '%s' must be type "+
				"%v (got %v)", paramNum, fieldName, destBaseType,
				srcBaseType)
			return makeError(ErrInvalidType, str)
		}

	// Source value is a float.
	case reflect.Float32, reflect.Float64:
		destKind := dest.Kind()
		if destKind != reflect.Float32 && destKind != reflect.Float64 {
			str := fmt.Sprintf("parameter #%d '%s' must be type "+
				"%v (got %v)", paramNum, fieldName, destBaseType,
				srcBaseType)
			return makeError(ErrInvalidType, str)
		}

		srcFloat := src.Float()
		if dest.OverflowFloat(srcFloat) {
			str := fmt.Sprintf("parameter #%d '%s' overflows "+
				"destination type %v", paramNum, fieldName,
				destBaseType)
			return makeError(ErrInvalidType, str)
		}
		dest.SetFloat(srcFloat)

	// Source value is a string.
	case reflect.String:
		switch dest.Kind() {
		// String -> bool
		case reflect.Bool:
			b, err := strconv.ParseBool(src.String())
			if err != nil {
				str := fmt.Sprintf("parameter #%d '%s' must "+
					"parse to a %v", paramNum, fieldName,
					destBaseType)
				return makeError(ErrInvalidType, str)
			}
			dest.SetBool(b)

		// String -> signed integer of varying size.
		case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32,
			reflect.Int64:

			srcInt, err := strconv.ParseInt(src.String(), 0, 0)
			if err != nil {
				str := fmt.Sprintf("parameter #%d '%s' must "+
					"parse to a %v", paramNum, fieldName,
					destBaseType)
				return makeError(ErrInvalidType, str)
			}
			if dest.OverflowInt(srcInt) {
				str := fmt.Sprintf("parameter #%d '%s' "+
					"overflows destination type %v",
					paramNum, fieldName, destBaseType)
				return makeError(ErrInvalidType, str)
			}
			dest.SetInt(srcInt)

		// String -> unsigned integer of varying size.
		case reflect.Uint, reflect.Uint8, reflect.Uint16,
			reflect.Uint32, reflect.Uint64:

			srcUint, err := strconv.ParseUint(src.String(), 0, 0)
			if err != nil {
				str := fmt.Sprintf("parameter #%d '%s' must "+
					"parse to a %v", paramNum, fieldName,
					destBaseType)
				return makeError(ErrInvalidType, str)
			}
			if dest.OverflowUint(srcUint) {
				str := fmt.Sprintf("parameter #%d '%s' "+
					"overflows destination type %v",
					paramNum, fieldName, destBaseType)
				return makeError(ErrInvalidType, str)
			}
			dest.SetUint(srcUint)

		// String -> float of varying size.
		case reflect.Float32, reflect.Float64:
			srcFloat, err := strconv.ParseFloat(src.String(), 0)
			if err != nil {
				str := fmt.Sprintf("parameter #%d '%s' must "+
					"parse to a %v", paramNum, fieldName,
					destBaseType)
				return makeError(ErrInvalidType, str)
			}
			if dest.OverflowFloat(srcFloat) {
				str := fmt.Sprintf("parameter #%d '%s' "+
					"overflows destination type %v",
					paramNum, fieldName, destBaseType)
				return makeError(ErrInvalidType, str)
			}
			dest.SetFloat(srcFloat)

		// String -> string (typecast).
		case reflect.String:
			dest.SetString(src.String())

		// String -> arrays, slices, structs, and maps via
		// json.Unmarshal.
		case reflect.Array, reflect.Slice, reflect.Struct, reflect.Map:
			concreteVal := dest.Addr().Interface()
			err := json.Unmarshal([]byte(src.String()), &concreteVal)
			if err != nil {
				str := fmt.Sprintf("parameter #%d '%s' must "+
					"be valid JSON which unsmarshals to a %v",
					paramNum, fieldName, destBaseType)
				return makeError(ErrInvalidType, str)
			}
			dest.Set(reflect.ValueOf(concreteVal).Elem())
		}
	}

	return nil
}
コード例 #26
0
ファイル: parameter.go プロジェクト: jason-xxl/go-swagger
func (p *untypedParamBinder) setFieldValue(target reflect.Value, defaultValue interface{}, data string) error {
	tpe := p.parameter.Type
	if p.parameter.Format != "" {
		tpe = p.parameter.Format
	}

	if data == "" && p.parameter.Required && p.parameter.Default == nil {
		return errors.Required(p.Name, p.parameter.In)
	}

	ok, err := p.tryUnmarshaler(target, defaultValue, data)
	if err != nil {
		return errors.InvalidType(p.Name, p.parameter.In, tpe, data)
	}
	if ok {
		return nil
	}

	defVal := reflect.Zero(target.Type())
	if defaultValue != nil {
		defVal = reflect.ValueOf(defaultValue)
	}

	if tpe == "byte" {
		if data == "" {
			target.SetBytes(defVal.Bytes())
			return nil
		}

		b, err := base64.StdEncoding.DecodeString(data)
		if err != nil {
			b, err = base64.URLEncoding.DecodeString(data)
			if err != nil {
				return errors.InvalidType(p.Name, p.parameter.In, tpe, data)
			}
		}
		target.SetBytes(b)
		return nil
	}

	switch target.Kind() {
	case reflect.Bool:
		if data == "" {
			target.SetBool(defVal.Bool())
			return nil
		}
		b, err := swag.ConvertBool(data)
		if err != nil {
			return err
		}
		target.SetBool(b)

	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		if data == "" {
			target.SetInt(defVal.Int())
			return nil
		}
		i, err := strconv.ParseInt(data, 10, 64)
		if err != nil {
			return errors.InvalidType(p.Name, p.parameter.In, tpe, data)
		}
		if target.OverflowInt(i) {
			return errors.InvalidType(p.Name, p.parameter.In, tpe, data)
		}

		target.SetInt(i)

	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
		if data == "" {
			target.SetUint(defVal.Uint())
			return nil
		}
		u, err := strconv.ParseUint(data, 10, 64)
		if err != nil {
			return errors.InvalidType(p.Name, p.parameter.In, tpe, data)
		}
		if target.OverflowUint(u) {
			return errors.InvalidType(p.Name, p.parameter.In, tpe, data)
		}
		target.SetUint(u)

	case reflect.Float32, reflect.Float64:
		if data == "" {
			target.SetFloat(defVal.Float())
			return nil
		}
		f, err := strconv.ParseFloat(data, 64)
		if err != nil {
			return errors.InvalidType(p.Name, p.parameter.In, tpe, data)
		}
		if target.OverflowFloat(f) {
			return errors.InvalidType(p.Name, p.parameter.In, tpe, data)
		}
		target.SetFloat(f)

	case reflect.String:
		value := data
		if value == "" {
			value = defVal.String()
		}
		// validate string
		target.SetString(value)

	case reflect.Ptr:
		if data == "" && defVal.Kind() == reflect.Ptr {
			target.Set(defVal)
			return nil
		}
		newVal := reflect.New(target.Type().Elem())
		if err := p.setFieldValue(reflect.Indirect(newVal), defVal, data); err != nil {
			return err
		}
		target.Set(newVal)

	default:
		return errors.InvalidType(p.Name, p.parameter.In, tpe, data)
	}
	return nil
}
コード例 #27
0
func resolve_uint(val string, v reflect.Value, useNumber bool) (string, error) {
	original := val
	val = strings.Replace(val, "_", "", -1)
	var value uint64

	isNumberValue := v.Type() == numberType

	if val[0] == '-' {
		return "", errors.New("Unsigned int with negative value: " + original)
	}

	if val[0] == '+' {
		val = val[1:]
	}

	base := 10
	if val == "0" {
		if isNumberValue {
			v.SetString("0")
		} else {
			v.Set(reflect.Zero(v.Type()))
		}

		return "!!int", nil
	}

	if strings.HasPrefix(val, "0b") {
		base = 2
		val = val[2:]
	} else if strings.HasPrefix(val, "0x") {
		base = 16
		val = val[2:]
	} else if val[0] == '0' {
		base = 8
		val = val[1:]
	} else if strings.Contains(val, ":") {
		digits := strings.Split(val, ":")
		bes := uint64(1)
		for j := len(digits) - 1; j >= 0; j-- {
			n, err := strconv.ParseUint(digits[j], 10, 64)
			n *= bes
			if err != nil {
				return "", errors.New("Unsigned Integer: " + original)
			}
			value += n
			bes *= 60
		}

		if isNumberValue {
			v.SetString(strconv.FormatUint(value, 10))
		} else {
			if v.OverflowUint(value) {
				return "", errors.New("Unsigned Integer: " + original)
			}

			v.SetUint(value)
		}
		return "!!int", nil
	}

	value, err := strconv.ParseUint(val, base, 64)
	if err != nil {
		return "", errors.New("Unsigned Integer: " + val)
	}

	if isNumberValue {
		v.SetString(strconv.FormatUint(value, 10))
	} else {
		if v.OverflowUint(value) {
			return "", errors.New("Unsigned Integer: " + val)
		}

		v.SetUint(value)
	}

	return "!!int", nil
}
コード例 #28
0
ファイル: decoder.go プロジェクト: joamaki/gorethink
// decodeLiteral decodes the source value into the destination value. This function
// is used to decode literal values.
func decodeLiteral(s *decodeState, dv reflect.Value, sv reflect.Value) {
	dv = indirect(dv)

	// Special case for if sv is nil:
	switch sv.Kind() {
	case reflect.Invalid:
		dv.Set(reflect.Zero(dv.Type()))
		return
	}

	// Attempt to convert the value from the source type to the destination type
	switch value := sv.Interface().(type) {
	case nil:
		switch dv.Kind() {
		case reflect.Interface, reflect.Ptr, reflect.Map, reflect.Slice:
			dv.Set(reflect.Zero(dv.Type()))
		}
	case bool:
		switch dv.Kind() {
		default:
			s.saveError(&DecodeTypeError{"bool", dv.Type()})
			return
		case reflect.Bool:
			dv.SetBool(value)
		case reflect.String:
			dv.SetString(strconv.FormatBool(value))
		case reflect.Interface:
			if dv.NumMethod() == 0 {
				dv.Set(reflect.ValueOf(value))
			} else {
				s.saveError(&DecodeTypeError{"bool", dv.Type()})
				return
			}
		}

	case string:
		switch dv.Kind() {
		default:
			s.saveError(&DecodeTypeError{"string", dv.Type()})
			return
		case reflect.String:
			dv.SetString(value)
		case reflect.Bool:
			b, err := strconv.ParseBool(value)
			if err != nil {
				s.saveError(&DecodeTypeError{"string", dv.Type()})
				return
			}
			dv.SetBool(b)
		case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
			n, err := strconv.ParseInt(value, 10, 64)
			if err != nil || dv.OverflowInt(n) {
				s.saveError(&DecodeTypeError{"string", dv.Type()})
				return
			}
			dv.SetInt(n)
		case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
			n, err := strconv.ParseUint(value, 10, 64)
			if err != nil || dv.OverflowUint(n) {
				s.saveError(&DecodeTypeError{"string", dv.Type()})
				return
			}
			dv.SetUint(n)
		case reflect.Float32, reflect.Float64:
			n, err := strconv.ParseFloat(value, 64)
			if err != nil || dv.OverflowFloat(n) {
				s.saveError(&DecodeTypeError{"string", dv.Type()})
				return
			}
			dv.SetFloat(n)
		case reflect.Interface:
			if dv.NumMethod() == 0 {
				dv.Set(reflect.ValueOf(string(value)))
			} else {
				s.saveError(&DecodeTypeError{"string", dv.Type()})
				return
			}
		}

	case int, int8, int16, int32, int64:
		switch dv.Kind() {
		default:
			s.saveError(&DecodeTypeError{"int", dv.Type()})
			return
		case reflect.Interface:
			if dv.NumMethod() != 0 {
				s.saveError(&DecodeTypeError{"int", dv.Type()})
				return
			}
			dv.Set(reflect.ValueOf(value))

		case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
			dv.SetInt(int64(reflect.ValueOf(value).Int()))
		case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
			dv.SetUint(uint64(reflect.ValueOf(value).Int()))
		case reflect.Float32, reflect.Float64:
			dv.SetFloat(float64(reflect.ValueOf(value).Int()))
		case reflect.String:
			dv.SetString(strconv.FormatInt(int64(reflect.ValueOf(value).Int()), 10))
		}
	case uint, uint8, uint16, uint32, uint64:
		switch dv.Kind() {
		default:
			s.saveError(&DecodeTypeError{"uint", dv.Type()})
			return
		case reflect.Interface:
			if dv.NumMethod() != 0 {
				s.saveError(&DecodeTypeError{"uint", dv.Type()})
				return
			}
			dv.Set(reflect.ValueOf(value))

		case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
			dv.SetInt(int64(reflect.ValueOf(value).Uint()))
		case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
			dv.SetUint(uint64(reflect.ValueOf(value).Uint()))
		case reflect.Float32, reflect.Float64:
			dv.SetFloat(float64(reflect.ValueOf(value).Uint()))
		case reflect.String:
			dv.SetString(strconv.FormatUint(uint64(reflect.ValueOf(value).Uint()), 10))
		}
	case float32, float64:
		switch dv.Kind() {
		default:
			s.saveError(&DecodeTypeError{"float", dv.Type()})
			return
		case reflect.Interface:
			if dv.NumMethod() != 0 {
				s.saveError(&DecodeTypeError{"float", dv.Type()})
				return
			}
			dv.Set(reflect.ValueOf(value))

		case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
			dv.SetInt(int64(reflect.ValueOf(value).Float()))
		case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
			dv.SetUint(uint64(reflect.ValueOf(value).Float()))
		case reflect.Float32, reflect.Float64:
			dv.SetFloat(float64(reflect.ValueOf(value).Float()))
		case reflect.String:
			dv.SetString(strconv.FormatFloat(float64(reflect.ValueOf(value).Float()), 'g', -1, 64))
		}
	default:
		s.saveError(&DecodeTypeError{sv.Type().String(), dv.Type()})
		return
	}

	return
}
コード例 #29
0
ファイル: marshal.go プロジェクト: kballard/go-osx-plist
func (state *unmarshalState) unmarshalValue(cfObj cfTypeRef, v reflect.Value) error {
	vType := v.Type()
	var unmarshaler Unmarshaler
	if u, ok := v.Interface().(Unmarshaler); ok {
		unmarshaler = u
	} else if vType.Kind() != reflect.Ptr && vType.Name() != "" && v.CanAddr() {
		// matching the encoding/json behavior here
		// If v is a named type and is addressable, check its address for Unmarshaler.
		vA := v.Addr()
		if u, ok := vA.Interface().(Unmarshaler); ok {
			unmarshaler = u
		}
	}
	if unmarshaler != nil {
		// flip over to the dumb conversion routine so we have something to give UnmarshalPlist()
		plist, err := convertCFTypeToInterface(cfObj)
		if err != nil {
			return err
		}
		if vType.Kind() == reflect.Ptr && v.IsNil() {
			v.Set(reflect.New(vType.Elem()))
			unmarshaler = v.Interface().(Unmarshaler)
		}
		return unmarshaler.UnmarshalPlist(plist)
	}
	if vType.Kind() == reflect.Ptr {
		if v.IsNil() {
			v.Set(reflect.New(vType.Elem()))
		}
		return state.unmarshalValue(cfObj, v.Elem())
	}
	typeID := C.CFGetTypeID(C.CFTypeRef(cfObj))
	vSetter := v      // receiver of any Set* calls
	vAddr := v.Addr() // used for re-setting v for maps/slices
	if vType.Kind() == reflect.Interface {
		if v.IsNil() {
			// pick an appropriate type based on the cfobj
			var typ reflect.Type
			if typeID == cfNumberTypeID {
				typ = cfNumberTypeToType(C.CFNumberGetType(C.CFNumberRef(cfObj)))
			} else {
				var ok bool
				typ, ok = cfTypeMap[typeID]
				if !ok {
					return &UnknownCFTypeError{typeID}
				}
			}
			if !typ.AssignableTo(vType) {
				// v must be some interface that our object doesn't conform to
				state.recordError(&UnmarshalTypeError{cfTypeNames[typeID], vType})
				return nil
			}
			vSetter.Set(reflect.Zero(typ))
		}
		vAddr = v
		v = v.Elem()
		vType = v.Type()
	}
	switch typeID {
	case cfArrayTypeID:
		if vType.Kind() != reflect.Slice && vType.Kind() != reflect.Array {
			state.recordError(&UnmarshalTypeError{cfTypeNames[typeID], vType})
			return nil
		}
		return convertCFArrayToSliceHelper(C.CFArrayRef(cfObj), func(elem cfTypeRef, idx, count int) (bool, error) {
			if idx == 0 && vType.Kind() == reflect.Slice {
				vSetter.Set(reflect.MakeSlice(vType, count, count))
				v = vAddr.Elem()
			} else if vType.Kind() == reflect.Array && idx >= v.Len() {
				return false, nil
			}
			if err := state.unmarshalValue(elem, v.Index(idx)); err != nil {
				return false, err
			}
			return true, nil
		})
	case cfBooleanTypeID:
		if vType.Kind() != reflect.Bool {
			state.recordError(&UnmarshalTypeError{cfTypeNames[typeID], vType})
			return nil
		}
		vSetter.Set(reflect.ValueOf(C.CFBooleanGetValue(C.CFBooleanRef(cfObj)) != C.false))
		return nil
	case cfDataTypeID:
		if !byteSliceType.AssignableTo(vType) {
			state.recordError(&UnmarshalTypeError{cfTypeNames[typeID], vType})
			return nil
		}
		vSetter.Set(reflect.ValueOf(convertCFDataToBytes(C.CFDataRef(cfObj))))
		return nil
	case cfDateTypeID:
		if !timeType.AssignableTo(vType) {
			state.recordError(&UnmarshalTypeError{cfTypeNames[typeID], vType})
			return nil
		}
		vSetter.Set(reflect.ValueOf(convertCFDateToTime(C.CFDateRef(cfObj))))
		return nil
	case cfDictionaryTypeID:
		if vType.Kind() == reflect.Map {
			// it's a map. Check its key type first
			if !stringType.AssignableTo(vType.Key()) {
				state.recordError(&UnmarshalTypeError{cfTypeNames[cfStringTypeID], vType.Key()})
				return nil
			}
			if v.IsNil() {
				vSetter.Set(reflect.MakeMap(vType))
				v = vAddr.Elem()
			}
			return convertCFDictionaryToMapHelper(C.CFDictionaryRef(cfObj), func(key string, value cfTypeRef, count int) error {
				keyVal := reflect.ValueOf(key)
				val := reflect.New(vType.Elem())
				if err := state.unmarshalValue(value, val); err != nil {
					return err
				}
				v.SetMapIndex(keyVal, val.Elem())
				return nil
			})
		} else if vType.Kind() == reflect.Struct {
			return convertCFDictionaryToMapHelper(C.CFDictionaryRef(cfObj), func(key string, value cfTypeRef, count int) error {
				// we need to iterate the fields because the tag might rename the key
				var f reflect.StructField
				var ok bool
				for i := 0; i < vType.NumField(); i++ {
					sf := vType.Field(i)
					tag := sf.Tag.Get("plist")
					if tag == "-" {
						// Pretend this field doesn't exist
						continue
					}
					if sf.Anonymous {
						// Match encoding/json's behavior here and pretend it doesn't exist
						continue
					}
					name, _ := parseTag(tag)
					if name == key {
						f = sf
						ok = true
						// This is unambiguously the right match
						break
					}
					if sf.Name == key {
						f = sf
						ok = true
					}
					// encoding/json does a case-insensitive match. Lets do that too
					if !ok && strings.EqualFold(sf.Name, key) {
						f = sf
						ok = true
					}
				}
				if ok {
					if f.PkgPath != "" {
						// this is an unexported field
						return &UnmarshalFieldError{key, vType, f}
					}
					vElem := v.FieldByIndex(f.Index)
					if err := state.unmarshalValue(value, vElem); err != nil {
						return err
					}
				}
				return nil
			})
		}
		state.recordError(&UnmarshalTypeError{cfTypeNames[typeID], vType})
		return nil
	case cfNumberTypeID:
		switch vType.Kind() {
		case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
			i := convertCFNumberToInt64(C.CFNumberRef(cfObj))
			if v.OverflowInt(i) {
				state.recordError(&UnmarshalTypeError{cfTypeNames[typeID] + " " + strconv.FormatInt(i, 10), vType})
				return nil
			}
			if vSetter.Kind() == reflect.Interface {
				vSetter.Set(reflect.ValueOf(i))
			} else {
				vSetter.SetInt(i)
			}
			return nil
		case reflect.Uint, reflect.Uintptr, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
			u := uint64(convertCFNumberToUInt32(C.CFNumberRef(cfObj)))
			if v.OverflowUint(u) {
				state.recordError(&UnmarshalTypeError{cfTypeNames[typeID] + " " + strconv.FormatUint(u, 10), vType})
				return nil
			}
			if vSetter.Kind() == reflect.Interface {
				vSetter.Set(reflect.ValueOf(u))
			} else {
				vSetter.SetUint(u)
			}
			return nil
		case reflect.Float32, reflect.Float64:
			f := convertCFNumberToFloat64(C.CFNumberRef(cfObj))
			if v.OverflowFloat(f) {
				state.recordError(&UnmarshalTypeError{cfTypeNames[typeID] + " " + strconv.FormatFloat(f, 'f', -1, 64), vType})
				return nil
			}
			if vSetter.Kind() == reflect.Interface {
				vSetter.Set(reflect.ValueOf(f))
			} else {
				vSetter.SetFloat(f)
			}
			return nil
		}
		state.recordError(&UnmarshalTypeError{cfTypeNames[typeID], vType})
		return nil
	case cfStringTypeID:
		if vType.Kind() != reflect.String {
			state.recordError(&UnmarshalTypeError{cfTypeNames[typeID], vType})
			return nil
		}
		vSetter.Set(reflect.ValueOf(convertCFStringToString(C.CFStringRef(cfObj))))
		return nil
	}
	return &UnknownCFTypeError{typeID}
}
コード例 #30
0
ファイル: decode.go プロジェクト: Sunmonds/gcc
// literalStore decodes a literal stored in item into v.
func (d *decodeState) literalStore(item []byte, v reflect.Value) {
	// Check for unmarshaler.
	wantptr := item[0] == 'n' // null
	unmarshaler, pv := d.indirect(v, wantptr)
	if unmarshaler != nil {
		err := unmarshaler.UnmarshalJSON(item)
		if err != nil {
			d.error(err)
		}
		return
	}
	v = pv

	switch c := item[0]; c {
	case 'n': // null
		switch v.Kind() {
		default:
			d.saveError(&UnmarshalTypeError{"null", v.Type()})
		case reflect.Interface, reflect.Ptr, reflect.Map:
			v.Set(reflect.Zero(v.Type()))
		}

	case 't', 'f': // true, false
		value := c == 't'
		switch v.Kind() {
		default:
			d.saveError(&UnmarshalTypeError{"bool", v.Type()})
		case reflect.Bool:
			v.SetBool(value)
		case reflect.Interface:
			v.Set(reflect.ValueOf(value))
		}

	case '"': // string
		s, ok := unquoteBytes(item)
		if !ok {
			d.error(errPhase)
		}
		switch v.Kind() {
		default:
			d.saveError(&UnmarshalTypeError{"string", v.Type()})
		case reflect.Slice:
			if v.Type() != byteSliceType {
				d.saveError(&UnmarshalTypeError{"string", v.Type()})
				break
			}
			b := make([]byte, base64.StdEncoding.DecodedLen(len(s)))
			n, err := base64.StdEncoding.Decode(b, s)
			if err != nil {
				d.saveError(err)
				break
			}
			v.Set(reflect.ValueOf(b[0:n]))
		case reflect.String:
			v.SetString(string(s))
		case reflect.Interface:
			v.Set(reflect.ValueOf(string(s)))
		}

	default: // number
		if c != '-' && (c < '0' || c > '9') {
			d.error(errPhase)
		}
		s := string(item)
		switch v.Kind() {
		default:
			d.error(&UnmarshalTypeError{"number", v.Type()})
		case reflect.Interface:
			n, err := strconv.Atof64(s)
			if err != nil {
				d.saveError(&UnmarshalTypeError{"number " + s, v.Type()})
				break
			}
			v.Set(reflect.ValueOf(n))

		case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
			n, err := strconv.Atoi64(s)
			if err != nil || v.OverflowInt(n) {
				d.saveError(&UnmarshalTypeError{"number " + s, v.Type()})
				break
			}
			v.SetInt(n)

		case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
			n, err := strconv.Atoui64(s)
			if err != nil || v.OverflowUint(n) {
				d.saveError(&UnmarshalTypeError{"number " + s, v.Type()})
				break
			}
			v.SetUint(n)

		case reflect.Float32, reflect.Float64:
			n, err := strconv.AtofN(s, v.Type().Bits())
			if err != nil || v.OverflowFloat(n) {
				d.saveError(&UnmarshalTypeError{"number " + s, v.Type()})
				break
			}
			v.SetFloat(n)
		}
	}
}