Beispiel #1
0
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())
}
Beispiel #2
0
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)
	}
}
Beispiel #3
0
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
	}
}
Beispiel #4
0
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()})
	}
}
Beispiel #5
0
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))
	}
}
Beispiel #6
0
func resolve_int(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

	sign := int64(1)
	if val[0] == '-' {
		sign = -1
		val = val[1:]
	} else 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 integer: '%s' at %s", original, event.start_mark)
	}

	var val64 int64
	if value <= math.MaxInt64 {
		val64 = int64(value)
		if sign == -1 {
			val64 = -val64
		}
	} else if sign == -1 && value == uint64(math.MaxInt64)+1 {
		val64 = math.MinInt64
	} else {
		return "", fmt.Errorf("Invalid integer: '%s' at %s", original, event.start_mark)
	}

	if isNumberValue {
		v.SetString(strconv.FormatInt(val64, 10))
	} else {
		if v.OverflowInt(val64) {
			return "", fmt.Errorf("Invalid integer: '%s' at %s", original, event.start_mark)
		}
		v.SetInt(val64)
	}

	return yaml_INT_TAG, nil
}
Beispiel #7
0
func setInt(v reflect.Value, x interface{}) error {
	xx := x.(int64)
	if v.OverflowInt(xx) {
		return fmt.Errorf("bigquery: value %v overflows struct field of type %v", xx, v.Type())
	}
	v.SetInt(xx)
	return nil
}
Beispiel #8
0
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
}
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
}
Beispiel #10
0
func decodeInt(rval reflect.Value, arg string) error {
	v, err := strconv.ParseInt(arg, 10, 64)
	if err != nil {
		return err
	}
	if rval.OverflowInt(v) {
		return fmt.Errorf("value %d would overflow %s", v, rval.Kind())
	}
	rval.Set(reflect.ValueOf(v).Convert(rval.Type()))
	return nil
}
Beispiel #11
0
func resolve_int(val string, v reflect.Value) error {
	val = strings.Replace(val, "_", "", -1)
	var value int64

	sign := int64(1)
	if val[0] == '-' {
		sign = -1
		val = val[1:]
	} else 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 := int64(1)
		for j := len(digits) - 1; j >= 0; j-- {
			n, err := strconv.ParseInt(digits[j], 10, 64)
			n *= bes
			if err != nil || v.OverflowInt(n) {
				return errors.New("Integer: " + val)
			}
			value += n
			bes *= 60
		}

		value *= sign
		v.SetInt(value)
		return nil
	}

	value, err := strconv.ParseInt(val, base, 64)
	value *= sign
	if err != nil || v.OverflowInt(value) {
		return errors.New("Integer: " + val)
	}

	v.SetInt(value)
	return nil
}
Beispiel #12
0
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)
		}
	}
}
Beispiel #13
0
func unmarshalNumber(number float64, value reflect.Value) error {
	switch k := value.Kind(); k {
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		intv := int64(number)
		if value.OverflowInt(intv) {
			fmt.Errorf("Number will overflow field of type %q", k)
		}
		value.SetInt(intv)
	case reflect.Float32, reflect.Float64:
		value.SetFloat(float64(number))
	default:
		return fmt.Errorf("Cannot unmarshal number into %q", k)
	}
	return nil
}
Beispiel #14
0
func setInt(rv reflect.Value, i int64) error {
	switch rv.Kind() {
	case reflect.Ptr:
		return setInt(reflect.Indirect(rv), i)
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		if rv.OverflowInt(i) {
			return fmt.Errorf("value %d does not fit into target of type %s", i, rv.Kind().String())
		}
		rv.SetInt(i)
		return nil
	case reflect.Interface:
		rv.Set(reflect.ValueOf(i))
		return nil
	default:
		return fmt.Errorf("cannot assign int into Kind=%s Type=%#v %#v", rv.Kind().String(), rv.Type(), rv)
	}
}
Beispiel #15
0
// 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()
}
Beispiel #16
0
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)
	}
}
Beispiel #17
0
// 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()
}
Beispiel #18
0
func decodeInteger(b []byte, v reflect.Value) error {
	if len(b) == 0 {
		return SyntaxError("integer must have at least one byte of content")
	}

	var i int64
	for _, b := range b {
		i = i<<8 + int64(b)
	}

	if v.OverflowInt(i) {
		return StructuralError("integer overflow")
	}

	v.SetInt(i)

	return nil
}
Beispiel #19
0
func decodeInt(d *decodeState, kind int, v reflect.Value) {
	var n int64
	switch kind {
	default:
		d.saveErrorAndSkip(kind, v.Type())
		return
	case kindInt64, kindTimestamp, kindDateTime:
		n = d.scanInt64()
	case kindInt32:
		n = int64(d.scanInt32())
	case kindFloat:
		n = int64(d.scanFloat())
	}
	if v.OverflowInt(n) {
		d.saveError(&DecodeConvertError{kind, v.Type()})
		return
	}
	v.SetInt(n)
}
Beispiel #20
0
// 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())})
	}

}
Beispiel #21
0
// unmarshalScalar sets the scalar value of the node to field based on its type.
// This returns an error if the node cannot be converted to a scalar type
func unmarshalScalar(node yaml.Node, field reflect.Value, supportedYamlTags map[string]bool) error {
	value, ok := node.(yaml.Scalar)
	if !ok {
		return fmt.Errorf("Error parsing: node is not of type string %v", node)
	}
	strValue := value.String()

	// unmarshal double-quoted string (best-effort)
	// TODO, single-quoted string http://yaml.org/spec/1.2/spec.html#id2786942
	unquotedStrValue, err := strconv.Unquote(strValue)
	if err == nil { // strconv.Unquote returns no error only if the string has valid quotes
		strValue = unquotedStrValue
	}

	switch field.Kind() {
	case reflect.String:
		field.SetString(strValue)
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		intValue, err := strconv.Atoi(strValue)
		if err != nil {
			return err
		}
		if !field.OverflowInt(int64(intValue)) {
			field.SetInt(int64(intValue))
		}
	case reflect.Bool:
		boolValue, err := strconv.ParseBool(strValue)
		if err != nil {
			return err
		}
		field.SetBool(boolValue)
	case reflect.Float32, reflect.Float64:
		floatValue, err := strconv.ParseFloat(strValue, 64)
		if err != nil {
			return err
		}
		field.SetFloat(float64(floatValue))
	default:
		return fmt.Errorf("Unknown type kind [%v] to setValue from scalar", field.Kind())
	}
	return nil
}
Beispiel #22
0
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()})
}
Beispiel #23
0
func setInt(fv reflect.Value, v *ast.Integer) error {
	i, err := v.Int()
	if err != nil {
		return err
	}
	switch fv.Kind() {
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		if fv.OverflowInt(i) {
			return &errorOutOfRange{fv.Kind(), i}
		}
		fv.SetInt(i)
	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
		fv.SetUint(uint64(i))
	case reflect.Interface:
		fv.Set(reflect.ValueOf(i))
	default:
		return fmt.Errorf("`%v' is not any types of int", fv.Type())
	}
	return nil
}
func resolve_int(val string, v reflect.Value, useNumber bool) (string, error) {
	original := val
	val = strings.Replace(val, "_", "", -1)
	var value int64

	isNumberValue := v.Type() == numberType

	sign := int64(1)
	if val[0] == '-' {
		sign = -1
		val = val[1:]
	} else 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 := int64(1)
		for j := len(digits) - 1; j >= 0; j-- {
			n, err := strconv.ParseInt(digits[j], 10, 64)
			n *= bes
			if err != nil {
				return "", errors.New("Integer: " + original)
			}
			value += n
			bes *= 60
		}

		value *= sign

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

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

	value, err := strconv.ParseInt(val, base, 64)
	if err != nil {
		return "", errors.New("Integer: " + original)
	}
	value *= sign

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

		v.SetInt(value)
	}

	return "!!int", nil
}
Beispiel #25
0
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
}
Beispiel #26
0
// 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)
		}
	}
}
Beispiel #27
0
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 ""
}
Beispiel #28
0
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
}
Beispiel #29
0
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}
}
Beispiel #30
0
// 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
}