Example #1
0
File: mque.go Project: influx6/gu
// Run recevies the argument and
func (m *mqueSub) Run(d interface{}, ctype reflect.Type) {
	if !m.has {
		for _, tm := range m.tms {
			tm.Call([]reflect.Value{})
		}

		return
	}

	var configVal reflect.Value

	if !ctype.AssignableTo(m.am) {
		if !ctype.ConvertibleTo(m.am) {
			return
		}

		vum := reflect.ValueOf(d)
		configVal = vum.Convert(m.am)
	} else {
		configVal = reflect.ValueOf(d)
	}

	for _, tm := range m.tms {
		tm.Call([]reflect.Value{configVal})
	}
}
Example #2
0
func makeDecoder(typ reflect.Type, tags tags) (dec decoder, err error) {
	kind := typ.Kind()
	switch {
	case typ == rawValueType:
		return decodeRawValue, nil
	case typ.Implements(decoderInterface):
		return decodeDecoder, nil
	case kind != reflect.Ptr && reflect.PtrTo(typ).Implements(decoderInterface):
		return decodeDecoderNoPtr, nil
	case typ.AssignableTo(reflect.PtrTo(bigInt)):
		return decodeBigInt, nil
	case typ.AssignableTo(bigInt):
		return decodeBigIntNoPtr, nil
	case isUint(kind):
		return decodeUint, nil
	case kind == reflect.Bool:
		return decodeBool, nil
	case kind == reflect.String:
		return decodeString, nil
	case kind == reflect.Slice || kind == reflect.Array:
		return makeListDecoder(typ, tags)
	case kind == reflect.Struct:
		return makeStructDecoder(typ)
	case kind == reflect.Ptr:
		if tags.nilOK {
			return makeOptionalPtrDecoder(typ)
		}
		return makePtrDecoder(typ)
	case kind == reflect.Interface:
		return decodeInterface, nil
	default:
		return nil, fmt.Errorf("rlp: type %v is not RLP-serializable", typ)
	}
}
Example #3
0
// makeWriter creates a writer function for the given type.
func makeWriter(typ reflect.Type) (writer, error) {
	kind := typ.Kind()
	switch {
	case typ.Implements(encoderInterface):
		return writeEncoder, nil
	case kind != reflect.Ptr && reflect.PtrTo(typ).Implements(encoderInterface):
		return writeEncoderNoPtr, nil
	case kind == reflect.Interface:
		return writeInterface, nil
	case typ.AssignableTo(reflect.PtrTo(bigInt)):
		return writeBigIntPtr, nil
	case typ.AssignableTo(bigInt):
		return writeBigIntNoPtr, nil
	case isUint(kind):
		return writeUint, nil
	case kind == reflect.Bool:
		return writeBool, nil
	case kind == reflect.String:
		return writeString, nil
	case kind == reflect.Slice && isByte(typ.Elem()):
		return writeBytes, nil
	case kind == reflect.Array && isByte(typ.Elem()):
		return writeByteArray, nil
	case kind == reflect.Slice || kind == reflect.Array:
		return makeSliceWriter(typ)
	case kind == reflect.Struct:
		return makeStructWriter(typ)
	case kind == reflect.Ptr:
		return makePtrWriter(typ)
	default:
		return nil, fmt.Errorf("rlp: type %v is not RLP-serializable", typ)
	}
}
func mustBeCompatible(a, b reflect.Type) {
	if !a.ConvertibleTo(b) || !a.AssignableTo(b) {
		panic(errors.New(fmt.Sprintf(
			"Types '%v' and '%v' is not compatile to each other! "+
				"It is no possible to make a swap function that "+
				"return or receive different kinds of objects!", a.Name(), b.Name())))
	}
}
Example #5
0
func assignable(to, from reflect.Type) bool {
	if from == nil {
		switch to.Kind() {
		case reflect.Chan, reflect.Interface, reflect.Map, reflect.Ptr, reflect.Slice, reflect.Func:
			return true
		}
		return false
	}
	return from.AssignableTo(to)
}
Example #6
0
File: mque.go Project: influx6/gu
// CanRun returns whether the argument can be used with this subscriber.
func (m *mqueSub) CanRun(d reflect.Type) bool {
	if !d.AssignableTo(m.am) {
		// if d.ConvertibleTo(m.am) {
		// 	return true
		// }

		return false
	}

	return true
}
Example #7
0
// CanSetForType checks if a val reflect.Type can be used for the target type.
// It returns true bool, where the first returns if the value can be used and if
// it must be converted into the type first.
func CanSetForType(target, val reflect.Type) (canSet bool, mustConvert bool) {
	if val.AssignableTo(target) {
		canSet = true
		return
	}

	if val.ConvertibleTo(target) {
		canSet = true
		mustConvert = true
		return
	}

	return
}
Example #8
0
func unmarshalToType(typ reflect.Type, value string) (val interface{}, err error) {
	// If we get a pointer in, we'll return a pointer out
	if typ.Kind() == reflect.Ptr {
		val = reflect.New(typ.Elem()).Interface()
	} else {
		val = reflect.New(typ).Interface()
	}
	defer func() {
		if err == nil && typ.Kind() != reflect.Ptr {
			val = reflect.Indirect(reflect.ValueOf(val)).Interface()
		}
	}()

	// If we can just assign the value, return the value
	if typ.AssignableTo(reflect.TypeOf(value)) {
		return value, nil
	}

	// Try Unmarshalers
	if um, ok := val.(encoding.TextUnmarshaler); ok {
		if err = um.UnmarshalText([]byte(value)); err == nil {
			return val, nil
		}
	}
	if um, ok := val.(json.Unmarshaler); ok {
		if err = um.UnmarshalJSON([]byte(value)); err == nil {
			return val, nil
		}
	}

	// Try conversion
	if typ.ConvertibleTo(reflect.TypeOf(value)) {
		return reflect.ValueOf(value).Convert(typ).Interface(), nil
	}

	// Try JSON
	if err = json.Unmarshal([]byte(value), val); err == nil {
		return val, nil
	}

	// Return error if we have one
	if err != nil {
		return nil, err
	}

	return val, fmt.Errorf("No way to unmarshal \"%s\" to %s", value, typ.Name())
}
Example #9
0
func (s *schemaField) check(ft reflect.Type, v interface{}) error {
	t := reflect.TypeOf(v)
	if !ft.AssignableTo(t) {
		if !ft.ConvertibleTo(t) {
			return fmt.Errorf("type %s (%v) cannot be converted to %T", ft.Name(), ft.Kind(), t.Name())
		}

		s.marshalType = t
	}

	if !t.AssignableTo(ft) {
		if !t.ConvertibleTo(ft) {
			return fmt.Errorf("type %s (%v) cannot be converted to %T", t.Name(), t.Kind(), ft.Name())
		}

		s.unmarshalType = ft
	}
	return nil
}
Example #10
0
// converts in to an expression of type OutT.
// also serves as type check (not convertible == type error)
// pos is used for error message on impossible conversion.
func typeConv(pos token.Pos, in Expr, outT reflect.Type) Expr {
	inT := in.Type()
	switch {
	default:
		panic(err(pos, "type mismatch: can not use type", inT, "as", outT))

	// treat 'void' (type nil) separately:
	case inT == nil && outT != nil:
		panic(err(pos, "void used as value"))
	case inT != nil && outT == nil:
		panic("script internal bug: void input type")

	// strict go conversions:
	case inT == outT:
		return in
	case inT.AssignableTo(outT):
		return in

	// extra conversions for ease-of-use:
	// int -> float64
	case outT == float64_t && inT == int_t:
		return &intToFloat64{in}

	// float64 -> int
	case outT == int_t && inT == float64_t:
		return &float64ToInt{in}

	case outT == float64_t && inT.AssignableTo(ScalarIf_t):
		return &getScalar{in.Eval().(ScalarIf)}
	case outT == float64_t && inT.AssignableTo(VectorIf_t):
		return &getVector{in.Eval().(VectorIf)}

	// magical expression -> function conversions
	case inT == float64_t && outT.AssignableTo(ScalarFunction_t):
		return &scalFn{in}
	case inT == int_t && outT.AssignableTo(ScalarFunction_t):
		return &scalFn{&intToFloat64{in}}
	case inT == vector_t && outT.AssignableTo(VectorFunction_t):
		return &vecFn{in}
	case inT == bool_t && outT == func_bool_t:
		return &boolToFunc{in}
	}
}
Example #11
0
func isDurationField(t reflect.Type) bool {
	return t.AssignableTo(durationType)
}
Example #12
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}
}
Example #13
0
// suitableMethods returns suitable Rpc methods of typ, it will report
// error using logger if reportErr is true.
func (server *Server) suitableMethods(rcvr interface{}, s *service, typ reflect.Type, reportErr bool, rcvrFns ...interface{}) map[uint32]*methodType {
	methods := s.method

	if typ.AssignableTo(reflect.TypeOf((**lua.LTable)(nil)).Elem()) {

		if len(rcvrFns) > 0 {

			rcvrFns[0].(*lua.LTable).ForEach(func(key, value lua.LValue) {
				//logger.Debug("ForEach LTable :%v, %v", key, value)
				if key.Type() == lua.LTString && value.Type() == lua.LTFunction && value.(*lua.LFunction).Proto.NumParameters == 3 {
					method, ok := reflect.TypeOf(server).MethodByName("CallLua")

					if !ok {
						logger.Debug("regist MethodByName error :%v", key.String())
					}

					mtype := method.Type
					mname := method.Name

					// Second arg need not be a pointer.
					argType := mtype.In(2)
					if !isExportedOrBuiltinType(argType) {
						if reportErr {
							logger.Info("%s argument type not exported: %s", mname, argType)
						}
						//continue
					}

					methods[server.protocol[key.String()]] = &methodType{method: method, ArgType: argType, luaMethod: value.(*lua.LFunction)}

					logger.Debug("regist %v", key.String())
				}
			})

		}

	} else {

		for m := 0; m < typ.NumMethod(); m++ {
			method := typ.Method(m)
			mtype := method.Type
			mname := method.Name

			//fmt.Printf("suitableMethods %s, %s, %s, %d \n", mtype, mname, method.PkgPath, mtype.NumIn())
			// Method must be exported.
			if method.PkgPath != "" {
				continue
			}

			// Method needs three ins: receiver, connid, *args.
			if mtype.NumIn() != 3 {
				if reportErr {
					logger.Info("method %s has wrong number of ins: %v", mname, mtype.NumIn())
				}
				continue
			}

			idType := mtype.In(1)

			if !idType.AssignableTo(reflect.TypeOf((*RpcConn)(nil)).Elem()) {
				if reportErr {
					logger.Info("%s conn %s must be %s", mname, idType.Name(), reflect.TypeOf((*RpcConn)(nil)).Elem().Name())
				}
				continue
			}

			// Second arg need not be a pointer.
			argType := mtype.In(2)
			if !isExportedOrBuiltinType(argType) {
				if reportErr {
					logger.Info("%s argument type not exported: %s", mname, argType)
				}
				continue
			}

			// Method needs one out.
			if mtype.NumOut() != 1 {
				if reportErr {
					logger.Info("method %s has wrong number of outs: %v", mname, mtype.NumOut())
				}
				continue
			}
			// The return type of the method must be error.
			if returnType := mtype.Out(0); returnType != typeOfError {
				if reportErr {
					logger.Info("method %s returns %s not error", mname, returnType.String())
				}
				continue
			}
			methods[server.protocol[mname]] = &methodType{method: method, ArgType: argType}
			logger.Debug("suitableMethods protocol %v, %d, %v", mname, server.protocol[mname], methods[server.protocol[mname]])
		}
	}

	return methods
}
Example #14
0
// Determines if two types can be automatically converted between.
func areTypesCompatible(xt, yt reflect.Type) bool {
	return xt.AssignableTo(unhackType(yt)) || yt.AssignableTo(unhackType(xt))
}
Example #15
0
// newTypeDecoder constructs an decoderFunc for a type.
func newTypeDecoder(dt, st reflect.Type, blank bool) decoderFunc {
	if reflect.PtrTo(dt).Implements(unmarshalerType) ||
		dt.Implements(unmarshalerType) {
		return unmarshalerDecoder
	}

	if st.Kind() == reflect.Interface {
		return newInterfaceAsTypeDecoder(blank)
	}

	switch dt.Kind() {
	case reflect.Bool:
		switch st.Kind() {
		case reflect.Bool:
			return boolAsBoolDecoder
		case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
			return intAsBoolDecoder
		case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
			return uintAsBoolDecoder
		case reflect.Float32, reflect.Float64:
			return floatAsBoolDecoder
		case reflect.String:
			return stringAsBoolDecoder
		default:
			return decodeTypeError
		}
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		switch st.Kind() {
		case reflect.Bool:
			return boolAsIntDecoder
		case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
			return intAsIntDecoder
		case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
			return uintAsIntDecoder
		case reflect.Float32, reflect.Float64:
			return floatAsIntDecoder
		case reflect.String:
			return stringAsIntDecoder
		default:
			return decodeTypeError
		}
	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
		switch st.Kind() {
		case reflect.Bool:
			return boolAsUintDecoder
		case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
			return intAsUintDecoder
		case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
			return uintAsUintDecoder
		case reflect.Float32, reflect.Float64:
			return floatAsUintDecoder
		case reflect.String:
			return stringAsUintDecoder
		default:
			return decodeTypeError
		}
	case reflect.Float32, reflect.Float64:
		switch st.Kind() {
		case reflect.Bool:
			return boolAsFloatDecoder
		case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
			return intAsFloatDecoder
		case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
			return uintAsFloatDecoder
		case reflect.Float32, reflect.Float64:
			return floatAsFloatDecoder
		case reflect.String:
			return stringAsFloatDecoder
		default:
			return decodeTypeError
		}
	case reflect.String:
		switch st.Kind() {
		case reflect.Bool:
			return boolAsStringDecoder
		case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
			return intAsStringDecoder
		case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
			return uintAsStringDecoder
		case reflect.Float32, reflect.Float64:
			return floatAsStringDecoder
		case reflect.String:
			return stringAsStringDecoder
		default:
			return decodeTypeError
		}
	case reflect.Interface:
		if !st.AssignableTo(dt) {
			return decodeTypeError
		}

		return interfaceDecoder
	case reflect.Ptr:
		return newPtrDecoder(dt, st, blank)
	case reflect.Map:
		if st.AssignableTo(dt) {
			return interfaceDecoder
		}

		switch st.Kind() {
		case reflect.Map:
			return newMapAsMapDecoder(dt, st, blank)
		default:
			return decodeTypeError
		}
	case reflect.Struct:
		if st.AssignableTo(dt) {
			return interfaceDecoder
		}

		switch st.Kind() {
		case reflect.Map:
			if kind := st.Key().Kind(); kind != reflect.String && kind != reflect.Interface {
				return newDecodeTypeError(fmt.Errorf("map needs string keys"))
			}

			return newMapAsStructDecoder(dt, st, blank)
		default:
			return decodeTypeError
		}
	case reflect.Slice:
		if st.AssignableTo(dt) {
			return interfaceDecoder
		}

		switch st.Kind() {
		case reflect.Array, reflect.Slice:
			return newSliceDecoder(dt, st)
		default:
			return decodeTypeError
		}
	case reflect.Array:
		if st.AssignableTo(dt) {
			return interfaceDecoder
		}

		switch st.Kind() {
		case reflect.Array, reflect.Slice:
			return newArrayDecoder(dt, st)
		default:
			return decodeTypeError
		}
	default:
		return unsupportedTypeDecoder
	}
}
Example #16
0
// When implements Resolver.WhenT().
func (s *turnResolver) WhenT(in, out, outR reflect.Type, f interface{}) async.ResultT {
	// Validate function type - this is in lieu of static type checking from generics.
	fType := reflect.TypeOf(f)
	assert.True(fType.Kind() == reflect.Func, "f MUST be a WhenFunc")

	// Validate inputs - this is in lieu of static type checking from generics.
	assert.True(fType.NumIn() <= 2, "f MUST take val, err, both or neither")
	takeValue, takeError := true, true
	if numIn := fType.NumIn(); numIn == 2 {
		assert.True(in.AssignableTo(fType.In(0)), "in MUST be assignable to value")
		assert.True(fType.In(1) == reflectTypeError, "f MUST take err")
	} else if numIn == 1 {
		takeError = (fType.In(0) == reflectTypeError)
		takeValue = !takeError
		if takeValue {
			assert.True(in.AssignableTo(fType.In(0)), "in MUST be assignable to value")
		} else {
			assert.True(fType.In(0) == reflectTypeError, "f MUST take err")
		}
	} else if numIn == 0 {
		takeValue, takeError = false, false
	}

	// Validate outputs - this is in lieu of static type checking from generics.
	assert.True(fType.NumOut() <= 2, "f MUST return val, (val, err), or async")
	returnsResult := false
	if numOut := fType.NumOut(); numOut == 2 {
		assert.True(fType.Out(0).AssignableTo(out), "value MUST be assignable to out")
		assert.True(fType.Out(1) == reflectTypeError, "err MUST be error")
	} else if numOut == 1 {
		if fType.Out(0).Implements(reflectTypeAwaitableT) {
			returnsResult = true
			assert.True(fType.Out(0) == outR, "result MUST be ResultT")
		} else if fType.Out(0) == reflectTypeError {
			assert.True(out == reflectTypeInterface, "func() error ONLY allowed on void results")
		} else {
			assert.True(fType.Out(0).AssignableTo(out), "value MUST be assignable to out")
		}
	} else {
		assert.True(out == reflectTypeInterface, "func() ONLY allowed on void results")
	}

	// If this result is already forwarded then just forward the When as well.
	if s.next != nil {
		return s.getShortest().WhenT(in, out, outR, f)
	}

	// Create a new turn that will run once the result is resolved.
	outer := newTurnResolver(s.manager)
	turn := NewTurn("When"+s.manager.NewID().String(), func() {
		// Find the resolved value.
		final := s.getShortest()
		assert.True(final.isResolved(), "When's shouldn't run if the target is not resolved.")

		// Distinguish the error from the value.
		value := final.outcome
		err, isError := final.outcome.(error)
		if isError {
			value = nil
		}

		// If f doesn't take an error but the previous computation failed, then just flow it through to
		// the output by failing immediately.  This allows for null-style error propagation which
		// simplifies handlers since that is a very common case.  f is NEVER called in this case under
		// the assumption that its first line would be: if err != nil { return err }.
		if !takeError {
			if err != nil {
				outer.Fail(err)
				return
			}
		}

		// Convert the arguments into an array of Values
		args := make([]reflect.Value, 0, 2)
		if takeValue {
			if value == nil {
				args = append(args, reflect.New(in).Elem())
			} else {
				args = append(args, reflect.ValueOf(value))
			}
		}
		if takeError {
			if err == nil {
				args = append(args, reflect.New(reflectTypeError).Elem())
			} else {
				args = append(args, reflect.ValueOf(err))
			}
		}

		// Dispatch the result to the WhenFunc.
		retvals := reflect.ValueOf(f).Call(args)

		// Resolve the outer result.
		if returnsResult {
			outer.Forward(retvals[0].Interface().(async.AwaitableT).Base())
			return
		}
		if numRets := len(retvals); numRets == 2 {
			if err, _ = retvals[1].Interface().(error); err != nil {
				outer.resolve(err)
			} else {
				outer.resolve(retvals[0].Interface())
			}
		} else if numRets == 1 {
			outer.resolve(retvals[0].Interface())
		} else {
			outer.resolve(nil)
		}
	})
	s.queue(turn)
	return async.NewResultT(outer)
}
Example #17
0
func isStorageType(typ reflect.Type) bool {
	return typ == storageType || typ.AssignableTo(storageType)
}
Example #18
0
func AdaptToValue(fr *Frame, a T, ty R.Type) R.Value {
	switch ty.Kind() {
	case R.Bool:
		var tmp bool = a.Bool()
		return R.NewAt(ty, unsafe.Pointer(&tmp)).Elem()

	case R.Int:
		var tmp int = int(a.Int())
		return R.NewAt(ty, unsafe.Pointer(&tmp)).Elem()

	case R.Int8:
		var tmp int8 = int8(a.Int())
		return R.NewAt(ty, unsafe.Pointer(&tmp)).Elem()

	case R.Int16:
		var tmp int16 = int16(a.Int())
		return R.NewAt(ty, unsafe.Pointer(&tmp)).Elem()

	case R.Int32:
		var tmp int32 = int32(a.Int())
		return R.NewAt(ty, unsafe.Pointer(&tmp)).Elem()

	case R.Int64:
		var tmp int64 = a.Int()
		return R.NewAt(ty, unsafe.Pointer(&tmp)).Elem()

	case R.Uint:
		var tmp uint = uint(a.Uint())
		return R.NewAt(ty, unsafe.Pointer(&tmp)).Elem()

	case R.Uint8:
		var tmp uint8 = uint8(a.Uint())
		return R.NewAt(ty, unsafe.Pointer(&tmp)).Elem()

	case R.Uint16:
		var tmp uint16 = uint16(a.Uint())
		return R.NewAt(ty, unsafe.Pointer(&tmp)).Elem()

	case R.Uint32:
		var tmp uint32 = uint32(a.Uint())
		return R.NewAt(ty, unsafe.Pointer(&tmp)).Elem()

	case R.Uint64:
		var tmp uint64 = a.Uint()
		return R.NewAt(ty, unsafe.Pointer(&tmp)).Elem()

	case R.Uintptr:
		var tmp uintptr = uintptr(a.Uint())
		return R.NewAt(ty, unsafe.Pointer(&tmp)).Elem()

	case R.Float32:
		var tmp float32 = float32(a.Float())
		return R.NewAt(ty, unsafe.Pointer(&tmp)).Elem()

	case R.Float64:
		var tmp float64 = a.Float()
		return R.NewAt(ty, unsafe.Pointer(&tmp)).Elem()

	case R.Complex64:
	case R.Complex128:
	case R.Array:
	case R.Chan:
		if a.IsEmpty() {
			log.Printf("AdaptToValue: Nil for Chan (%s), due to IsEmpty.", ty)
			return R.Zero(ty)
		}
	case R.Func:
		if a.IsEmpty() {
			log.Printf("AdaptToValue: Nil for Func (%s), due to IsEmpty.", ty)
			return R.Zero(ty)
		}
		v := R.ValueOf(a)
		if v.Kind() == R.Func {
			return v
		}
	case R.Interface:
		if a.IsEmpty() {
			log.Printf("AdaptToValue: Nil for Interface (%s), due to IsEmpty.", ty)
			return R.Zero(ty)
		}

		// Very special case of T: Return arg as a Value.
		if ty == TypeT { // TODO: why doesn't this work?
			return R.ValueOf(a)
		}
		if ty.AssignableTo(TypeT) { // TODO: why doesn't this work?
			return R.ValueOf(a)
		}
		if ty.String() == "chirp.T" { // TODO: This is fragile & lame, but it works.
			return R.ValueOf(a)
		}
	case R.Map:
	case R.Ptr:
		if a.IsEmpty() {
			log.Printf("AdaptToValue: Nil for Ptr (%s), due to IsEmpty.", ty)
			return R.Zero(ty)
		}
		// Very special case of *Frame:
		framePtrValue := R.ValueOf(fr)
		framePtrType := framePtrValue.Type()
		if ty == framePtrType {
			return framePtrValue
		}
	case R.Slice:
		raw := a.Raw()
		val := R.ValueOf(raw)

		switch ty.Elem().Kind() {
		case R.Uint8:
			var tmp []byte = make([]byte, val.Len())
			copy(tmp, val.String())
			return R.NewAt(ty, unsafe.Pointer(&tmp)).Elem()
		}

	case R.String:
		raw := a.Raw()
		val := R.ValueOf(raw)

		switch val.Kind() {
		case R.Slice:
			switch val.Elem().Kind() {
			case R.Uint8:
				var tmp string = string(val.Bytes())
				return R.NewAt(ty, unsafe.Pointer(&tmp)).Elem()
			}
		}

	case R.Struct:
	case R.UnsafePointer:
	}
	// We haven't checked this is correct;
	//  cmdCall will reject it, if it won't work.
	// But maybe we can do better, so log it.
	if Debug['r'] {
		log.Printf("AdaptToValue: Default: for type <%s>: %s", ty, Show(a))
	}
	return R.ValueOf(a.Raw())
}
Example #19
0
// Determine if type from is assignable to type to. From and To must not be ConstTypes
func typeAssignableTo(from, to reflect.Type) bool {
	return from.AssignableTo(unhackType(to))
}