Beispiel #1
1
func labelType(t reflect.Type) bool {
	switch t.Kind() {
	case reflect.Interface, reflect.Struct:
		return true
	}
	return false
}
Beispiel #2
1
// 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
	}
}
Beispiel #3
1
// 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
}
Beispiel #6
0
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)
}
Beispiel #7
0
// 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
}
Beispiel #8
0
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())
	}
}
Beispiel #10
0
// 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())
}
Beispiel #11
0
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
}
Beispiel #12
0
// 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}
}
Beispiel #13
0
// 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
}
Beispiel #14
0
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())
}
Beispiel #15
0
// 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
}
Beispiel #16
0
// 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
}
Beispiel #17
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)
	}
}
Beispiel #18
0
// 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
}
Beispiel #19
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})
}
Beispiel #20
0
// 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
}
Beispiel #22
0
// 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())
	}
}
Beispiel #23
0
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

}
Beispiel #24
0
// 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
}
Beispiel #25
0
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)
}
Beispiel #26
0
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)
}
Beispiel #27
0
// 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")
}
Beispiel #28
0
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
}
Beispiel #29
0
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
}
Beispiel #30
0
// 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
}