示例#1
0
文件: clone.go 项目: knz/cockroach
func typeIsOrContainsVerbotenImpl(t reflect.Type, verboten reflect.Kind) bool {
	switch t.Kind() {
	case verboten:
		return true

	case reflect.Map:
		if typeIsOrContainsVerbotenLocked(t.Key(), verboten) || typeIsOrContainsVerbotenLocked(t.Elem(), verboten) {
			return true
		}

	case reflect.Array, reflect.Ptr, reflect.Slice:
		if typeIsOrContainsVerbotenLocked(t.Elem(), verboten) {
			return true
		}

	case reflect.Struct:
		for i := 0; i < t.NumField(); i++ {
			if typeIsOrContainsVerbotenLocked(t.Field(i).Type, verboten) {
				return true
			}
		}

	case reflect.Chan, reflect.Func, reflect.Interface:
		// Not strictly correct, but cloning these kinds is not allowed.
		return true

	}

	return false
}
示例#2
0
// verifyHandler ensures that the given t is a function with the following signature:
// func(json.Context, *ArgType)(*ResType, error)
func verifyHandler(t reflect.Type) error {
	if t.NumIn() != 2 || t.NumOut() != 2 {
		return fmt.Errorf("handler should be of format func(json.Context, *ArgType) (*ResType, error)")
	}

	isStructPtr := func(t reflect.Type) bool {
		return t.Kind() == reflect.Ptr && t.Elem().Kind() == reflect.Struct
	}
	isMap := func(t reflect.Type) bool {
		return t.Kind() == reflect.Map && t.Key().Kind() == reflect.String
	}
	validateArgRes := func(t reflect.Type, name string) error {
		if !isStructPtr(t) && !isMap(t) {
			return fmt.Errorf("%v should be a pointer to a struct, or a map[string]interface{}", name)
		}
		return nil
	}

	if t.In(0) != typeOfContext {
		return fmt.Errorf("arg0 should be of type json.Context")
	}
	if err := validateArgRes(t.In(1), "second argument"); err != nil {
		return err
	}
	if err := validateArgRes(t.Out(0), "first return value"); err != nil {
		return err
	}
	if !t.Out(1).AssignableTo(typeOfError) {
		return fmt.Errorf("second return value should be an error")
	}

	return nil
}
示例#3
0
func getOrCreateSchema(definitions Definitions, t reflect.Type) *Schema {
	var result Schema
	if t.Kind() == reflect.Ptr {
		t = t.Elem()
	}

	if t.Kind() == reflect.Map {
		if t.Key().Kind() != reflect.String {
			panic("swagger supports only maps with string keys")
		}
		result.Type = "object"
		result.AdditionalProperties = getOrCreateSchema(definitions, t.Elem())
		return &result
	}

	if t.Kind() == reflect.Interface {
		result.Type = "object"
		return &result
	}

	result.Type = typeName(t)
	if result.Type == "object" {
		name := t.String()
		if _, ok := definitions[name]; ok {
			result = Schema{Ref: "#/definitions/" + name}
			return &result
		}
		definitions[name] = result

		if t.NumField() > 0 {
			result.Properties = Properties{}
		}
		for i := 0; i < t.NumField(); i++ {
			field := t.Field(i)
			if field.PkgPath != "" {
				continue
			}
			name := field.Tag.Get("json")
			if name == "" {
				name = field.Tag.Get("key")
				if name == "" {
					name = field.Name
				}
			}
			if field.Type.Kind() != reflect.Ptr {
				result.Required = append(result.Required, name)
			}
			fieldSchema := getOrCreateSchema(definitions, field.Type)
			fieldSchema.Description = field.Tag.Get("description")
			result.Properties[name] = fieldSchema
		}
		definitions[name] = result
		result = Schema{Ref: "#/definitions/" + name}
	} else if result.Type == "array" {
		itemsSchema := getOrCreateSchema(definitions, t.Elem())
		result.Items = &Items{*itemsSchema}
	}

	return &result
}
示例#4
0
文件: luar.go 项目: stevedonovan/luar
func copyTableToMap(L *lua.State, t reflect.Type, idx int, visited map[uintptr]interface{}) interface{} {
	if t == nil {
		t = tmap
	}
	te, tk := t.Elem(), t.Key()
	m := reflect.MakeMap(t)

	// See copyTableToSlice.
	ptr := L.ToPointer(idx)
	if !luaIsEmpty(L, idx) {
		visited[ptr] = m.Interface()
	}

	L.PushNil()
	if idx < 0 {
		idx--
	}
	for L.Next(idx) != 0 {
		// key at -2, value at -1
		key := reflect.ValueOf(luaToGo(L, tk, -2, visited))
		val := reflect.ValueOf(luaToGo(L, te, -1, visited))
		if val.Interface() == nullv.Interface() {
			val = reflect.Zero(te)
		}
		m.SetMapIndex(key, val)
		L.Pop(1)
	}
	return m.Interface()
}
示例#5
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())
	}
}
示例#6
0
func (g *conversionGenerator) typeName(inType reflect.Type) string {
	switch inType.Kind() {
	case reflect.Map:
		return fmt.Sprintf("map[%s]%s", g.typeName(inType.Key()), g.typeName(inType.Elem()))
	case reflect.Slice:
		return fmt.Sprintf("[]%s", g.typeName(inType.Elem()))
	case reflect.Ptr:
		return fmt.Sprintf("*%s", g.typeName(inType.Elem()))
	default:
		typeWithPkg := fmt.Sprintf("%s", inType)
		slices := strings.Split(typeWithPkg, ".")
		if len(slices) == 1 {
			// Default package.
			return slices[0]
		}
		if len(slices) == 2 {
			pkg := slices[0]
			if val, found := g.pkgOverwrites[pkg]; found {
				pkg = val
			}
			if pkg != "" {
				pkg = pkg + "."
			}
			return pkg + slices[1]
		}
		panic("Incorrect type name: " + typeWithPkg)
	}
}
示例#7
0
文件: encode.go 项目: hgGeorg/mongo
func newMapEncoder(t reflect.Type) encoderFunc {
	if t.Key().Kind() != reflect.String && !t.Key().Implements(textMarshalerType) {
		return unsupportedTypeEncoder
	}
	me := &mapEncoder{typeEncoder(t.Elem())}
	return me.encode
}
示例#8
0
func evalCompositeLitMap(ctx *Ctx, t reflect.Type, lit *CompositeLit, env *Env) (reflect.Value, error) {

	m := reflect.MakeMap(t)

	kT := knownType{t.Key()}
	vT := knownType{t.Elem()}
	for _, elt := range lit.Elts {
		kv := elt.(*KeyValueExpr)
		k, err := evalTypedExpr(ctx, kv.Key.(Expr), kT, env)
		if err != nil {
			return reflect.Value{}, err
		}
		if kT[0].Kind() == reflect.Interface {
			dynamicT := k[0].Elem().Type()
			if !isStaticTypeComparable(dynamicT) {
				return reflect.Value{}, PanicUnhashableType{dynamicT}
			}
		}
		v, err := evalTypedExpr(ctx, kv.Value.(Expr), vT, env)
		if err != nil {
			return reflect.Value{}, err
		}
		m.SetMapIndex(k[0], v[0])
	}
	return m, nil
}
func (g *conversionGenerator) typeName(inType reflect.Type) string {
	switch inType.Kind() {
	case reflect.Slice:
		return fmt.Sprintf("[]%s", g.typeName(inType.Elem()))
	case reflect.Ptr:
		return fmt.Sprintf("*%s", g.typeName(inType.Elem()))
	case reflect.Map:
		if len(inType.Name()) == 0 {
			return fmt.Sprintf("map[%s]%s", g.typeName(inType.Key()), g.typeName(inType.Elem()))
		}
		fallthrough
	default:
		pkg, name := inType.PkgPath(), inType.Name()
		if len(name) == 0 && inType.Kind() == reflect.Struct {
			return "struct{}"
		}
		if len(pkg) == 0 {
			// Default package.
			return name
		}
		if val, found := g.pkgOverwrites[pkg]; found {
			pkg = val
		}
		if len(pkg) == 0 {
			return name
		}
		short := g.addImportByPath(pkg)
		if len(short) > 0 {
			return fmt.Sprintf("%s.%s", short, name)
		}
		return name
	}
}
示例#10
0
文件: encode.go 项目: spxtr/contrib
// mapEncodeScratch returns a new reflect.Value matching the map's value type,
// and a structPointer suitable for passing to an encoder or sizer.
func mapEncodeScratch(mapType reflect.Type) (keycopy, valcopy reflect.Value, keybase, valbase structPointer) {
	// Prepare addressable doubly-indirect placeholders for the key and value types.
	// This is needed because the element-type encoders expect **T, but the map iteration produces T.

	keycopy = reflect.New(mapType.Key()).Elem()                 // addressable K
	keyptr := reflect.New(reflect.PtrTo(keycopy.Type())).Elem() // addressable *K
	keyptr.Set(keycopy.Addr())                                  //
	keybase = toStructPointer(keyptr.Addr())                    // **K

	// Value types are more varied and require special handling.
	switch mapType.Elem().Kind() {
	case reflect.Slice:
		// []byte
		var dummy []byte
		valcopy = reflect.ValueOf(&dummy).Elem() // addressable []byte
		valbase = toStructPointer(valcopy.Addr())
	case reflect.Ptr:
		// message; the generated field type is map[K]*Msg (so V is *Msg),
		// so we only need one level of indirection.
		valcopy = reflect.New(mapType.Elem()).Elem() // addressable V
		valbase = toStructPointer(valcopy.Addr())
	default:
		// everything else
		valcopy = reflect.New(mapType.Elem()).Elem()                // addressable V
		valptr := reflect.New(reflect.PtrTo(valcopy.Type())).Elem() // addressable *V
		valptr.Set(valcopy.Addr())                                  //
		valbase = toStructPointer(valptr.Addr())                    // **V
	}
	return
}
示例#11
0
func newMapEncoder(t reflect.Type, vx reflect.Value) encoderFunc {
	if t.Key().Kind() != reflect.String {
		return unsupportedTypeEncoder
	}
	me := &mapEncoder{typeEncoder(vx.Type().Elem(), reflect.Value{})}
	return me.encode
}
示例#12
0
// unify attempts to satisfy a pair of types, where the `param` type is the
// expected type of a function argument and the `input` type is the known
// type of a function argument. The `param` type may be parametric (that is,
// it may contain a type that is convertible to TypeVariable) but the
// `input` type may *not* be parametric.
//
// Any failure to unify the two types results in a panic.
//
// The end result of unification is a type environment: a set of substitutions
// from type variable to a Go type.
func (tp typePair) unify(param, input reflect.Type) error {
	if tyname := tyvarName(input); len(tyname) > 0 {
		return tp.error("Type variables are not allowed in the types of " +
			"arguments.")
	}
	if tyname := tyvarName(param); len(tyname) > 0 {
		if cur, ok := tp.tyenv[tyname]; ok && cur != input {
			return tp.error("Type variable %s expected type '%s' but got '%s'.",
				tyname, cur, input)
		} else if !ok {
			tp.tyenv[tyname] = input
		}
		return nil
	}
	if param.Kind() != input.Kind() {
		return tp.error("Cannot unify different kinds of types '%s' and '%s'.",
			param, input)
	}

	switch param.Kind() {
	case reflect.Array:
		return tp.unify(param.Elem(), input.Elem())
	case reflect.Chan:
		if param.ChanDir() != input.ChanDir() {
			return tp.error("Cannot unify '%s' with '%s' "+
				"(channel directions are different: '%s' != '%s').",
				param, input, param.ChanDir(), input.ChanDir())
		}
		return tp.unify(param.Elem(), input.Elem())
	case reflect.Func:
		if param.NumIn() != input.NumIn() || param.NumOut() != input.NumOut() {
			return tp.error("Cannot unify '%s' with '%s'.", param, input)
		}
		for i := 0; i < param.NumIn(); i++ {
			if err := tp.unify(param.In(i), input.In(i)); err != nil {
				return err
			}
		}
		for i := 0; i < param.NumOut(); i++ {
			if err := tp.unify(param.Out(i), input.Out(i)); err != nil {
				return err
			}
		}
	case reflect.Map:
		if err := tp.unify(param.Key(), input.Key()); err != nil {
			return err
		}
		return tp.unify(param.Elem(), input.Elem())
	case reflect.Ptr:
		return tp.unify(param.Elem(), input.Elem())
	case reflect.Slice:
		return tp.unify(param.Elem(), input.Elem())
	}

	// The only other container types are Interface and Struct.
	// I am unsure about what to do with interfaces. Mind is fuzzy.
	// Structs? I don't think it really makes much sense to use type
	// variables inside of them.
	return nil
}
示例#13
0
// tysubst attempts to substitute all type variables within a single return
// type with their corresponding Go type from the type environment.
//
// tysubst will panic if a type variable is unbound, or if it encounters a
// type that cannot be dynamically created. Such types include arrays,
// functions and structs. (A limitation of the `reflect` package.)
func (rt returnType) tysubst(typ reflect.Type) reflect.Type {
	if tyname := tyvarName(typ); len(tyname) > 0 {
		if thetype, ok := rt.tyenv[tyname]; !ok {
			rt.panic("Unbound type variable %s.", tyname)
		} else {
			return thetype
		}
	}

	switch typ.Kind() {
	case reflect.Array:
		rt.panic("Cannot dynamically create Array types.")
	case reflect.Chan:
		return reflect.ChanOf(typ.ChanDir(), rt.tysubst(typ.Elem()))
	case reflect.Func:
		rt.panic("Cannot dynamically create Function types.")
	case reflect.Interface:
		rt.panic("TODO")
	case reflect.Map:
		return reflect.MapOf(rt.tysubst(typ.Key()), rt.tysubst(typ.Elem()))
	case reflect.Ptr:
		return reflect.PtrTo(rt.tysubst(typ.Elem()))
	case reflect.Slice:
		return reflect.SliceOf(rt.tysubst(typ.Elem()))
	case reflect.Struct:
		rt.panic("Cannot dynamically create Struct types.")
	case reflect.UnsafePointer:
		rt.panic("Cannot dynamically create unsafe.Pointer types.")
	}

	// We've covered all the composite types, so we're only left with
	// base types.
	return typ
}
示例#14
0
func compileField(typ reflect.Type, name string, args []parse.Node, final reflect.Type) (fn lookupFn, elem reflect.Type) {
	if isNilType(typ) {
		fn = compileFieldDynamic(name, args)
		return
	}

	if m, exist := typ.MethodByName(name); exist {
		fn = compileMethodCall(typ, m.Func, args, final)
		elem = m.Type.Out(0)
		return
	}

	switch typ.Kind() {
	case reflect.Struct:
		structField, found := typ.FieldByName(name)
		if !found {
			panic(fmt.Errorf("%s has no field %s", typ, name))
		}
		fn = func(s state, v reflect.Value, final interface{}) reflect.Value {
			return v.FieldByIndex(structField.Index)
		}
		elem = structField.Type
		return
	case reflect.Map:
		k := reflect.ValueOf(name)
		fn = func(s state, v reflect.Value, final interface{}) reflect.Value {
			return v.MapIndex(k)
		}
		elem = typ.Key()
		return
	}
	panic(fmt.Errorf("struct or map expected, but got %s", typ))
}
示例#15
0
func newMapEncoder(t reflect.Type) encoderFunc {
	if t.Key().Kind() != reflect.String {
		return unsupportedTypeEncoder
	}
	me := &mapEncoder{typeEncoder(t.Elem())}
	return me.encode
}
示例#16
0
文件: sig.go 项目: jonboulle/fleet
// getSignature returns the signature of the given type and panics on unknown types.
func getSignature(t reflect.Type) string {
	// handle simple types first
	switch t.Kind() {
	case reflect.Uint8:
		return "y"
	case reflect.Bool:
		return "b"
	case reflect.Int16:
		return "n"
	case reflect.Uint16:
		return "q"
	case reflect.Int32:
		if t == unixFDType {
			return "h"
		}
		return "i"
	case reflect.Uint32:
		if t == unixFDIndexType {
			return "h"
		}
		return "u"
	case reflect.Int64:
		return "x"
	case reflect.Uint64:
		return "t"
	case reflect.Float64:
		return "d"
	case reflect.Ptr:
		return getSignature(t.Elem())
	case reflect.String:
		if t == objectPathType {
			return "o"
		}
		return "s"
	case reflect.Struct:
		if t == variantType {
			return "v"
		} else if t == signatureType {
			return "g"
		}
		var s string
		for i := 0; i < t.NumField(); i++ {
			field := t.Field(i)
			if field.PkgPath == "" && field.Tag.Get("dbus") != "-" {
				s += getSignature(t.Field(i).Type)
			}
		}
		return "(" + s + ")"
	case reflect.Array, reflect.Slice:
		return "a" + getSignature(t.Elem())
	case reflect.Map:
		if !isKeyType(t.Key()) {
			panic(InvalidTypeError{t})
		}
		return "a{" + getSignature(t.Key()) + getSignature(t.Elem()) + "}"
	case reflect.Interface:
		return "v"
	}
	panic(InvalidTypeError{t})
}
示例#17
0
func checkCompositeLitMap(ctx *Ctx, lit *CompositeLit, t reflect.Type, env *Env) (*CompositeLit, []error) {
	var errs, moreErrs []error

	kT := t.Key()

	// Don't check for duplicate interface{} keys. This is a gc bug
	// http://code.google.com/p/go/issues/detail?id=7214
	var seen map[interface{}]bool
	if kT.Kind() != reflect.Interface {
		seen = make(map[interface{}]bool, len(lit.Elts))
	}
	eltT := t.Elem()

	for i := range lit.Elts {
		if kv, ok := lit.Elts[i].(*ast.KeyValueExpr); !ok {
			lit.Elts[i], moreErrs = CheckExpr(ctx, lit.Elts[i], env)
			if moreErrs != nil {
				errs = append(errs, moreErrs...)
			}
			errs = append(errs, ErrMissingMapKey{at(ctx, lit.Elts[i])})
		} else {
			lit.Elts[i] = &KeyValueExpr{KeyValueExpr: kv}
			k, ok, moreErrs := checkExprAssignableTo(ctx, kv.Key, kT, env)
			if !ok {
				if len(k.KnownType()) != 0 {
					kF := fakeCheckExpr(kv.Key, env)
					kF.setKnownType(knownType(k.KnownType()))
					errs = append(errs, ErrBadMapKey{at(ctx, kF), kT})
				}
			} else {
				errs = append(errs, moreErrs...)
			}
			kv.Key = k

			if seen != nil && k.IsConst() {
				var constKey interface{}
				if k.KnownType()[0] == ConstNil {
					constKey = nil
				} else if cT, ok := k.KnownType()[0].(ConstType); ok {
					c, _ := promoteConstToTyped(ctx, cT, constValue(k.Const()),
						cT.DefaultPromotion(), k)
					constKey = reflect.Value(c).Interface()
				} else {
					constKey = k.Const().Interface()
				}
				if seen[constKey] {
					errs = append(errs, ErrDuplicateMapKey{at(ctx, kv.Key)})
				}
				seen[constKey] = true
			}
			v, moreErrs := checkMapValue(ctx, kv.Value, eltT, env)
			if moreErrs != nil {
				errs = append(errs, moreErrs...)
			}
			kv.Value = v
		}
	}
	return lit, errs
}
示例#18
0
// Return the string that should be used to refer to the supplied type within
// the given package. The output is not guaranteed to be pretty, and should be
// run through a tool like gofmt afterward.
//
// For example, a pointer to an io.Reader may be rendered as "*Reader" or
// "*io.Reader" depending on whether the package path is "io" or not.
func typeString(
	t reflect.Type,
	pkgPath string) (s string) {
	// Is this type named? If so we use its name, possibly with a package prefix.
	//
	// Examples:
	//
	//     int
	//     string
	//     error
	//     gcs.Bucket
	//
	if t.Name() != "" {
		if t.PkgPath() == pkgPath {
			s = t.Name()
		} else {
			s = t.String()
		}

		return
	}

	// This type is unnamed. Recurse.
	switch t.Kind() {
	case reflect.Array:
		s = fmt.Sprintf("[%d]%s", t.Len(), typeString(t.Elem(), pkgPath))

	case reflect.Chan:
		s = fmt.Sprintf("%s %s", t.ChanDir(), typeString(t.Elem(), pkgPath))

	case reflect.Func:
		s = typeString_Func(t, pkgPath)

	case reflect.Interface:
		s = typeString_Interface(t, pkgPath)

	case reflect.Map:
		s = fmt.Sprintf(
			"map[%s]%s",
			typeString(t.Key(), pkgPath),
			typeString(t.Elem(), pkgPath))

	case reflect.Ptr:
		s = fmt.Sprintf("*%s", typeString(t.Elem(), pkgPath))

	case reflect.Slice:
		s = fmt.Sprintf("[]%s", typeString(t.Elem(), pkgPath))

	case reflect.Struct:
		s = typeString_Struct(t, pkgPath)

	default:
		log.Panicf("Unhandled kind %v for type: %v", t.Kind(), t)
	}

	return
}
示例#19
0
func validateType(t reflect.Type) (err error) {
	t = removePtr(t)
	for _, vd := range validatedTypes {
		if vd.t == t {
			return *vd.err
		}
	}
	validatedTypes = append(validatedTypes, &validatedType{
		t:   t,
		err: &err,
	})

	switch t.Kind() {
	case reflect.Chan, reflect.Func, reflect.Interface, reflect.UnsafePointer:
		err = fmt.Errorf("%s. Found [%s]", t.Kind(), t)
		return err
	case reflect.Array, reflect.Slice:
		if err = validateType(t.Elem()); err != nil {
			err = fmt.Errorf("%s in the %s [%s]", err, t.Kind(), t)
			return err
		}
	case reflect.Map:
		if err = validateType(t.Elem()); err != nil {
			err = fmt.Errorf("%s in the value of map [%s]", err, t)
			return err
		}
		if err = validateType(t.Key()); err != nil {
			err = fmt.Errorf("%s in the key of map [%s]", err, t)
			return err
		}
	case reflect.Struct:
		if supportsGob(t) {
			return nil
		}
		// Special case for struct{}
		if t.NumField() == 0 {
			return nil
		}
		n := 0
		for i := 0; i < t.NumField(); i++ {
			f := t.Field(i)
			if f.PkgPath == "" {
				if err = validateType(f.Type); err != nil {
					err = fmt.Errorf("%s in the field [%s] of struct [%s]", err, f.Name, t)
					return err
				}
				n++
			}
		}
		if n == 0 {
			err = fmt.Errorf("struct without exported fields [%s]", t)
			return err
		}
	}

	return err
}
示例#20
0
// baseMapKind returns the the Kind of the key and value types of a map.  If
// the map consists of other maps, the Kind of the key of the lowest level map
// will be returned; e.g. reflect.String and reflect.Int will be returned for
// map[string]map[int]string.
func baseMapKind(typ reflect.Type) (k, v reflect.Kind) {
	if typ.Kind() == reflect.Ptr {
		return baseMapKind(typ.Elem())
	}
	k = typ.Key().Kind()
	if k == reflect.Ptr {
		k, _ = baseKind(typ.Key())
	}
	v, _ = baseKind(typ.Elem())
	return k, v
}
示例#21
0
文件: render.go 项目: hgGeorg/mongo
func tryAndSortMapKeys(mt reflect.Type, k []reflect.Value) {
	// Try our stock sortable values.
	switch mt.Key().Kind() {
	case reflect.String, reflect.Int:
		vs := &sortableValueSlice{
			kind:     mt.Key().Kind(),
			elements: k,
		}
		sort.Sort(vs)
	}
}
示例#22
0
func getMapValue(ic *Inception, name string, typ reflect.Type, ptr bool, forceString bool) string {
	var out = ""

	if typ.Key().Kind() != reflect.String {
		out += fmt.Sprintf("/* Falling back. type=%v kind=%v */\n", typ, typ.Kind())
		out += ic.q.Flush()
		out += "err = buf.Encode(" + name + ")" + "\n"
		out += "if err != nil {" + "\n"
		out += "  return err" + "\n"
		out += "}" + "\n"
		return out
	}

	var elemKind reflect.Kind
	elemKind = typ.Elem().Kind()

	switch elemKind {
	case reflect.String,
		reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
		reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr,
		reflect.Float32,
		reflect.Float64,
		reflect.Bool:

		ic.OutputImports[`fflib "github.com/pquerna/ffjson/fflib/v1"`] = true

		out += "if " + name + " == nil  {" + "\n"
		ic.q.Write("null")
		out += ic.q.GetQueued()
		ic.q.DeleteLast()
		out += "} else {" + "\n"
		out += ic.q.WriteFlush("{ ")
		out += "  for key, value := range " + name + " {" + "\n"
		out += "    fflib.WriteJsonString(buf, key)" + "\n"
		out += "    buf.WriteString(`:`)" + "\n"
		out += getGetInnerValue(ic, "value", typ.Elem(), false, forceString)
		out += "    buf.WriteByte(',')" + "\n"
		out += "  }" + "\n"
		out += "buf.Rewind(1)" + "\n"
		out += ic.q.WriteFlush("}")
		out += "}" + "\n"

	default:
		out += ic.q.Flush()
		out += fmt.Sprintf("/* Falling back. type=%v kind=%v */\n", typ, typ.Kind())
		out += "err = buf.Encode(" + name + ")" + "\n"
		out += "if err != nil {" + "\n"
		out += "  return err" + "\n"
		out += "}" + "\n"
	}
	return out
}
示例#23
0
文件: encode.go 项目: 2thetop/go
func newMapEncoder(t reflect.Type) encoderFunc {
	switch t.Key().Kind() {
	case reflect.String,
		reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
		reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
	default:
		if !t.Key().Implements(textMarshalerType) {
			return unsupportedTypeEncoder
		}
	}
	me := &mapEncoder{typeEncoder(t.Elem())}
	return me.encode
}
示例#24
0
func (g *conversionGenerator) generateConversionsForMap(inType, outType reflect.Type) error {
	inKey := inType.Key()
	outKey := outType.Key()
	if err := g.generateConversionsBetween(inKey, outKey); err != nil {
		return err
	}
	inValue := inType.Elem()
	outValue := outType.Elem()
	if err := g.generateConversionsBetween(inValue, outValue); err != nil {
		return err
	}
	return nil
}
示例#25
0
func ValType(t reflect.Type) (decl string) {
	switch k := t.Kind(); k {
	case reflect.Struct:
		decl = "struct {\n"
		for i, ed := 0, t.NumField(); i < ed; i++ {
			ft := t.Field(i)
			if ft.Tag != "-" || ft.Tag.Get("goval") == "-" {
				s := ft.Name + " " + ValType(ft.Type)
				if ft.Tag != "" {
					s += " `" + strings.Replace("`", "\\`", string(ft.Tag), -1) + "`"
				}
				decl += indent(s) + "\n"
			}
		}
		decl += "}"
	case reflect.Array:
		decl = "[" + strconv.Itoa(t.Len()) + "]" + Val(t.Elem())
	case reflect.Slice:
		decl = "[]" + Val(t.Elem())
	case reflect.Chan:
		switch t.ChanDir() {
		case reflect.RecvDir:
			decl = "<-chan "
		case reflect.SendDir:
			decl = "chan<- "
		case reflect.BothDir:
			decl = "chan "
		default:
			panic("Didn't expect a dir other than send, recieve or both.")
		}
		decl += Val(t.Elem())
	case reflect.Map:
		decl = "map[" + ValType(t.Key()) + "]" + ValType(t.Elem())
	case reflect.Ptr:
		decl = "*" + ValType(t.Elem())
	case reflect.Interface:
		decl = "interface {\n"
		for i, ed := 0, t.NumMethod(); i < ed; i++ {
			ft := t.Method(i)
			s := ft.Name + FormatFuncArguments(ft.Type)
			decl += indent(s) + "\n"
		}
		decl += "}"
	case reflect.Func:
		decl = "func" + FormatFuncArguments(t)
	default:
		return k.String()
	}

	return
}
示例#26
0
func typeSchema(title string, t reflect.Type, tag reflect.StructTag) *Value {
	fieldType := fieldType(t, tag)

	isReadOnly := tag.Get("readOnly") != ""

	value := &Value{
		Title:       title,
		Type:        fieldType,
		Required:    isRequired(tag),
		Enum:        enum(tag),
		Description: tag.Get("description"),
		Format:      Format(tag.Get("format")),
		ReadOnly:    isReadOnly,
	}

	switch fieldType {
	case Map:
		value.Title = t.Name()
		value.Format = "tabs"

		// map items
		value.Items = &Value{
			Type:           Object,
			HeaderTemplate: "{{self.key}}",
			Properties: map[string]*Value{
				"key":   typeSchema("key", t.Key(), reflect.StructTag("")),
				"value": typeSchema("value", t.Elem(), reflect.StructTag("")),
			},
		}

		// the enum annotation for maps is for the key not for the map itself
		value.Items.Properties["key"].Enum = enum(tag)
		value.Enum = make([]string, 0)

		// if there is valueEnum then the value is considered enum
		if tag.Get("valueEnum") != "" {
			value.Items.Properties["value"].Enum = strings.Split(tag.Get("valueEnum"), ",")
		} else {
			value.Items.Properties["value"].Enum = make([]string, 0)
		}
	case Array:
		value.Items = typeSchema(t.Name(), t.Elem(), tag)
		value.Items.HeaderTemplate = tag.Get("headerTemplate")
	case ProtoEnum:
		value.Enum = getProtoEnumValues(t)
	case Object:
		value = structSchema(title, t, tag)
	}

	return value
}
示例#27
0
文件: type.go 项目: shutej/go2flow
func getTypes(t reflect.Type, s supportingTypes, c *int) *Type {
	n, p := t.String(), t.PkgPath()

	if _, ok := t.MethodByName("MarshalJSON"); ok {
		return custom(n, p)
	}

	switch t.Kind() {
	case reflect.String:
		return simple(String)
	case reflect.Int, reflect.Int8, reflect.Int16,
		reflect.Int32, reflect.Int64,
		reflect.Uint, reflect.Uint8, reflect.Uint16,
		reflect.Uint32, reflect.Uint64, reflect.Uintptr:
		return simple(Int)
	case reflect.Float32, reflect.Float64:
		return simple(Float)
	case reflect.Bool:
		return simple(Bool)
	case reflect.Ptr:
		return s.set(n, p, func() *Type {
			return ptrOf(getTypes(t.Elem(), s, c))
		})
	case reflect.Array, reflect.Slice:
		if t.Elem().Kind() == reflect.Uint8 {
			return simple(Bytes)
		}
		return s.set(n, p, func() *Type {
			return arrayOf(getTypes(t.Elem(), s, c))
		})
	case reflect.Struct:
		if p == "" {
			// gets an anonymous type name and fake the package
			n = anonTypeName(c)
			p = "github.com/shutej/go2flow/anonymous"
		}
		return s.set(n, p, func() *Type {
			return structOf(getFields(t, s, c))
		})
	case reflect.Map:
		if t.Key().Kind() != reflect.String {
			log.Fatalf("unexpected map key type: %v", t.Key())
		}
		return s.set(n, p, func() *Type {
			return mapOf(getTypes(t.Elem(), s, c))
		})
	}
	log.Fatalf("unknown kind for type: %v", t)
	return nil
}
示例#28
0
文件: encoder.go 项目: catgatp/gol
func (t *TGen) genMap(name string, val reflect.Type) {
	t.src += "// map encode\n"
	t.genNilBegin(name)
	t.genUint32("uint32(len(" + name + "))")
	tmpKey := t.tmpNameGen.Get() // get tmp var name
	tmpVal := t.tmpNameGen.Get() // get tmp var name
	t.src += "for " + tmpKey + ", " + tmpVal + " := range " + name + " {\n"
	t.stackName.Push(tmpKey)
	t.encode(val.Key())
	t.stackName.Push(tmpVal)
	t.encode(val.Elem())
	t.src += "}\n"
	t.genNilEnd()
}
示例#29
0
func getDecoder(typ reflect.Type) decoderFunc {
	kind := typ.Kind()

	// Addressable struct field value.
	if kind != reflect.Ptr && reflect.PtrTo(typ).Implements(decoderType) {
		return decodeCustomValuePtr
	}

	if typ.Implements(decoderType) {
		return decodeCustomValue
	}

	if typ.Implements(unmarshalerType) {
		return unmarshalValue
	}

	if decoder, ok := typDecMap[typ]; ok {
		return decoder
	}

	switch kind {
	case reflect.Ptr:
		return ptrDecoderFunc(typ)
	case reflect.Slice:
		elem := typ.Elem()
		switch elem.Kind() {
		case reflect.Uint8:
			return decodeBytesValue
		}
		switch elem {
		case stringType:
			return decodeStringSliceValue
		}
	case reflect.Array:
		if typ.Elem().Kind() == reflect.Uint8 {
			return decodeByteArrayValue
		}
	case reflect.Map:
		if typ.Key() == stringType {
			switch typ.Elem() {
			case stringType:
				return decodeMapStringStringValue
			case interfaceType:
				return decodeMapStringInterfaceValue

			}
		}
	}
	return valueDecoders[kind]
}
示例#30
0
// decodeMap decodes a map and stores it in value.
// Maps are encoded as a length followed by key:value pairs.
// Because the internals of maps are not visible to us, we must
// use reflection rather than pointer magic.
func (dec *Decoder) decodeMap(mtyp reflect.Type, state *decoderState, value reflect.Value, keyOp, elemOp decOp, ovfl error) {
	if value.IsNil() {
		// Allocate map.
		value.Set(reflect.MakeMap(mtyp))
	}
	n := int(state.decodeUint())
	keyIsPtr := mtyp.Key().Kind() == reflect.Ptr
	elemIsPtr := mtyp.Elem().Kind() == reflect.Ptr
	for i := 0; i < n; i++ {
		key := decodeIntoValue(state, keyOp, keyIsPtr, allocValue(mtyp.Key()), ovfl)
		elem := decodeIntoValue(state, elemOp, elemIsPtr, allocValue(mtyp.Elem()), ovfl)
		value.SetMapIndex(key, elem)
	}
}