Пример #1
0
func typeMarshaler(t reflect.Type) marshalFunc {
	if t.Implements(textMarshalerType) {
		return textMarshaler
	}
	switch t.Kind() {
	case reflect.Bool:
		return boolMarshaler
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		return intMarshaler
	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
		return uintMarshaler
	case reflect.Float32:
		return float32Marshaler
	case reflect.Float64:
		return float64Marshaler
	case reflect.String:
		return stringMarshaler
	case reflect.Slice:
		return newSliceMarshaler(t)
	case reflect.Array:
		return newArrayMarshaler(t)
	default:
		panic(fmt.Sprintf("dynamodb: %s type is not supported", t.Kind()))
	}
}
Пример #2
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)
	}
}
Пример #3
0
func convertVal(t reflect.Type, v reflect.Value) reflect.Value {
	var ptr Pointer
	if v.Type() == obj_t {
		ptr = v.Interface().(*Object).GetPtr()
	} else if v.Type() == ptr_t {
		ptr = v.Interface().(Pointer)
	}
	if ptr != nil {
		var ret reflect.Value
		if t.Implements(ptr_setter_i) {
			// Desired type implements PointerSetter so we are creating
			// new value with desired type and set it from ptr
			if t.Kind() == reflect.Ptr {
				ret = reflect.New(t.Elem())
			} else {
				ret = reflect.Zero(t)
			}
			ret.Interface().(PointerSetter).SetPtr(ptr)
		} else if t.Kind() == reflect.Ptr {
			// t doesn't implements PointerSetter but it is pointer
			// so we bypass type checking and setting it from ptr.
			ret = valueFromPointer(ptr, t)
		}
		return ret
	}
	return v
}
Пример #4
0
func getValueParser(t reflect.Type) func(s string) (reflect.Value, error) {
	if parser, ok := valueParsers[t]; ok {
		return parser
	}
	if t.Implements(unmarshalerType) {
		return func(s string) (reflect.Value, error) {
			v := reflect.Zero(t)
			buff, err := json.Marshal(s)
			if err != nil {
				return v, err
			}
			err = v.Interface().(json.Unmarshaler).UnmarshalJSON(buff)
			return v, err
		}
	}
	tt := reflect.PtrTo(t)
	if tt.Implements(unmarshalerType) {
		return func(s string) (reflect.Value, error) {
			v := reflect.New(t)
			buff, err := json.Marshal(s)
			if err != nil {
				return v, err
			}
			err = v.Interface().(json.Unmarshaler).UnmarshalJSON(buff)
			return reflect.Indirect(v), err
		}
	}
	return nil
}
Пример #5
0
func (m *structCache) getDecoder(typ reflect.Type) decoderFunc {
	if decoder, ok := typDecMap[typ]; ok {
		return decoder
	}

	if typ.Implements(unmarshalerType) {
		return unmarshalValue
	}

	kind := typ.Kind()
	switch kind {
	case reflect.Slice:
		elemKind := typ.Elem().Kind()
		if dec := sliceDecoders[elemKind]; dec != nil {
			return dec
		}
	case reflect.Ptr:
		fallthrough
	case reflect.Struct:
		if m.ext != nil {
			if decoder, ok := m.ext.decTypeMap[typ]; ok {
				return decoder
			}
		}
	}

	return valueDecoders[kind]
}
Пример #6
0
// ShouldNotImplement receives exactly two parameters and ensures
// that the first does NOT implement the interface type of the second.
func ShouldNotImplement(actual interface{}, expectedList ...interface{}) string {
	if fail := need(1, expectedList); fail != success {
		return fail
	}

	expected := expectedList[0]
	if fail := ShouldBeNil(expected); fail != success {
		return shouldCompareWithInterfacePointer
	}

	if fail := ShouldNotBeNil(actual); fail != success {
		return shouldNotBeNilActual
	}

	var actualType reflect.Type
	if reflect.TypeOf(actual).Kind() != reflect.Ptr {
		actualType = reflect.PtrTo(reflect.TypeOf(actual))
	} else {
		actualType = reflect.TypeOf(actual)
	}

	expectedType := reflect.TypeOf(expected)
	if fail := ShouldNotBeNil(expectedType); fail != success {
		return shouldCompareWithInterfacePointer
	}

	expectedInterface := expectedType.Elem()

	if actualType.Implements(expectedInterface) {
		return fmt.Sprintf(shouldNotHaveImplemented, actualType, expectedInterface)
	}
	return success
}
Пример #7
0
func Decoder(typ reflect.Type) valueDecoder {
	if typ == timeType {
		return decodeTimeValue
	}

	if reflect.PtrTo(typ).Implements(scannerType) {
		return decodeScannerAddrValue
	}

	if typ.Implements(scannerType) {
		return decodeScannerValue
	}

	kind := typ.Kind()

	if kind == reflect.Slice && typ.Elem().Kind() == reflect.Uint8 {
		return decodeBytesValue
	}

	if dec := valueDecoders[kind]; dec != nil {
		return dec
	}

	return nil
}
Пример #8
0
// isScalar returns true if the type can be parsed from a single string
func isScalar(t reflect.Type) (scalar, boolean bool) {
	// If it implements encoding.TextUnmarshaler then use that
	if t.Implements(textUnmarshalerType) {
		// scalar=YES, boolean=NO
		return true, false
	}

	// If we have a pointer then dereference it
	if t.Kind() == reflect.Ptr {
		t = t.Elem()
	}

	// Check for other special types
	switch t {
	case durationType, mailAddressType, ipType, macType:
		// scalar=YES, boolean=NO
		return true, false
	}

	// Fall back to checking the kind
	switch t.Kind() {
	case reflect.Bool:
		// scalar=YES, boolean=YES
		return true, true
	case reflect.String, reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
		reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64,
		reflect.Float32, reflect.Float64:
		// scalar=YES, boolean=NO
		return true, false
	}
	// scalar=NO, boolean=NO
	return false, false
}
Пример #9
0
func getTypeEncoder(typ reflect.Type) encoderFunc {
	kind := typ.Kind()

	if typ.Implements(encoderType) {
		return encodeCustomValue
	}

	// Addressable struct field value.
	if reflect.PtrTo(typ).Implements(encoderType) {
		return encodeCustomValuePtr
	}

	if typ.Implements(marshalerType) {
		return marshalValue
	}
	if encoder, ok := typEncMap[typ]; ok {
		return encoder
	}

	if kind == reflect.Slice && typ.Elem().Kind() == reflect.Uint8 {
		return encodeBytesValue
	}

	return valueEncoders[kind]
}
Пример #10
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
	}

	if kind == reflect.Slice && typ.Elem().Kind() == reflect.Uint8 {
		return decodeBytesValue
	}

	return valueDecoders[kind]
}
Пример #11
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)
	}
}
Пример #12
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)
}
Пример #13
0
func IsSupportUnmarshal(t reflect.Type) bool {
	if t.Kind() != reflect.Ptr {
		t = reflect.PtrTo(t)
	}

	return t.Implements(unmarshalerType)
}
Пример #14
0
func implementsUnpacker(t reflect.Type) bool {
	for _, tUnpack := range tUnpackers {
		if t.Implements(tUnpack) {
			return true
		}
	}

	return false
}
Пример #15
0
func isOkType(v reflect.Type) bool {
	if v.Implements(typeOfPropertyLoadSaver) {
		return true
	}
	if v.Kind() == reflect.Ptr && v.Elem().Kind() == reflect.Struct {
		return true
	}
	return false
}
Пример #16
0
// isUnmarshaler reports whether type t implements Unmarshaler.
func isUnmarshaler(t reflect.Type) bool {
	// We're checking for (likely) pointer-receiver methods
	// so if t is not a pointer, something is very wrong.
	// The calls above only invoke isUnmarshaler on pointer types.
	if t.Kind() != reflect.Ptr {
		panic("proto: misuse of isUnmarshaler")
	}
	return t.Implements(unmarshalerType)
}
Пример #17
0
func (t Type) Match(rt reflect.Type) bool {
	if rt.Implements(object_caster) {
		return t.IsA(TYPE_OBJECT)
	}
	if rt.Implements(type_getter) {
		if rt.Kind() == reflect.Ptr {
			rt = rt.Elem()
		}
		r := reflect.New(rt).Interface().(TypeGetter).Type()
		return t.QName() == r.QName()
	}
	switch rt.Kind() {
	case reflect.Invalid:
		return t == TYPE_INVALID

	case reflect.String:
		return t == TYPE_STRING

	case reflect.Int:
		return t == TYPE_GO_INT

	case reflect.Uint:
		return t == TYPE_GO_UINT

	case reflect.Int8:
		return t == TYPE_CHAR

	case reflect.Uint8:
		return t == TYPE_UCHAR

	case reflect.Int32:
		return t == TYPE_GO_INT32

	case reflect.Uint32:
		return t == TYPE_GO_UINT32

	case reflect.Int64:
		return t == TYPE_INT64

	case reflect.Uint64:
		return t == TYPE_UINT64

	case reflect.Bool:
		return t == TYPE_BOOLEAN

	case reflect.Float32:
		return t == TYPE_FLOAT

	case reflect.Float64:
		return t == TYPE_DOUBLE

	case reflect.Ptr:
		return t == TYPE_POINTER
	}
	return false
}
Пример #18
0
func validateModelType(sqlType string, goType reflect.Type) error {
	// If the go type implements the driver.Valuer and sql.Scanner
	// interfaces, just ignore the sql type and assume it is doing the
	// right thing. It would be possible to instantiate the go type and
	// check to see if it can handle the sql type, but that seems overly
	// complicated for the benefit.
	if goType.Implements(valuerType) &&
		reflect.PtrTo(goType).Implements(scannerType) {
		return nil
	}

	sqlType = strings.ToLower(sqlType)
	baseType := sqlBaseType(sqlType)

	valid := false
	switch baseType {
	case "int":
		valid = validateIntType(32, sqlType, goType)
	case "tinyint":
		// The "(1)" is really a formatting specifier, but MySQL uses it
		// when "bool" or "boolean" is specified as the type.
		valid = (sqlType == "tinyint(1)" && goType.Kind() == reflect.Bool)
		valid = valid || validateIntType(8, sqlType, goType)
	case "smallint":
		valid = validateIntType(16, sqlType, goType)
	case "mediumint":
		valid = validateIntType(32, sqlType, goType)
	case "bigint":
		valid = validateIntType(64, sqlType, goType)
	case "bit":
		valid = validateBitType(sqlType, goType)
	case "float":
		valid = validateFloatType(32, goType)
	case "double":
		valid = validateFloatType(64, goType)
	case "decimal":
		valid = validateFloatType(64, goType)
	case "date", "time", "datetime", "timestamp":
		valid = validateDateTimeType(goType)
	case "char", "varchar", "binary", "varbinary":
		fallthrough
	case "blob", "tinyblob", "mediumblob", "longblob":
		fallthrough
	case "text", "tinytext", "mediumtext", "longtext":
		valid = validateStringType(goType)
	case "enum":
		valid = (goType.Kind() == reflect.String)
	case "set":
		valid = (goType == setStringType)
	}

	if valid {
		return nil
	}
	return fmt.Errorf("incompatible types: \"%s\" vs \"%s\"", sqlType, goType)
}
Пример #19
0
// Call this once after each struct type declaration
func GetModelInfoFromType(modelType reflect.Type) *ModelInfo {
	if modelType.Kind() == reflect.Ptr {
		modelType = modelType.Elem()
	}
	if modelType.Kind() != reflect.Struct {
		return nil
	}
	if modelType.Implements(reflect.TypeOf((*sql.Scanner)(nil)).Elem()) {
		return nil
	}

	modelName := modelType.Name()

	// Check cache
	if allModelInfos[modelName] != nil {
		return allModelInfos[modelName]
	}

	// Construct
	m := &ModelInfo{}
	allModelInfos[modelName] = m
	m.Type = modelType
	m.TableName = strings.ToLower(modelName)

	// Fields
	numFields := m.Type.NumField()
	for i := 0; i < numFields; i++ {
		field := m.Type.Field(i)
		if field.Tag.Get("db") != "" {
			column, null, autoinc := parseDBTag(field.Tag.Get("db"))
			m.Fields = append(m.Fields, &ModelField{field, column, null, autoinc})
		}
	}

	// Simple & Prefixed
	fieldNames := []string{}
	fieldInsertNames := []string{}
	ph := []string{}
	for _, field := range m.Fields {
		fieldName, _, _ := parseDBTag(field.Tag.Get("db"))
		fieldNames = append(fieldNames, fieldName)
		if !field.Autoinc {
			fieldInsertNames = append(fieldInsertNames, fieldName)
			ph = append(ph, fmt.Sprintf("$%v", len(ph)+1))
		}
	}

	m.FieldsSimple = strings.Join(fieldNames, ", ")
	m.FieldsPrefixed = m.TableName + "." + strings.Join(fieldNames, ", "+m.TableName+".")
	m.FieldsInsert = strings.Join(fieldInsertNames, ", ")
	m.Placeholders = strings.Join(ph, ", ")

	return m
}
Пример #20
0
func IsImplemented(t, target reflect.Type) bool {
	if t.Implements(target) {
		return true
	}
	if t.Kind() == reflect.Struct {
		return reflect.PtrTo(t).Implements(target)
	} else if t.Kind() == reflect.Ptr {
		return t.Elem().Implements(target)
	}
	return false
}
Пример #21
0
func typeIsUnpacker(t reflect.Type) (reflect.Value, bool) {
	if t.Implements(tUnpacker) {
		return reflect.New(t).Elem(), true
	}

	if reflect.PtrTo(t).Implements(tUnpacker) {
		return reflect.New(t), true
	}

	return reflect.Value{}, false
}
Пример #22
0
func IfImplementsModel(t reflect.Type) bool {
	if t.Implements(_modelType) {
		return true
	}
	if t.Kind() != reflect.Ptr {
		if reflect.PtrTo(t).Implements(_modelType) {
			return true
		}
	}
	return false
}
Пример #23
0
//获取t对应的类型信息,不支持slice, function, map, pointer, interface, channel
//如果parentIdx的长度>0,则表示t是strut中的字段的类型信息, t为字段对应的类型
func getKeyInfoByParent(t reflect.Type, parent *keyInfo, parentIdx []int) (ki *keyInfo, err error) {
	ki = &keyInfo{}
	//判断是否实现了hasher接口
	if t.Implements(hasherT) {
		ki.isHasher = true
		return
	}
	ki.kind = t.Kind()

	if _, ok := engM[ki.kind]; ok {
		//简单类型,不需要再分解元素类型的信息
		ki.index = parentIdx
	} else {
		//some types can be used as key, we can use equals to test
		switch ki.kind {
		case reflect.Chan, reflect.Slice, reflect.Func, reflect.Map, reflect.Ptr, reflect.Interface:
			err = NonSupportKey
		case reflect.Struct:
			if parent == nil {
				//parent==nil表示t不是一个嵌套的struct,所以这里需要初始化fields
				parent = ki
				ki.fields = make([]*keyInfo, 0, t.NumField())
			}
			for i := 0; i < t.NumField(); i++ {
				f := t.Field(i)
				//skip unexported field,
				if len(f.PkgPath) > 0 {
					continue
				}

				idx := make([]int, len(parentIdx), len(parentIdx)+1)
				copy(idx, parentIdx)
				idx = append(idx, i)
				if fi, e := getKeyInfoByParent(f.Type, parent, idx); e != nil {
					err = e
					return
				} else {
					//fi.index = i
					parent.fields = append(ki.fields, fi)
				}
			}
		case reflect.Array:
			if ki.elementInfo, err = getKeyInfo(t.Elem()); err != nil {
				return
			}
			ki.size = t.Len()
			ki.index = parentIdx
		}
	}

	return

}
Пример #24
0
func (p *protoUnmarshaller) getObject(reflectType reflect.Type, object []byte) (interface{}, error) {
	if reflectType.Implements(reflect.TypeOf((*proto.Message)(nil)).Elem()) {
		protoMessage := reflect.New(reflectType.Elem()).Interface().(proto.Message)
		if err := proto.Unmarshal(object, protoMessage); err != nil {
			return nil, err
		}
		return protoMessage, nil
	}
	objectPtr := reflect.New(reflectType).Interface()
	if err := gob.NewDecoder(bytes.NewBuffer(object)).Decode(objectPtr); err != nil {
		return nil, err
	}
	return reflect.ValueOf(objectPtr).Elem().Interface(), nil
}
Пример #25
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]
}
Пример #26
0
// newTypeEncoder constructs an encoderFunc for a type.
// The returned encoder only checks CanAddr when allowAddr is true.
func newTypeEncoder(t reflect.Type, allowAddr bool) encoderFunc {
	if t.Implements(marshalerType) {
		return marshalerEncoder
	}
	if t.Kind() != reflect.Ptr && allowAddr {
		if reflect.PtrTo(t).Implements(marshalerType) {
			return newCondAddrEncoder(addrMarshalerEncoder, newTypeEncoder(t, false))
		}
	}

	// Check for psuedo-types first
	switch t {
	case timeType:
		return timePseudoTypeEncoder
	}

	switch t.Kind() {
	case reflect.Bool:
		return boolEncoder
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		return intEncoder
	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
		return uintEncoder
	case reflect.Float32, reflect.Float64:
		return floatEncoder
	case reflect.String:
		return stringEncoder
	case reflect.Interface:
		return interfaceEncoder
	case reflect.Struct:
		return newStructEncoder(t)
	case reflect.Map:
		return newMapEncoder(t)
	case reflect.Slice:
		return newSliceEncoder(t)
	case reflect.Array:
		return newArrayEncoder(t)
	case reflect.Ptr:
		return newPtrEncoder(t)
	case reflect.Func:
		// functions are a special case as they can be used internally for
		// optional arguments. Just return the raw function, if somebody tries
		// to pass a function to the database the JSON marshaller will catch this
		// anyway.
		return funcEncoder
	default:
		return unsupportedTypeEncoder
	}
}
Пример #27
0
// newTypeEncoder constructs an encoderFunc for a type.
// The returned encoder only checks CanAddr when allowAddr is true.
func newTypeEncoder(t reflect.Type, allowAddr bool) encoderFunc {
	// Special case for time.Time because it already implements
	// TextMarshaler which is not what we want as EDN.
	if t == timeType {
		return timeEncoder
	}
	if t.Kind() == reflect.Ptr && t.Elem() == timeType {
		return newPtrEncoder(t)
	}

	if t.Implements(textMarshalerType) {
		return textMarshalerEncoder
	}
	if t.Kind() != reflect.Ptr && allowAddr {
		if reflect.PtrTo(t).Implements(textMarshalerType) {
			return newCondAddrEncoder(addrTextMarshalerEncoder, newTypeEncoder(t, false))
		}
	}

	switch t.Kind() {
	case reflect.Bool:
		return boolEncoder
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		return intEncoder
	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
		return uintEncoder
	case reflect.Float32:
		return float32Encoder
	case reflect.Float64:
		return float64Encoder
	case reflect.String:
		return stringEncoder
	case reflect.Interface:
		return interfaceEncoder
	case reflect.Map:
		return newMapEncoder(t)
	case reflect.Slice:
		return newSliceEncoder(t)
	case reflect.Array:
		return newArrayEncoder(t)
	case reflect.Ptr:
		return newPtrEncoder(t)
	default:
		if t == listType {
			return listEncoder
		}
		return unsupportedTypeEncoder
	}
}
Пример #28
0
// newTypeEncoder constructs an encoderFunc for a type.
// The returned encoder only checks CanAddr when allowAddr is true.
func newTypeEncoder(t reflect.Type, allowAddr bool) encoderFunc {
	if t.Implements(marshalerType) {
		return marshalerEncoder
	}
	if t.Kind() != reflect.Ptr && allowAddr {
		if reflect.PtrTo(t).Implements(marshalerType) {
			return newCondAddrEncoder(addrMarshalerEncoder, newTypeEncoder(t, false))
		}
	}

	if t.Implements(textMarshalerType) {
		return textMarshalerEncoder
	}
	if t.Kind() != reflect.Ptr && allowAddr {
		if reflect.PtrTo(t).Implements(textMarshalerType) {
			return newCondAddrEncoder(addrTextMarshalerEncoder, newTypeEncoder(t, false))
		}
	}

	switch t.Kind() {
	case reflect.Bool:
		return boolEncoder
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		return intEncoder
	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
		return uintEncoder
	case reflect.Float32:
		return float32Encoder
	case reflect.Float64:
		return float64Encoder
	case reflect.String:
		return stringEncoder
	case reflect.Interface:
		return interfaceEncoder
	case reflect.Struct:
		return newStructEncoder(t)
	case reflect.Map:
		return newMapEncoder(t)
	case reflect.Slice:
		return newSliceEncoder(t)
	case reflect.Array:
		return newArrayEncoder(t)
	case reflect.Ptr:
		return newPtrEncoder(t)
	default:
		return unsupportedTypeEncoder
	}
}
Пример #29
0
func (m *structCache) getTypeEncoder(typ reflect.Type) encoderFunc {
	if typ.Implements(marshalerType) {
		return marshalValue
	}

	kind := typ.Kind()
	switch kind {
	case reflect.Slice:
		elemKind := typ.Elem().Kind()
		if enc := sliceEncoders[elemKind]; enc != nil {
			return enc
		}
	}

	return valueEncoders[kind]
}
func ensureTags(t *testing.T, gvk schema.GroupVersionKind, tp reflect.Type, parents []reflect.Type) {
	// This type handles its own encoding/decoding and doesn't need json tags
	if tp.Implements(marshalerType) && (tp.Implements(unmarshalerType) || reflect.PtrTo(tp).Implements(unmarshalerType)) {
		return
	}

	parents = append(parents, tp)

	switch tp.Kind() {
	case reflect.Map, reflect.Slice, reflect.Ptr:
		ensureTags(t, gvk, tp.Elem(), parents)

	case reflect.String, reflect.Bool, reflect.Float32, reflect.Int, reflect.Int32, reflect.Int64, reflect.Uint8, reflect.Uintptr, reflect.Uint32, reflect.Uint64, reflect.Interface:
		// no-op

	case reflect.Struct:
		for i := 0; i < tp.NumField(); i++ {
			f := tp.Field(i)
			jsonTag := f.Tag.Get("json")
			if len(jsonTag) == 0 {
				t.Errorf("External types should have json tags. %#v tags on field %v are: %s", gvk, f.Name, f.Tag)
				for i, tp := range parents {
					t.Logf("%s%v", strings.Repeat("  ", i), tp)
				}
			}

			jsonTagName := strings.Split(jsonTag, ",")[0]
			if len(jsonTagName) > 0 && (jsonTagName[0] < 'a' || jsonTagName[0] > 'z') && jsonTagName != "-" && allowedNonstandardJSONNames[tp] != jsonTagName {
				t.Errorf("External types should have json names starting with lowercase letter. %#v has json tag on field %v with name %s", gvk, f.Name, jsonTagName)
				t.Log(tp)
				t.Log(allowedNonstandardJSONNames[tp])
				for i, tp := range parents {
					t.Logf("%s%v", strings.Repeat("  ", i), tp)
				}
			}

			ensureTags(t, gvk, f.Type, parents)
		}

	default:
		t.Errorf("Unexpected type %v in %#v", tp.Kind(), gvk)
		for i, tp := range parents {
			t.Logf("%s%v:", strings.Repeat("  ", i), tp)
		}
	}
}