github.com/wfusion/gofusion@v1.1.14/common/utils/conv.go (about) 1 package utils 2 3 import ( 4 "reflect" 5 "unsafe" 6 7 "github.com/pkg/errors" 8 "github.com/spf13/cast" 9 10 "github.com/wfusion/gofusion/common/constant" 11 "github.com/wfusion/gofusion/common/constraint" 12 ) 13 14 // SliceMapping Mapping slice convert go1.18 version 15 func SliceMapping[T, K any](s []T, mapFn func(t T) K) (d []K) { 16 if s == nil { 17 return 18 } 19 d = make([]K, 0, len(s)) 20 for _, item := range s { 21 d = append(d, mapFn(item)) 22 } 23 return 24 } 25 26 // SortableToGeneric convert sortable type to generic type 27 func SortableToGeneric[T, K constraint.Sortable](s T) (d K) { 28 switch any(d).(type) { 29 case int: 30 return any(cast.ToInt(s)).(K) 31 case int8: 32 return any(cast.ToInt8(s)).(K) 33 case int16: 34 return any(cast.ToInt16(s)).(K) 35 case int32: 36 return any(cast.ToInt32(s)).(K) 37 case int64: 38 return any(cast.ToInt64(s)).(K) 39 case *int: 40 return any(AnyPtr(cast.ToInt(s))).(K) 41 case *int8: 42 return any(AnyPtr(cast.ToInt8(s))).(K) 43 case *int16: 44 return any(AnyPtr(cast.ToInt16(s))).(K) 45 case *int32: 46 return any(AnyPtr(cast.ToInt32(s))).(K) 47 case *int64: 48 return any(AnyPtr(cast.ToInt64(s))).(K) 49 case uint: 50 return any(cast.ToUint(s)).(K) 51 case uint8: 52 return any(cast.ToUint8(s)).(K) 53 case uint16: 54 return any(cast.ToUint16(s)).(K) 55 case uint32: 56 return any(cast.ToUint32(s)).(K) 57 case uint64: 58 return any(cast.ToUint64(s)).(K) 59 case *uint: 60 return any(AnyPtr(cast.ToUint(s))).(K) 61 case *uint8: 62 return any(AnyPtr(cast.ToUint8(s))).(K) 63 case *uint16: 64 return any(AnyPtr(cast.ToUint16(s))).(K) 65 case *uint32: 66 return any(AnyPtr(cast.ToUint32(s))).(K) 67 case *uint64: 68 return any(AnyPtr(cast.ToUint64(s))).(K) 69 case float32: 70 return any(cast.ToFloat32(s)).(K) 71 case float64: 72 return any(cast.ToFloat64(s)).(K) 73 case *float32: 74 return any(AnyPtr(cast.ToFloat32(s))).(K) 75 case *float64: 76 return any(AnyPtr(cast.ToFloat64(s))).(K) 77 case string: 78 return any(cast.ToString(s)).(K) 79 case *string: 80 return any(AnyPtr(cast.ToString(s))).(K) 81 default: 82 panic(errors.Errorf("cannot mapping %T", d)) 83 } 84 } 85 86 var sortableReflectType = []reflect.Type{ 87 constant.IntType, 88 constant.UintType, 89 constant.StringType, 90 constant.Float32Type, 91 constant.Float64Type, 92 constant.BoolType, 93 } 94 95 // ComparableToSortable convert generic type to sortable type 96 func ComparableToSortable[T comparable](s T) (d any) { 97 val := reflect.ValueOf(s) 98 typ := val.Type() 99 for _, sortableType := range sortableReflectType { 100 if typ.ConvertibleTo(sortableType) { 101 return val.Convert(sortableType).Interface() 102 } 103 } 104 105 return 106 } 107 108 // SliceConvert >= go1.18 recommend to use SliceMapping 109 func SliceConvert(src any, dstType reflect.Type) any { 110 srcVal := reflect.ValueOf(src) 111 srcType := reflect.TypeOf(src) 112 dstVal := reflect.Indirect(reflect.New(dstType)) 113 if srcType.Kind() != reflect.Slice || dstType.Kind() != reflect.Slice { 114 panic(errors.Errorf("src or dst type is invalid [src[%s] dst[%s]]", srcType.Kind(), dstType.Kind())) 115 } 116 117 isInterfaceSlice := false 118 srcElemType := srcType.Elem() 119 if srcType == constant.AnySliceType { 120 if srcVal.Len() == 0 { 121 return dstVal.Interface() 122 } 123 srcElemType = reflect.TypeOf(srcVal.Index(0).Interface()) 124 isInterfaceSlice = true 125 } 126 127 dstElemType := dstType.Elem() 128 if !srcElemType.ConvertibleTo(dstElemType) { 129 panic(errors.Errorf("src elem is not convertible to dst elem [src[%s] dst[%s]]", 130 srcElemType.Kind(), dstElemType.Kind())) 131 } 132 133 length := srcVal.Len() 134 for i := 0; i < length; i++ { 135 srcElem := srcVal.Index(i) 136 if isInterfaceSlice { 137 srcElem = reflect.ValueOf(srcVal.Index(i).Interface()) 138 } 139 dstVal = reflect.Append(dstVal, srcElem.Convert(dstElemType)) 140 } 141 142 return dstVal.Interface() 143 } 144 145 func AnyPtr[T any](s T) *T { return &s } 146 147 // UnsafeStringToBytes converts string to byte slice without a memory allocation. 148 // Fork from github.com/gin-gonic/gin@v1.7.7/internal/bytesconv/bytesconv.go 149 func UnsafeStringToBytes(s string) []byte { 150 return *(*[]byte)(unsafe.Pointer( 151 &struct { 152 string 153 Cap int 154 }{s, len(s)}, 155 )) 156 } 157 158 // UnsafeBytesToString converts byte slice to string without a memory allocation. 159 // Fork from github.com/gin-gonic/gin@v1.7.7/internal/bytesconv/bytesconv.go 160 func UnsafeBytesToString(b []byte) string { 161 return *(*string)(unsafe.Pointer(&b)) 162 }