func labelType(t reflect.Type) bool { switch t.Kind() { case reflect.Interface, reflect.Struct: return true } return false }
// lessFunc returns a function that implements the "<" operator // for the given type, or nil if the type doesn't support "<" . func lessFunc(t reflect.Type) func(v1, v2 interface{}) bool { switch t.Kind() { case reflect.String: return func(v1, v2 interface{}) bool { return v1.(string) < v2.(string) } case reflect.Int: return func(v1, v2 interface{}) bool { return v1.(int) < v2.(int) } case reflect.Int8: return func(v1, v2 interface{}) bool { return v1.(int8) < v2.(int8) } case reflect.Int16: return func(v1, v2 interface{}) bool { return v1.(int16) < v2.(int16) } case reflect.Int32: return func(v1, v2 interface{}) bool { return v1.(int32) < v2.(int32) } case reflect.Int64: return func(v1, v2 interface{}) bool { return v1.(int64) < v2.(int64) } case reflect.Uint: return func(v1, v2 interface{}) bool { return v1.(uint) < v2.(uint) } case reflect.Uint8: return func(v1, v2 interface{}) bool { return v1.(uint8) < v2.(uint8) } case reflect.Uint16: return func(v1, v2 interface{}) bool { return v1.(uint16) < v2.(uint16) } case reflect.Uint32: return func(v1, v2 interface{}) bool { return v1.(uint32) < v2.(uint32) } case reflect.Uint64: return func(v1, v2 interface{}) bool { return v1.(uint64) < v2.(uint64) } case reflect.Float32: return func(v1, v2 interface{}) bool { return v1.(float32) < v2.(float32) } case reflect.Float64: return func(v1, v2 interface{}) bool { return v1.(float64) < v2.(float64) } default: return nil } }
// Copy matching Lua table entries to a struct, given the struct type // and the index on the Lua stack. func CopyTableToStruct(L *lua.State, t reflect.Type, idx int) interface{} { was_ptr := t.Kind() == reflect.Ptr if was_ptr { t = t.Elem() } s := reflect.New(t) // T -> *T ref := s.Elem() L.PushNil() if idx < 0 { idx-- } for L.Next(idx) != 0 { key := L.ToString(-2) f := ref.FieldByName(strings.Title(key)) if f.IsValid() { val := luaToGoValue(L, f.Type(), -1) f.Set(val) } L.Pop(1) } if was_ptr { return s.Interface() } return s.Elem().Interface() }
func getComparator(dt reflect.Type) (funcPointer interface{}) { switch dt.Kind() { case reflect.Int: funcPointer = func(a, b int) int64 { return int64(a - b) } case reflect.Int8: funcPointer = func(a, b int8) int64 { return int64(a - b) } case reflect.Int16: funcPointer = func(a, b int16) int64 { return int64(a - b) } case reflect.Int32: funcPointer = func(a, b int32) int64 { return int64(a - b) } case reflect.Uint: funcPointer = func(a, b uint) int64 { return int64(a - b) } case reflect.Uint8: funcPointer = func(a, b uint8) int64 { return int64(a - b) } case reflect.Uint16: funcPointer = func(a, b uint16) int64 { return int64(a - b) } case reflect.Uint32: funcPointer = func(a, b uint32) int64 { return int64(a - b) } case reflect.Uint64: funcPointer = func(a, b uint64) int64 { return int64(a - b) } case reflect.Int64: funcPointer = func(a, b int64) int64 { return a - b } case reflect.Float32: funcPointer = DefaultFloat32Comparator case reflect.Float64: funcPointer = DefaultFloat64Comparator case reflect.String: funcPointer = DefaultStringComparator default: log.Panicf("No default comparator for %s:%s", dt.String(), dt.Kind().String()) } return }
// canBeNil reports whether an untyped nil can be assigned to the type. See reflect.Zero. // // Copied from Go stdlib src/text/template/exec.go. func canBeNil(typ reflect.Type) bool { switch typ.Kind() { case reflect.Chan, reflect.Func, reflect.Interface, reflect.Map, reflect.Ptr, reflect.Slice: return true } return false }
func getSetter(outt reflect.Type, out reflect.Value) Setter { setterMutex.RLock() style := setterStyle[outt] setterMutex.RUnlock() if style == setterNone { return nil } if style == setterUnknown { setterMutex.Lock() defer setterMutex.Unlock() if outt.Implements(setterIface) { setterStyle[outt] = setterType } else if reflect.PtrTo(outt).Implements(setterIface) { setterStyle[outt] = setterAddr } else { setterStyle[outt] = setterNone return nil } style = setterStyle[outt] } if style == setterAddr { if !out.CanAddr() { return nil } out = out.Addr() } else if outt.Kind() == reflect.Ptr && out.IsNil() { out.Set(reflect.New(outt.Elem())) } return out.Interface().(Setter) }
// sizeof returns the size >= 0 of variables for the given type or -1 if the type is not acceptable. func sizeof(t reflect.Type) int { switch t.Kind() { case reflect.Array: if s := sizeof(t.Elem()); s >= 0 { return s * t.Len() } case reflect.Struct: sum := 0 for i, n := 0, t.NumField(); i < n; i++ { s := sizeof(t.Field(i).Type) if s < 0 { return -1 } sum += s } return sum case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Float32, reflect.Float64, reflect.Complex64, reflect.Complex128, reflect.Ptr: return int(t.Size()) } return -1 }
func defaultType(t reflect.Type) TypeDesc { switch t.Kind() { case reflect.Bool: return BooleanType case reflect.String: return UTF8Type case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: return LongType case reflect.Float32: return FloatType case reflect.Float64: return DoubleType case reflect.Array: if t.Name() == "UUID" && t.Size() == 16 { return UUIDType } return UnknownType case reflect.Struct: if t.Name() == "Time" && t.PkgPath() == "time" { return DateType } return UnknownType case reflect.Slice: if et := t.Elem(); et.Kind() == reflect.Uint8 { return BytesType } return UnknownType } return UnknownType }
// Recursively check composite literals, where a child composite lit's type depends the // parent's type For example, the expression [][]int{{1,2},{3,4}} contains two // slice lits, {1,2} and {3,4}, but their types are inferenced from the parent [][]int{}. func checkCompositeLitR(lit *ast.CompositeLit, t reflect.Type, env Env) (*CompositeLit, []error) { alit := &CompositeLit{CompositeLit: lit} // We won't generate any errors here if the given type does not match lit.Type. // The caller will need to detect the type incompatibility. if lit.Type != nil { var errs []error lit.Type, t, _, errs = checkType(lit.Type, env) if errs != nil { return alit, errs } } else if t == nil { return alit, []error{ErrMissingCompositeLitType{alit}} } alit.knownType = knownType{t} if alit.CompositeLit.Elts != nil { alit.Elts = make([]Expr, len(alit.CompositeLit.Elts)) } switch t.Kind() { case reflect.Map: return checkCompositeLitMap(alit, t, env) case reflect.Array, reflect.Slice: return checkCompositeLitArrayOrSlice(alit, t, env) case reflect.Struct: return checkCompositeLitStruct(alit, t, env) default: panic("eval: unimplemented composite lit " + t.Kind().String()) } }
// Convert a string into the specified type. Return the type's zero value // if we receive an empty string func convert(t reflect.Type, value string) (reflect.Value, error) { if value == "" { return reflect.ValueOf(nil), nil } var d time.Duration switch t { case reflect.TypeOf(d): result, err := time.ParseDuration(value) return reflect.ValueOf(result), err default: } switch t.Kind() { case reflect.String: return reflect.ValueOf(value), nil case reflect.Int: return parseInt(value) case reflect.Bool: return parseBool(value) } return reflect.ValueOf(nil), conversionError(value, `unsupported `+t.Kind().String()) }
func unflattenValue(v reflect.Value, t reflect.Type) reflect.Value { // When t is an Interface, we can't do much, since we don't know the // original (unflattened) type of the value placed in v, so we just nop it. if t.Kind() == reflect.Interface { return v } // v can be invalid, if it holds the nil value for pointer type if !v.IsValid() { return v } // Make sure v is indeed flat if v.Kind() == reflect.Ptr { panic("unflattening non-flat value") } // Add a *, one at a time for t.Kind() == reflect.Ptr { if v.CanAddr() { v = v.Addr() } else { pw := reflect.New(v.Type()) pw.Elem().Set(v) v = pw } t = t.Elem() } return v }
// prepareMethod returns a methodType for the provided method or nil // in case if the method was unsuitable. func prepareMethod(method reflect.Method) *methodType { mtype := method.Type mname := method.Name var replyType, argType, contextType reflect.Type stream := false // Method must be exported. if method.PkgPath != "" { return nil } switch mtype.NumIn() { case 3: // normal method argType = mtype.In(1) replyType = mtype.In(2) contextType = nil case 4: // method that takes a context argType = mtype.In(2) replyType = mtype.In(3) contextType = mtype.In(1) default: log.Println("method", mname, "of", mtype, "has wrong number of ins:", mtype.NumIn()) return nil } // First arg need not be a pointer. if !isExportedOrBuiltinType(argType) { log.Println(mname, "argument type not exported:", argType) return nil } // the second argument will tell us if it's a streaming call // or a regular call if replyType == typeOfStream { // this is a streaming call stream = true } else if replyType.Kind() != reflect.Ptr { log.Println("method", mname, "reply type not a pointer:", replyType) return nil } // Reply type must be exported. if !isExportedOrBuiltinType(replyType) { log.Println("method", mname, "reply type not exported:", replyType) return nil } // Method needs one out. if mtype.NumOut() != 1 { log.Println("method", mname, "has wrong number of outs:", mtype.NumOut()) return nil } // The return type of the method must be error. if returnType := mtype.Out(0); returnType != typeOfError { log.Println("method", mname, "returns", returnType.String(), "not error") return nil } return &methodType{method: method, ArgType: argType, ReplyType: replyType, ContextType: contextType, stream: stream} }
// AddExt registers an encode and decode function for a reflect.Type. // Note that the type must be a named type, and specifically not // a pointer or Interface. An error is returned if that is not honored. // // To Deregister an ext, call AddExt with 0 tag, nil encfn and nil decfn. func (o *extHandle) AddExt( rt reflect.Type, tag byte, encfn func(reflect.Value) ([]byte, error), decfn func(reflect.Value, []byte) error, ) (err error) { // o is a pointer, because we may need to initialize it if rt.PkgPath() == "" || rt.Kind() == reflect.Interface { err = fmt.Errorf("codec.Handle.AddExt: Takes named type, especially not a pointer or interface: %T", reflect.Zero(rt).Interface()) return } // o cannot be nil, since it is always embedded in a Handle. // if nil, let it panic. // if o == nil { // err = errors.New("codec.Handle.AddExt: extHandle cannot be a nil pointer.") // return // } rtid := reflect.ValueOf(rt).Pointer() for _, v := range *o { if v.rtid == rtid { v.tag, v.encFn, v.decFn = tag, encfn, decfn return } } *o = append(*o, &extTypeTagFn{rtid, rt, tag, encfn, decfn}) return }
func sizeof(t reflect.Type) (int, error) { switch t.Kind() { case reflect.Array: n, err := sizeof(t.Elem()) if err != nil { return 0, err } return t.Len() * n, nil case reflect.Struct: sum := 0 for i, n := 0, t.NumField(); i < n; i++ { s, err := sizeof(t.Field(i).Type) if err != nil { return 0, err } sum += s } return sum, nil case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Float32, reflect.Float64, reflect.Complex64, reflect.Complex128: return int(t.Size()), nil } return 0, errors.New("invalid type " + t.String()) }
// alignment returns the alignment of values of type t. func alignment(t reflect.Type) int { switch t { case variantType: return 1 case objectPathType: return 4 case signatureType: return 1 case interfacesType: return 4 } switch t.Kind() { case reflect.Uint8: return 1 case reflect.Uint16, reflect.Int16: return 2 case reflect.Uint32, reflect.Int32, reflect.String, reflect.Array, reflect.Slice, reflect.Map: return 4 case reflect.Uint64, reflect.Int64, reflect.Float64, reflect.Struct: return 8 case reflect.Ptr: return alignment(t.Elem()) } return 1 }
// callSliceRequired returns true if CallSlice is required instead of Call. func callSliceRequired(param reflect.Type, val reflect.Value) bool { vt := val.Type() for param.Kind() == reflect.Slice { if val.Kind() == reflect.Interface { val = reflect.ValueOf(val.Interface()) vt = val.Type() } if vt.Kind() != reflect.Slice { return false } vt = vt.Elem() if val.Kind() != reflect.Invalid { if val.Len() > 0 { val = val.Index(0) } else { val = reflect.Value{} } } param = param.Elem() } return true }
// 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) } }
// implementsInterface reports whether the type implements the // gobEncoder/gobDecoder interface. // It also returns the number of indirections required to get to the // implementation. func implementsInterface(typ, gobEncDecType reflect.Type) (success bool, indir int8) { if typ == nil { return } rt := typ // The type might be a pointer and we need to keep // dereferencing to the base type until we find an implementation. for { if rt.Implements(gobEncDecType) { return true, indir } if p := rt; p.Kind() == reflect.Ptr { indir++ if indir > 100 { // insane number of indirections return false, 0 } rt = p.Elem() continue } break } // No luck yet, but if this is a base type (non-pointer), the pointer might satisfy. if typ.Kind() != reflect.Ptr { // Not a pointer, but does the pointer work? if reflect.PtrTo(typ).Implements(gobEncDecType) { return true, -1 } } return false, 0 }
func fieldType(t reflect.Type) byte { switch t.Kind() { case reflect.Bool: return TypeBool case reflect.Int8, reflect.Uint8: return TypeByte case reflect.Int16: return TypeI16 case reflect.Int32, reflect.Int: return TypeI32 case reflect.Int64: return TypeI64 case reflect.Float64: return TypeDouble case reflect.Map: return TypeMap case reflect.Slice: elemType := t.Elem() if elemType.Kind() == reflect.Uint8 { return TypeString } else { return TypeList } case reflect.Struct: return TypeStruct case reflect.String: return TypeString case reflect.Interface, reflect.Ptr: return fieldType(t.Elem()) } panic(&UnsupportedTypeError{t}) }
// hasUnrecognizedKeys finds unrecognized keys and warns about them on stderr. // returns false when no unrecognized keys were found, true otherwise. func hasUnrecognizedKeys(inCfg interface{}, refType reflect.Type) (warnings bool) { if refType.Kind() == reflect.Ptr { refType = refType.Elem() } switch inCfg.(type) { case map[interface{}]interface{}: ks := inCfg.(map[interface{}]interface{}) keys: for key := range ks { for i := 0; i < refType.NumField(); i++ { sf := refType.Field(i) tv := sf.Tag.Get("yaml") if tv == key { if warn := hasUnrecognizedKeys(ks[key], sf.Type); warn { warnings = true } continue keys } } glog.Errorf("Unrecognized keyword: %v", key) warnings = true } case []interface{}: ks := inCfg.([]interface{}) for i := range ks { if warn := hasUnrecognizedKeys(ks[i], refType.Elem()); warn { warnings = true } } default: } return }
func checkArrayValue(expr ast.Expr, eltT reflect.Type, env Env) (Expr, []error) { switch eltT.Kind() { case reflect.Array, reflect.Slice, reflect.Map, reflect.Struct: if lit, ok := expr.(*ast.CompositeLit); ok { return checkCompositeLitR(lit, eltT, env) } } aexpr, ok, errs := checkExprAssignableTo(expr, eltT, env) if !ok { // NOTE[crc] this hack removes conversion errors from consts other // than strings and nil to match the output of gc. if ccerr, ok := errs[0].(ErrBadConstConversion); ok { if ccerr.from == ConstNil { // No ErrBadArrayValue for nil return aexpr, errs } else if ccerr.from != ConstString { // gc implementation only displays string conversion errors errs = nil } } errs = append(errs, ErrBadArrayValue{aexpr, eltT}) } return aexpr, errs }
// Add all necessary imports for the type, recursing as appropriate. func addImportsForType(imports importMap, t reflect.Type) { // Add any import needed for the type itself. addImportForType(imports, t) // Handle special cases where recursion is needed. switch t.Kind() { case reflect.Array, reflect.Chan, reflect.Ptr, reflect.Slice: addImportsForType(imports, t.Elem()) case reflect.Func: // Input parameters. for i := 0; i < t.NumIn(); i++ { addImportsForType(imports, t.In(i)) } // Return values. for i := 0; i < t.NumOut(); i++ { addImportsForType(imports, t.Out(i)) } case reflect.Map: addImportsForType(imports, t.Key()) addImportsForType(imports, t.Elem()) } }
func generatemethodsEx(t reflect.Type, ignorefunc func(name string) bool, callobject string, name func(t reflect.Type, m reflect.Method) string) (methods string) { t2 := t if t.Kind() == reflect.Ptr { t2 = t.Elem() } for i := 0; i < t.NumMethod(); i++ { var ( m = t.Method(i) reason string ) if m.Name[0] != strings.ToUpper(m.Name[:1])[0] { reason = "unexported" goto skip } if ignorefunc != nil && ignorefunc(m.Name) { reason = "in skip list" goto skip } if m, err := generatemethod(m, t2, callobject, name(t2, m)); err != nil { reason = err.Error() goto skip } else { methods += m } continue skip: fmt.Printf("Skipping method %s.%s: %s\n", t2, m.Name, reason) } return }
// Returns the type of the elements of N slice(s). If the type is different, // another slice or undefined, returns an error. func sliceElementType(slices ...[]interface{}) (reflect.Type, error) { var prevType reflect.Type for _, s := range slices { // Go through elements of all given slices and make sure they are all the same type. for _, v := range s { currentType := reflect.TypeOf(v) if prevType == nil { prevType = currentType // We don't support lists of lists yet. if prevType.Kind() == reflect.Slice { return nil, errNoListOfLists } } else { if prevType != currentType { return nil, fmt.Errorf("list element types are not identical: %v", fmt.Sprint(slices)) } prevType = currentType } } } if prevType == nil { return nil, fmt.Errorf("no elements in any of the given slices") } return prevType, nil }
func (m MySQLDialect) ToSqlType(val reflect.Type, maxsize int, isAutoIncr bool) string { switch val.Kind() { case reflect.Int, reflect.Int16, reflect.Int32: return "int" case reflect.Int64: return "bigint" case reflect.Float64, reflect.Float32: return "double" case reflect.Slice: if val.Elem().Kind() == reflect.Uint8 { return "mediumblob" } } switch val.Name() { case "NullableInt64": return "bigint" case "NullableFloat64": return "double" case "NullableBool": return "tinyint" case "NullableBytes": return "mediumblob" } if maxsize < 1 { maxsize = 255 } return fmt.Sprintf("varchar(%d)", maxsize) }
func (d SqliteDialect) ToSqlType(val reflect.Type, maxsize int, isAutoIncr bool) string { switch val.Kind() { case reflect.Ptr: return d.ToSqlType(val.Elem(), maxsize, isAutoIncr) case reflect.Bool: return "integer" case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: return "integer" case reflect.Float64, reflect.Float32: return "real" case reflect.Slice: if val.Elem().Kind() == reflect.Uint8 { return "blob" } } switch val.Name() { case "NullInt64": return "integer" case "NullFloat64": return "real" case "NullBool": return "integer" case "Time": return "datetime" } if maxsize < 1 { maxsize = 255 } return fmt.Sprintf("varchar(%d)", maxsize) }
// reflectTypeToJSONType returns a string that represents the JSON type // associated with the provided Go type. func reflectTypeToJSONType(xT descLookupFunc, rt reflect.Type) string { kind := rt.Kind() if isNumeric(kind) { return xT("json-type-numeric") } switch kind { case reflect.String: return xT("json-type-string") case reflect.Bool: return xT("json-type-bool") case reflect.Array, reflect.Slice: return xT("json-type-array") + reflectTypeToJSONType(xT, rt.Elem()) case reflect.Struct: return xT("json-type-object") case reflect.Map: return xT("json-type-object") } return xT("json-type-value") }
func MakeTypeInfo(rt reflect.Type) *TypeInfo { info := &TypeInfo{Type: rt} // If struct, register field name options if rt.Kind() == reflect.Struct { numFields := rt.NumField() structFields := []StructFieldInfo{} for i := 0; i < numFields; i++ { field := rt.Field(i) if field.PkgPath != "" { continue } skip, opts := getOptionsFromField(field) if skip { continue } structFields = append(structFields, StructFieldInfo{ Index: i, Type: field.Type, Options: opts, }) } info.Fields = structFields } return info }
func baseType(t reflect.Type, expected reflect.Kind) (reflect.Type, error) { t = reflectx.Deref(t) if t.Kind() != expected { return nil, fmt.Errorf("expected %s but got %s", expected, t.Kind()) } return t, nil }
// reflectWithProperType does the opposite thing with setWithProperType. func reflectWithProperType(t reflect.Type, key *Key, field reflect.Value, delim string) error { switch t.Kind() { case reflect.String: key.SetValue(field.String()) case reflect.Bool, reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Float64, reflectTime: key.SetValue(fmt.Sprint(field)) case reflect.Slice: vals := field.Slice(0, field.Len()) if field.Len() == 0 { return nil } var buf bytes.Buffer isTime := fmt.Sprint(field.Type()) == "[]time.Time" for i := 0; i < field.Len(); i++ { if isTime { buf.WriteString(vals.Index(i).Interface().(time.Time).Format(time.RFC3339)) } else { buf.WriteString(fmt.Sprint(vals.Index(i))) } buf.WriteString(delim) } key.SetValue(buf.String()[:buf.Len()-1]) default: return fmt.Errorf("unsupported type '%s'", t) } return nil }