| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485 | package iiimport (	"encoding/json"	"errors"	"fmt"	"reflect"	"strconv"	"strings"	"time"	"golib/v2/features/mo"	"golib/v2/gnet")var (	errCovertReturn = func(f *FieldInfo, v any) error {		return fmt.Errorf("%s: %v not covert name: %s valueType: %v", getCallerName(), v, f.Name, valueType(v))	}	errCovertRetErr = func(f *FieldInfo, v any, err error) error {		return fmt.Errorf("%s: %v not covert name: %s valueType: %s err: %s", getCallerName(), v, f.Name, valueType(v), err)	})// Convert 将 value 转换为 Type 类型. 遇到任何错误时返回// value 被设计为传入非指针类型参数. 当前除 mo.TypeBinary 支持传入指针类型(用作反射代码示例), 其他 Type 都会返回错误// 详情见 field_covert_test.gofunc (f *FieldInfo) Convert(value any) (any, error) {	switch f.Type {	case mo.TypeDouble:		return f.convertDouble(value)	case mo.TypeString:		return f.convertString(value)	case mo.TypeObject:		return f.convertObject(value)	case mo.TypeArray:		return f.convertArray(value)	case mo.TypeBinary:		return f.convertBinary(value)	case mo.TypeObjectID:		return f.convertObjectID(value)	case mo.TypeBoolean:		return f.convertBoolean(value)	case mo.TypeDateTime:		return f.convertDate(value)	case mo.TypeInt32:		return f.convertInt32(value)	case mo.TypeInt64:		return f.convertInt64(value)	default:		return nil, errCovertReturn(f, value)	}}func (f *FieldInfo) convertDouble(value any) (float64, error) {	switch v := value.(type) {	case float64, float32, int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64:		val := reflect.ValueOf(v).Convert(reflect.TypeOf(float64(0)))		return toFloat64Decimal(val.Float(), f.Decimal), nil	case string:		if v == "" {			return 0, nil		}		val, err := strconv.ParseFloat(v, 64)		if err != nil {			return 0, errCovertRetErr(f, value, err)		}		return toFloat64Decimal(val, f.Decimal), nil	default:		return 0, errCovertReturn(f, value)	}}func (f *FieldInfo) convertString(value any) (string, error) {	if value == nil {		return "", errors.New("value is nil")	}	rv := reflect.ValueOf(value)	switch rv.Type().Kind() {	case reflect.String:		return rv.String(), nil	case reflect.Bool:		return strconv.FormatBool(rv.Bool()), nil	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:		return strconv.FormatInt(rv.Int(), 10), nil	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:		return strconv.FormatUint(rv.Uint(), 10), nil	case reflect.Float64, reflect.Float32:		return strconv.FormatFloat(rv.Float(), 'g', -1, 64), nil	case reflect.Map:		val, _ := f.convertObject(value)		bv, err := json.Marshal(val)		if err != nil {			return "", err		}		return string(bv), nil	case reflect.Array, reflect.Slice:		length := rv.Len()		val := make([]string, length)		for i := 0; i < length; i++ {			sv, err := f.convertString(rv.Index(i).Interface())			if err != nil {				return "", err			}			val[i] = sv		}		return strings.Join(val, ","), nil	default:		return "", errCovertReturn(f, value)	}}// convertObject 将 value 转换为 mo.M 类型// 对于已经是 map 类型的 value, 则需要深度 copy 后返回.// 当大量转换时可能会出现性能影响// 2023/01/28: from eric: object/map 类型的数据不允许 value 再次作为 map, 即只能存在一层 map // 移动至 ItemInfo 的 initFieldMap 中实现func (f *FieldInfo) convertObject(value any) (mo.M, error) {	var (		m   mo.M		err error	)	switch val := value.(type) {	case mo.D:		m, err = mo.Convert.ME(val)	case mo.M:		m, err = mo.DeepMapCopy(val)	default:		var b []byte		b, err = mo.MarshalExtJSON(val, true, true)		if err != nil {			return nil, errCovertRetErr(f, value, err)		}		err = mo.UnmarshalExtJSON(b, true, &m)	}	if err != nil {		return nil, errCovertRetErr(f, value, err)	}	if f.NoField {		return m, nil	}	fm := make(mo.M)	for _, sf := range f.Fields {		sv, ok := m[sf.Name]		if !ok {			continue // 如果字段不存 SubField 内则跳过解析		}		sfv, err := sf.Convert(sv)		if err != nil {			return nil, errCovertRetErr(f, value, err)		}		fm[sf.Name] = sfv	}	return fm, nil}func (f *FieldInfo) convertArray(value any) (mo.A, error) {	if value == nil {		return nil, errors.New("value is nil")	}	rv := reflect.ValueOf(value)	switch rv.Type().Kind() {	case reflect.Slice, reflect.Array:		length := rv.Len()		n := make(mo.A, length)		for i := 0; i < length; i++ {			rvi := rv.Index(i).Interface()			if err := covertArray(f, rvi, &n, i); err != nil {				return nil, err			}		}		return n, nil	case reflect.String:		v := rv.String()		if strings.TrimSpace(v) == "" {			return mo.A{}, nil		}		if indexEqual(v, "{", "}") {			n := make(mo.A, 1)			if err := covertArray(f, v, &n, 0); err != nil {				return nil, err			}			return n, nil		}		if indexEqual(v, "[", "]") {			// 移除括号			v = strings.TrimPrefix(v, "[")			v = strings.TrimSuffix(v, "]")			// 如果包含 , 表示数组内有多个元素			if strings.Contains(v, ",") {				str := strings.Split(v, ",")				n := make(mo.A, len(str))				for i, s := range str {					if err := covertArray(f, s, &n, i); err != nil {						return nil, err					}				}				return n, nil			} else {				// 否则表示只有一个元素				n := make(mo.A, 1)				if err := covertArray(f, v, &n, 0); err != nil {					return nil, err				}				return n, nil			}		} else {			n := make(mo.A, 1)			if err := covertArray(f, v, &n, 0); err == nil {				return n, nil			}		}		return nil, errCovertReturn(f, v)	case reflect.Float32, reflect.Float64, reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,		reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:		return mo.A{value}, nil	case reflect.Map:		// 兼容 javaScript 传入空数组时会被 Go 语言解析为 (interface{}|map[string]interface{}) 的问题		return mo.A{}, nil	default:		return nil, errCovertReturn(f, value)	}}// convertBinaryfunc (f *FieldInfo) convertBinary(value any) (mo.Binary, error) {	if value == nil {		return mo.Binary{}, errors.New("value is nil")	}	rv := reflect.ValueOf(value)	// 获取 value 的类型, 例如 pointer, int64, float64, map, slice, array	switch rv.Type().Kind() {	case reflect.Pointer:		// 由于首先确认 value 是指针, 因此此处无需再次判断 CanSet		// if rv.Elem().CanSet() {		//		// }		// 当类型为 Pointer 时则需要使用 Elem() 函数操作		rvp := rv.Type().Elem()		// 所以 value 作为一个指针传入时, 先判断指针的类型是否为 Array 或 Slice		if rvp.Kind() != reflect.Array && rvp.Kind() != reflect.Slice {			return mo.Binary{}, errCovertReturn(f, value)		}		// 由于已知 rvp 为 Array 或 Slice 类型, 则再次调用 Elem() 函数表示获取其元素类型		// 备忘录: 若数组内的元素数据类型不一致时则 Kind() 会返回 interface		// uint8: [1,2,3,4,5]		// interface: ["1", 3.14, []byte{0x01, 0x02}]		if rvp.Elem().Kind() != reflect.Uint8 {			return mo.Binary{}, errCovertReturn(f, value)		}		// 检查完毕指针内部的类型后, 应继续调用 rv 表示使用指针操作		// 因此通过 rv.Elem() 调用 Bytes()		return mo.Binary{Data: rv.Elem().Bytes()}, nil	case reflect.Uint8:		return mo.Binary{Data: []byte{uint8(rv.Uint())}}, nil	case reflect.Slice, reflect.Array:		if rv.Type().Elem().Kind() != reflect.Uint8 {			return mo.Binary{}, errCovertReturn(f, value)		}		length := rv.Len()		val := make([]byte, length)		for i := 0; i < length; i++ {			val[i] = rv.Index(i).Interface().(byte)		}		return mo.Binary{Data: val}, nil	case reflect.String:		val := gnet.String(rv.String()).Hex()		if val == nil {			return mo.Binary{}, errCovertReturn(f, value)		}		return mo.Binary{Data: val}, nil	case reflect.Struct:		val, ok := rv.Interface().(mo.Binary)		if ok {			if val.IsZero() {				return mo.Binary{}, errCovertReturn(f, value)			}			return val, nil		}		fallthrough	default:		return mo.Binary{}, errCovertReturn(f, value)	}}func (f *FieldInfo) convertObjectID(value any) (mo.ObjectID, error) {	switch v := value.(type) {	case mo.ObjectID:		if v.IsZero() && f.Required {			return mo.NilObjectID, errCovertReturn(f, value)		}		return v, nil	case string:		if v == "new" {			return mo.ID.New(), nil		}		// 当 v 不等于空, 则不关心 Required 是否为 true		if v != "" {			val, err := mo.ID.From(v)			if err != nil {				return mo.NilObjectID, errCovertRetErr(f, val, err)			}			return val, nil		} else {			if f.Required {				return mo.NilObjectID, errCovertReturn(f, value)			}			return mo.NilObjectID, nil		}	default:		return mo.NilObjectID, errCovertReturn(f, value)	}}func (f *FieldInfo) convertBoolean(value any) (bool, error) {	switch v := value.(type) {	case bool:		return v, nil	case string:		if v == "" {			return false, nil		}		val, err := strconv.ParseBool(v)		if err != nil {			return false, errCovertRetErr(f, value, err)		}		return val, nil	case uint, uint8, uint16, uint32, uint64, int, int8, int16, int32, int64, float32, float64:		val := reflect.ValueOf(v).Convert(reflect.TypeOf(int64(0)))		return val.Int() == 1, nil	default:		return false, errCovertReturn(f, value)	}}// convertDate 将 value 转换为 mo.DateTime 类型// convertDate 函数会将 value 用做 毫秒 进行解析func (f *FieldInfo) convertDate(value any) (mo.DateTime, error) {	switch v := value.(type) {	case mo.DateTime:		return mo.NewDateTimeFromTime(v.Time()), nil	case time.Time:		if v.IsZero() {			return 0, errCovertReturn(f, value)		}		return mo.NewDateTimeFromTime(v), nil	case time.Duration:		return mo.NewDateTimeFromTime(time.UnixMilli(v.Milliseconds())), nil	case uint, uint8, uint16, uint32, uint64, int, int8, int16, int32, int64, float32, float64:		val := reflect.ValueOf(v).Convert(reflect.TypeOf(int64(0)))		return mo.NewDateTimeFromTime(time.UnixMilli(val.Int())), nil	case string:		if v == "" {			return 0, nil		}		if v == "now" {			return mo.NewDateTime(), nil		}		if strings.Contains(v, "-") || strings.Contains(v, ":") {			tim, err := mo.ResolveDateTime(v)			if err != nil {				return 0, errCovertRetErr(f, value, err)			}			return tim, nil		}		val, err := strconv.ParseInt(v, 10, 64)		if err != nil {			return 0, errCovertRetErr(f, value, err)		}		return mo.NewDateTimeFromTime(time.UnixMilli(val)), nil	case []byte:		if val := gnet.BigEndian.Int64(v); val > 0 {			return mo.NewDateTimeFromTime(time.UnixMilli(val)), nil		}		return 0, errCovertReturn(f, value)	default:		return 0, errCovertReturn(f, value)	}}func (f *FieldInfo) convertInt32(value any) (int32, error) {	switch v := value.(type) {	case int32:		return v, nil	case int64:		return int32(v), nil	case float64:		return int32(v), nil	case uint64:		return int32(v), nil	case int:		return int32(v), nil	case uint:		return int32(v), nil	case uint8:		return int32(v), nil	case uint16:		return int32(v), nil	case uint32:		return int32(v), nil	case int8:		return int32(v), nil	case int16:		return int32(v), nil	case float32:		return int32(v), nil	case string:		if v == "" {			return 0, nil		}		val, err := strconv.ParseInt(v, 10, 32)		if err != nil {			return 0, errCovertRetErr(f, val, err)		}		return int32(val), nil	case []byte:		if val := gnet.BigEndian.Int32(v); val > 0 {			return val, nil		}		return 0, errCovertReturn(f, value)	case time.Duration:		return int32(v.Milliseconds()), nil	case time.Time:		return int32(v.UnixMilli()), nil	case mo.DateTime:		return int32(v.Time().UnixMilli()), nil	default:		return 0, errCovertReturn(f, value)	}}func (f *FieldInfo) convertInt64(value any) (int64, error) {	switch v := value.(type) {	case int64:		return v, nil	case float64:		return int64(v), nil	case uint64:		return int64(v), nil	case int:		return int64(v), nil	case uint:		return int64(v), nil	case uint8:		return int64(v), nil	case uint16:		return int64(v), nil	case uint32:		return int64(v), nil	case int8:		return int64(v), nil	case int16:		return int64(v), nil	case int32:		return int64(v), nil	case float32:		return int64(v), nil	case string:		if v == "" {			return 0, nil		}		val, err := strconv.ParseInt(v, 10, 64)		if err != nil {			return 0, errCovertRetErr(f, val, err)		}		return val, nil	case []byte:		if val := gnet.BigEndian.Int64(v); val > 0 {			return val, nil		}		return 0, errCovertReturn(f, value)	case time.Duration:		return v.Milliseconds(), nil	case time.Time:		return v.UnixMilli(), nil	case mo.DateTime:		return v.Time().UnixMilli(), nil	default:		return 0, errCovertReturn(f, value)	}}
 |