예제 #1
0
// Unmarshal fills each field in the givne interface{} with the AMF data on the
// stream in-order.
//
// If a value of amf0.Null or amf0.Undefined is read, then the value will be
// skipped.
//
// If a pointer field type is reached, then the value will be reduced to match
// that same pointer type.
func (u *Unmarshaler) Unmarshal(dest interface{}) error {
	v := reflect.ValueOf(dest).Elem()

	for i := 0; i < v.NumField(); i++ {
		field := v.Field(i)

		next, err := u.decode(u.r)
		if err != nil {
			return err
		}

		if u.isBodyless(next) {
			if !u.canAssignNil(field) {
				return fmt.Errorf(
					"amf0: unable to assign nil to type %T",
					field.Interface())
			}

			continue
		}

		var val reflect.Value
		if u.canAssignNil(field) {
			val = reflect.ValueOf(next)
		} else {
			val = reflect.ValueOf(next).Elem()
		}

		field.Set(val.Convert(field.Type()))
	}

	return nil
}
예제 #2
0
파일: vm.go 프로젝트: postfix/anko
// equal return true when lhsV and rhsV is same value.
func equal(lhsV, rhsV reflect.Value) bool {
	lhsIsNil, rhsIsNil := isNil(lhsV), isNil(rhsV)
	if lhsIsNil && rhsIsNil {
		return true
	}
	if (!lhsIsNil && rhsIsNil) || (lhsIsNil && !rhsIsNil) {
		return false
	}
	if lhsV.Kind() == reflect.Interface || lhsV.Kind() == reflect.Ptr {
		lhsV = lhsV.Elem()
	}
	if rhsV.Kind() == reflect.Interface || rhsV.Kind() == reflect.Ptr {
		rhsV = rhsV.Elem()
	}
	if !lhsV.IsValid() || !rhsV.IsValid() {
		return true
	}
	if isNum(lhsV) && isNum(rhsV) {
		if rhsV.Type().ConvertibleTo(lhsV.Type()) {
			rhsV = rhsV.Convert(lhsV.Type())
		}
	}
	if lhsV.CanInterface() && rhsV.CanInterface() {
		return reflect.DeepEqual(lhsV.Interface(), rhsV.Interface())
	}
	return reflect.DeepEqual(lhsV, rhsV)
}
예제 #3
0
func mapidx(v reflect.Value, nm string) (interface{}, error) {
	t := v.Type()
	keyt := t.Key()
	var k reflect.Value
	switch keyt.Kind() {
	case reflect.String:
		k = reflect.ValueOf(nm)
	case reflect.Int, reflect.Int8, reflect.Int16,
		reflect.Int32, reflect.Int64:
		idx, err := strconv.ParseInt(nm, 0, 64)
		if err != nil {
			return nil, fmt.Errorf("%s not an index", nm)
		}
		k = reflect.ValueOf(idx)
	case reflect.Uint, reflect.Uint8, reflect.Uint16,
		reflect.Uint32, reflect.Uint64:
		idx, err := strconv.ParseUint(nm, 0, 64)
		if err != nil {
			return nil, fmt.Errorf("%s not an index", nm)
		}
		k = reflect.ValueOf(uint(idx))
	default:
		return nil, fmt.Errorf("%s: can't handle index type", nm)
	}
	if !k.Type().ConvertibleTo(keyt) {
		return nil, fmt.Errorf("invalid map key type")
	}
	k = k.Convert(keyt)
	return v.MapIndex(k).Interface(), nil

}
예제 #4
0
파일: bridge.go 프로젝트: reedobrien/qml
func convertAndSet(to, from reflect.Value, setMethod reflect.Value) {
	var toType reflect.Type
	if setMethod.IsValid() {
		toType = setMethod.Type().In(0)
	} else {
		toType = to.Type()
	}
	fromType := from.Type()
	defer func() {
		if v := recover(); v != nil {
			panic(fmt.Sprintf("cannot use %s as a %s", fromType, toType))
		}
	}()
	if fromType == listType && toType.Kind() == reflect.Slice {
		list := from.Interface().(*List)
		from = reflect.MakeSlice(toType, len(list.data), len(list.data))
		elemType := toType.Elem()
		for i, elem := range list.data {
			from.Index(i).Set(reflect.ValueOf(elem).Convert(elemType))
		}
	} else if toType != fromType {
		from = from.Convert(toType)
	}
	if setMethod.IsValid() {
		setMethod.Call([]reflect.Value{from})
	} else {
		to.Set(from)
	}
}
예제 #5
0
파일: util.go 프로젝트: raff/eval
// Only considers untyped kinds produced by our runtime. Assumes input type is unnamed
func promoteUntypedNumerals(x, y reflect.Value) (reflect.Value, reflect.Value) {
	switch x.Kind() {
	case reflect.Int64:
		switch y.Kind() {
		case reflect.Int64:
			return x, y
		case reflect.Float64:
			return x.Convert(y.Type()), y
		case reflect.Complex128:
			return reflect.ValueOf(complex(float64(x.Int()), 0)), y
		}
	case reflect.Float64:
		switch y.Kind() {
		case reflect.Int64:
			return x, y.Convert(x.Type())
		case reflect.Float64:
			return x, y
		case reflect.Complex128:
			return reflect.ValueOf(complex(x.Float(), 0)), y
		}
	case reflect.Complex128:
		switch y.Kind() {
		case reflect.Int64:
			return x, reflect.ValueOf(complex(float64(y.Int()), 0))
		case reflect.Float64:
			return x, reflect.ValueOf(complex(y.Float(), 0))
		case reflect.Complex128:
			return x, y
		}
	}
	panic(fmt.Sprintf("runtime: bad untyped numeras %v and %v", x, y))
}
예제 #6
0
파일: encode_map.go 프로젝트: h12w/msgpack
func encodeMapStringInterfaceValue(e *Encoder, v reflect.Value) error {
	if v.IsNil() {
		return e.EncodeNil()
	}

	if err := e.EncodeMapLen(v.Len()); err != nil {
		return err
	}

	m := v.Convert(mapStringInterfaceType).Interface().(map[string]interface{})
	if e.sortMapKeys {
		return e.encodeSortedMapStringInterface(m)
	}

	for mk, mv := range m {
		if err := e.EncodeString(mk); err != nil {
			return err
		}
		if err := e.Encode(mv); err != nil {
			return err
		}
	}

	return nil
}
예제 #7
0
파일: marshaler.go 프로젝트: WatchBeam/amf0
func (m *Marshaler) convertToAmfType(val reflect.Value) (amf0.AmfType, error) {
	if val.Kind() == reflect.Ptr && val.IsNil() {
		return new(amf0.Null), nil
	}

	amf := m.i.NewMatchingTypeFromValue(val)
	if amf == nil {
		return nil, noMatchingType{val.Type()}
	}

	var (
		toType reflect.Type
		amft   = reflect.ValueOf(amf)
		isPtr  = val.Kind() == reflect.Ptr
	)

	if isPtr {
		toType = amft.Type()
	} else {
		toType = amft.Type().Elem()
	}

	if !val.Type().ConvertibleTo(toType) {
		return nil, typeUnassignable{val.Type(), amft.Type().Elem()}
	}

	val = val.Convert(toType)
	if isPtr {
		val = val.Elem()
	}
	amft.Elem().Set(val)

	return amf, nil
}
예제 #8
0
func (en *encoder) sliceReflect(key uint64, slval reflect.Value) {

	if slval.Kind() != reflect.Slice {
		panic("no slice passed")
	}
	sllen := slval.Len()
	slelt := slval.Type().Elem()
	packed := encoder{}
	switch slelt.Kind() {
	case reflect.Bool:
		for i := 0; i < sllen; i++ {
			v := uint64(0)
			if slval.Index(i).Bool() {
				v = 1
			}
			packed.uvarint(v)
		}

	case reflect.Int, reflect.Int32, reflect.Int64:
		for i := 0; i < sllen; i++ {
			packed.svarint(slval.Index(i).Int())
		}

	case reflect.Uint32, reflect.Uint64:
		for i := 0; i < sllen; i++ {
			packed.uvarint(slval.Index(i).Uint())
		}

	case reflect.Float32:
		for i := 0; i < sllen; i++ {
			packed.u32(math.Float32bits(
				float32(slval.Index(i).Float())))
		}

	case reflect.Float64:
		for i := 0; i < sllen; i++ {
			packed.u64(math.Float64bits(slval.Index(i).Float()))
		}

	case reflect.Uint8: // Write the byte-slice as one key,value pair
		en.uvarint(key | 2)
		en.uvarint(uint64(sllen))
		b := slval.Convert(bytesType).Interface().([]byte)
		en.Write(b)
		return

	default: // Write each element as a separate key,value pair
		for i := 0; i < sllen; i++ {
			en.value(key, slval.Index(i), TagNone)
		}
		return
	}

	// Encode packed representation key/value pair
	en.uvarint(key | 2)
	b := packed.Bytes()
	en.uvarint(uint64(len(b)))
	en.Write(b)
}
예제 #9
0
func CanConvert(v reflect.Value, t reflect.Type) (val reflect.Value, canConvert bool) {
	defer func() {
		if r := recover(); r != nil {
		}
	}()

	converted := v.Convert(t)
	return converted, true
}
예제 #10
0
파일: bridge.go 프로젝트: jlebrech/qml
func convertAndSet(to, from reflect.Value) {
	defer func() {
		if v := recover(); v != nil {
			// TODO This should be an error. Test and fix.
			panic("FIXME attempted to set a field with the wrong type; this should be an error")
		}
	}()
	to.Set(from.Convert(to.Type()))
}
예제 #11
0
파일: reflection.go 프로젝트: influx6/gu
// Convert takes a val and converts it into the target type provided if possible.
func Convert(target reflect.Type, val reflect.Value) (reflect.Value, error) {
	valType := val.Type()

	if !valType.ConvertibleTo(target) {
		return reflect.Value{}, errors.New("Can not convert type")
	}

	return val.Convert(target), nil
}
예제 #12
0
파일: convert.go 프로젝트: nrml/convert-go
func convertField(src reflect.Value, dstptr *reflect.Value) error {
	t1 := src.Type()
	t2 := dstptr.Type()
	if t1.ConvertibleTo(t2) {
		resp := src.Convert(t2)
		dstptr.Set(resp)
	}
	return nil
}
예제 #13
0
파일: encode.go 프로젝트: henryren/form
func encodeTime(v reflect.Value) string {
	t := v.Convert(timeType).Interface().(time.Time)
	if t.Year() == 0 && (t.Month() == 0 || t.Month() == 1) && (t.Day() == 0 || t.Day() == 1) {
		return t.Format("15:04:05.999999999Z07:00")
	} else if t.Hour() == 0 && t.Minute() == 0 && t.Second() == 0 && t.Nanosecond() == 0 {
		return t.Format("2006-01-02")
	}
	return t.Format("2006-01-02T15:04:05.999999999Z07:00")
}
예제 #14
0
파일: encode.go 프로젝트: samsalisbury/yaml
func (e *encoder) itemsv(tag string, in reflect.Value) {
	e.mappingv(tag, func() {
		slice := in.Convert(reflect.TypeOf([]MapItem{})).Interface().([]MapItem)
		for _, item := range slice {
			e.marshal("", reflect.ValueOf(item.Key))
			e.marshal("", reflect.ValueOf(item.Value))
		}
	})
}
예제 #15
0
func tryConvert(in reflect.Value, t reflect.Type) (out reflect.Value, err error) {
	defer func() {
		if r := recover(); r != nil {
			err = fmt.Errorf("%s", r)
		}
	}()

	return in.Convert(t), nil
}
예제 #16
0
func populateValue(name string, sourceType reflect.Type, sourceValue reflect.Value, destType reflect.Type, destValue reflect.Value) error {
	if sourceType.Kind() == reflect.Interface {
		sourceValue = sourceValue.Elem()
		sourceType = sourceValue.Type()
	}

	if sourceType.Kind() == reflect.Ptr {
		if sourceValue.IsNil() {
			return nil
		}

		sourceValue = sourceValue.Elem()
		sourceType = sourceValue.Type()
	}

	if destType.Kind() == reflect.Ptr {
		if destValue.IsNil() {
			destValue.Set(reflect.New(destType.Elem()))
		}

		destValue = destValue.Elem()
		destType = destValue.Type()
	}

	switch destType.Kind() {
	case reflect.Array, reflect.Slice:
		if sourceType.Kind() != reflect.Array {
			return bowtie.NewError(http.StatusBadRequest, "%s.type.invalid", name)
		}

		return populateArray(name, sourceType, sourceValue, destType, destValue)

	case reflect.Struct:
		switch sourceType.Kind() {
		case reflect.Struct, reflect.Map:
			return populateStruct(name, sourceType, sourceValue, destType, destValue)

		default:
			return bowtie.NewError(http.StatusBadRequest, "%s.type.invalid", name)
		}

	default:
		if !sourceValue.Type().ConvertibleTo(destType) {
			return bowtie.NewError(http.StatusBadRequest, "%s.type.invalid", name)
		}

		if destType.Kind() == reflect.String && sourceType.Kind() == reflect.Int {
			return bowtie.NewError(http.StatusBadRequest, "%s.type.invalid", name)
		} else {
			destValue.Set(sourceValue.Convert(destType))
		}

	}

	return nil
}
예제 #17
0
func doChanWrite(valCh, argVal reflect.Value) {
	chType := valCh.Type().Elem()
	if argVal.Type().ConvertibleTo(chType) {
		argVal = argVal.Convert(chType)
	}

	for {
		valCh.Send(argVal)
	}
}
예제 #18
0
파일: serialize.go 프로젝트: newgogo/Exis
// attempts to convert a value to another; is a no-op if it's already assignable to the type
func convert(val reflect.Value, typ reflect.Type) (reflect.Value, error) {
	valType := val.Type()
	if !valType.AssignableTo(typ) {
		if valType.ConvertibleTo(typ) {
			return val.Convert(typ), nil
		} else {
			return val, fmt.Errorf("type %s not convertible to %s", valType.Kind(), typ.Kind())
		}
	}
	return val, nil
}
예제 #19
0
파일: util.go 프로젝트: raff/eval
func promoteUntypedNumeral(untyped reflect.Value, to reflect.Type) (reflect.Value, error) {
	// The only valid promotion that cannot be directly converted is int|float -> complex
	if untyped.Type().ConvertibleTo(to) {
		return untyped.Convert(to), nil
	} else if to.Kind() == reflect.Complex64 || to.Kind() == reflect.Complex128 {
		floatType := reflect.TypeOf(float64(0))
		if untyped.Type().ConvertibleTo(floatType) {
			return reflect.ValueOf(complex(untyped.Convert(floatType).Float(), 0)), nil
		}
	}
	return reflect.Value{}, errors.New(fmt.Sprintf("cannot convert %v to %v", untyped, to))
}
예제 #20
0
func callbackRetFloat(ctx *C.sqlite3_context, v reflect.Value) error {
	switch v.Type().Kind() {
	case reflect.Float64:
	case reflect.Float32:
		v = v.Convert(reflect.TypeOf(float64(0)))
	default:
		return fmt.Errorf("cannot convert %s to FLOAT", v.Type())
	}

	C.sqlite3_result_double(ctx, C.double(v.Interface().(float64)))
	return nil
}
예제 #21
0
파일: svccfg.go 프로젝트: chogaths/robin
func fillStructValue(fieldValue reflect.Value, sourceValue reflect.Value, fieldName string) {
	switch fieldValue.Kind() {
	case reflect.Invalid:
		log.Printf("field not match '%s'", fieldName)
		return
	case reflect.Ptr:

		newPtrValue := reflect.New(fieldValue.Type().Elem())

		if newPtrValue.Elem().Kind() != reflect.Struct {
			if newPtrValue.Type().Elem() != sourceValue.Type() {
				sourceValue = sourceValue.Convert(newPtrValue.Type().Elem())
			}

			// 设置new出来的值
			newPtrValue.Elem().Set(sourceValue)

		} else {

			obj := sourceValue.Interface().(map[string]interface{})

			fillStruct(obj, newPtrValue)
		}

		// 设置new出来的ptr给field
		fieldValue.Set(newPtrValue)

	case reflect.Slice:

		if sourceValue.Kind() != reflect.Slice {
			log.Printf("should add [] to repeated field '%s'", fieldName)
			return
		}

		sliceValue := reflect.MakeSlice(fieldValue.Type(), sourceValue.Len(), sourceValue.Len())

		for i := 0; i < sourceValue.Len(); i++ {

			arrValue := sourceValue.Index(i)

			arrField := sliceValue.Index(i)

			if arrValue.Kind() == reflect.Interface {
				arrValue = reflect.ValueOf(arrValue.Interface())
			}

			arrField.Set(arrValue)
		}

		fieldValue.Set(sliceValue)
	}
}
예제 #22
0
파일: call.go 프로젝트: ttthzy/qlang
func validateType(in *reflect.Value, t, tfn reflect.Type) {

	kind := in.Kind()
	if kind == reflect.Invalid {
		*in = reflect.Zero(t) // work around `reflect: Call using zero Value argument`
		return
	}

	tkind := t.Kind()
	if tkind == reflect.Interface {
		if tfn != nil && qlang.DontTyNormalize[tfn] { // don't normalize input type
			return
		}
		switch {
		case kind > reflect.Int && kind <= reflect.Int64:
			*in = reflect.ValueOf(int(in.Int()))
		case kind >= reflect.Uint && kind <= reflect.Uintptr:
			*in = reflect.ValueOf(int(in.Uint()))
		case kind == reflect.Float32:
			*in = reflect.ValueOf(in.Float())
		}
		return
	}

	tin := in.Type()
	if tin == t {
		return
	}

	switch tkind {
	case reflect.Struct:
		if kind == reflect.Ptr {
			tin = tin.Elem()
			if tin == t {
				*in = in.Elem()
				return
			}
		}
	case reflect.Func:
		if tin == typeFunction {
			function2Func(in, t)
			return
		}
	default:
		if tkind == kind || convertible(kind, tkind) {
			*in = in.Convert(t)
			return
		}
	}
	panic(fmt.Errorf("invalid argument type: require `%v`, but we got `%v`", t, tin))
}
예제 #23
0
파일: bridge.go 프로젝트: jlebrech/qml
func convertParam(methodName string, index int, param reflect.Value, argt reflect.Type) (newv reflect.Value, err error) {
	defer func() {
		if panicv := recover(); panicv != nil {
			const prefix = "reflect.Value.Convert: "
			if s, ok := panicv.(string); ok && strings.HasPrefix(s, prefix) {
				err = fmt.Errorf("cannot convert parameter %d of method %s from %s to %s (got %#v)",
					index, methodName, param.Type().Name(), argt.Name(), param.Interface())
			} else {
				panic(panicv)
			}
		}
	}()
	return param.Convert(argt), nil
}
예제 #24
0
// assignValue assignes a value 'pv' to the struct pointed to by 'val', given a
// slice of field indices. It recurses into the struct until it finds the field
// specified by the indices. It creates new values for pointer types where
// needed.
func assignValue(val reflect.Value, fi []int, pv reflect.Value) {
	// Create new value if necessary.
	if val.Kind() == reflect.Ptr {
		if val.IsNil() {
			val.Set(reflect.New(val.Type().Elem()))
		}

		val = val.Elem()
	}

	rv := val.Field(fi[0])
	fi = fi[1:]
	if len(fi) == 0 {
		rt := rv.Type()
		pt := pv.Type()

		// If type is a pointer, create new instance of type.
		if rt.Kind() == reflect.Ptr {
			rv.Set(reflect.New(rt.Elem()))
			rv = rv.Elem()
			rt = rv.Type()
		}

		// If type is an interface, check if pv implements it.
		if rt.Kind() == reflect.Interface && !pt.Implements(rt) {
			// Check if pointer to pv implements it.
			if reflect.PtrTo(pt).Implements(rt) {
				npv := reflect.New(pt)
				npv.Elem().Set(pv)
				pv = npv
				pt = pv.Type()
			} else {
				panic(fmt.Sprintf("type %s doesn't implement %s", pt.Name(), rt.Name()))
			}
		}

		if pt.AssignableTo(rt) {
			rv.Set(pv)
		} else if rt.ConvertibleTo(pt) {
			rv.Set(pv.Convert(rt))
		} else {
			panic(fmt.Sprintf("cannot assign %s (%s) to %s (%s)", rt.Name(), rt.Kind(), pt.Name(), pt.Kind()))
		}

		return
	}

	assignValue(rv, fi, pv)
}
예제 #25
0
func deStructScalar(dataValue reflect.Value) (interface{}, interface{}, map[string]interface{}) {
	if !dataValue.IsValid() {
		return nil, nil, map[string]interface{}{}
	}

	var newData interface{}
	// here we convert the value to it's underlaying kind. This is so that if you do `type myint int`, we drop the `myint` and get a plain `int`. This is necessary so that during string conversion, we don't have any interface such as `Error()` or `String()` which might return different values.
	if convertType, ok := scalarConversionMap[dataValue.Kind()]; ok {
		newData = dataValue.Convert(convertType).Interface()
	} else {
		// chan, func, or something else. just pass it through
		newData = dataValue.Interface()
	}

	return dataValue.Interface(), newData, map[string]interface{}{}
}
예제 #26
0
파일: bridge.go 프로젝트: pmeido/Arianrhod
func convertAndSet(to, from reflect.Value, setMethod reflect.Value) (err error) {
	var toType reflect.Type
	if setMethod.IsValid() {
		toType = setMethod.Type().In(0)
	} else {
		toType = to.Type()
	}
	fromType := from.Type()
	defer func() {
		// TODO This is catching more than it should. There are calls
		//      to custom code below that should be isolated.
		if v := recover(); v != nil {
			err = fmt.Errorf("cannot use %s as a %s", fromType, toType)
		}
	}()
	if fromType == typeList && toType.Kind() == reflect.Slice {
		list := from.Interface().(*List)
		from = reflect.MakeSlice(toType, len(list.data), len(list.data))
		elemType := toType.Elem()
		for i, elem := range list.data {
			from.Index(i).Set(reflect.ValueOf(elem).Convert(elemType))
		}
	} else if fromType == typeMap && toType.Kind() == reflect.Map {
		qmap := from.Interface().(*Map)
		from = reflect.MakeMap(toType)
		elemType := toType.Elem()
		for i := 0; i < len(qmap.data); i += 2 {
			key := reflect.ValueOf(qmap.data[i])
			val := reflect.ValueOf(qmap.data[i+1])
			if val.Type() != elemType {
				val = val.Convert(elemType)
			}
			from.SetMapIndex(key, val)
		}
	} else if toType != fromType {
		from = from.Convert(toType)
	}
	if setMethod.IsValid() {
		setMethod.Call([]reflect.Value{from})
	} else {
		to.Set(from)
	}
	return nil
}
예제 #27
0
func callbackRetInteger(ctx *C.sqlite3_context, v reflect.Value) error {
	switch v.Type().Kind() {
	case reflect.Int64:
	case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Int, reflect.Uint:
		v = v.Convert(reflect.TypeOf(int64(0)))
	case reflect.Bool:
		b := v.Interface().(bool)
		if b {
			v = reflect.ValueOf(int64(1))
		} else {
			v = reflect.ValueOf(int64(0))
		}
	default:
		return fmt.Errorf("cannot convert %s to INTEGER", v.Type())
	}

	C.sqlite3_result_int64(ctx, C.sqlite3_int64(v.Interface().(int64)))
	return nil
}
예제 #28
0
파일: bridge.go 프로젝트: janimo/qml
func convertAndSet(to, from reflect.Value) {
	defer func() {
		if v := recover(); v != nil {
			// TODO This should be an error. Test and fix.
			panic("FIXME attempted to set a field with the wrong type; this should be an error")
		}
	}()
	toType := to.Type()
	fromType := from.Type()
	if toType == fromType {
		to.Set(from)
	} else if fromType == listType && to.Kind() == reflect.Slice {
		list := from.Interface().(*List)
		to.Set(reflect.MakeSlice(toType, len(list.data), len(list.data)))
		elemType := toType.Elem()
		for i, elem := range list.data {
			to.Index(i).Set(reflect.ValueOf(elem).Convert(elemType))
		}
	} else {
		to.Set(from.Convert(toType))
	}
}
예제 #29
0
// hydrate the i'th field of the value from a map entry
func hydrateField(s map[string]interface{}, v reflect.Value, i int) error {
	var err error
	var mfv reflect.Value
	fv := v.Field(i)
	ft := v.Type().Field(i)

	if sv, ok := s[lF(ft.Name)]; ok && sv != nil {
		mfv = reflect.ValueOf(sv)
		switch ft.Type.Kind() {
		case reflect.Struct:
			if svMap, ok := sv.(map[string]interface{}); !ok {
				return fmt.Errorf("failed to convert value to map")
			} else {
				if err := hydrate(svMap, fv.Addr().Interface()); err != nil {
					return fmt.Errorf("hydrateField: failed to hydrate %+v", ft)
				}
				return nil
			}
		case reflect.Slice:
			if mfv.Kind() != reflect.Slice {
				return fmt.Errorf("hydrateField: while processing '%+v': failed to map '%v' to slice: value=%v", ft.Name, mfv.Kind(), fv)
			} else {
				if mfv, err = hydrateSlice(mfv, ft); err != nil {
					return err
				}
			}
		case reflect.Ptr:
			nfv := reflect.New(ft.Type.Elem())
			reflect.Indirect(nfv).Set(mfv.Convert(ft.Type.Elem()))
			mfv = nfv
		}
	} else {
		mfv = reflect.Zero(ft.Type)
	}

	fv.Set(mfv.Convert(ft.Type))
	return nil
}
예제 #30
0
func (c *Config) configureScalar(v, config reflect.Value, path string) error {
	if !config.IsValid() {
		switch v.Kind() {
		case reflect.Interface, reflect.Ptr, reflect.Map, reflect.Slice:
			v.Set(reflect.Zero(v.Type()))
			// otherwise, ignore null for primitives/string
		}
		return nil
	}

	// nil interface
	if v.Kind() == reflect.Interface && v.NumMethod() == 0 {
		v.Set(config)
		return nil
	}

	if config.Type().ConvertibleTo(v.Type()) {
		v.Set(config.Convert(v.Type()))
		return nil
	}

	return &ConfigValueError{path, fmt.Sprintf("%v cannot be used to configure %v", config.Type(), v.Type())}
}