// 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 }
// 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) }
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 }
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) } }
// 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)) }
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 }
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 }
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) }
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 }
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())) }
// 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 }
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 }
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") }
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)) } }) }
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 }
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 }
func doChanWrite(valCh, argVal reflect.Value) { chType := valCh.Type().Elem() if argVal.Type().ConvertibleTo(chType) { argVal = argVal.Convert(chType) } for { valCh.Send(argVal) } }
// 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 }
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)) }
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 }
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) } }
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)) }
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 }
// 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) }
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{}{} }
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 }
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 }
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)) } }
// 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 }
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())} }