gitlab.com/evatix-go/core@v1.3.55/coredata/coredynamic/ReflectSetFromTo.go (about) 1 package coredynamic 2 3 import ( 4 "encoding/json" 5 "reflect" 6 7 "gitlab.com/evatix-go/core/coredata/corejson" 8 "gitlab.com/evatix-go/core/errcore" 9 "gitlab.com/evatix-go/core/internal/reflectinternal" 10 "gitlab.com/evatix-go/core/isany" 11 ) 12 13 // ReflectSetFromTo 14 // 15 // Set any object from to toPointer object 16 // 17 // Valid Inputs or Supported (https://t.ly/1Lpt): 18 // - From, To: (null, null) -- do nothing 19 // - From, To: (sameTypePointer, sameTypePointer) -- try reflection 20 // - From, To: (sameTypeNonPointer, sameTypePointer) -- try reflection 21 // - From, To: ([]byte or *[]byte, otherType) -- try unmarshal, reflect 22 // - From, To: (otherType, *[]byte) -- try marshal, reflect 23 // 24 // Validations: 25 // - Check null, if both null no error return quickly. 26 // - NotSupported returns as error. 27 // - NotSupported: (from, to) - (..., not pointer) 28 // - NotSupported: (from, to) - (null, notNull) 29 // - NotSupported: (from, to) - (notNull, null) 30 // - NotSupported: (from, to) - not same type and not bytes on any 31 // - `From` null or nil is not supported and will return error. 32 // 33 // Reference: 34 // - Reflection String Set Example : https://go.dev/play/p/fySLYuOvoRK.go?download=true 35 // - Method document screenshot : https://prnt.sc/26dmf5g 36 func ReflectSetFromTo( 37 from, 38 toPointer interface{}, 39 ) error { 40 isLeftNull, isRightNull := isany.NullLeftRight( 41 from, 42 toPointer) 43 44 if isLeftNull == isRightNull && isLeftNull { 45 return nil 46 } 47 48 leftRfType := reflect.TypeOf(from) 49 rightRfType := reflect.TypeOf(toPointer) 50 51 if isRightNull { 52 return errcore. 53 InvalidNullPointerType. 54 MsgCsvRefError( 55 "\"destination pointer is null, cannot proceed further!\""+supportedTypesMessageReference, 56 "FromType", leftRfType, "ToType", rightRfType) 57 } 58 59 rightKind := rightRfType.Kind() 60 isRightKindNotPointer := rightKind != reflect.Ptr 61 if isRightKindNotPointer { 62 return errcore.UnexpectedType. 63 MsgCsvRefError( 64 "\"destination or toPointer must be a pointer to set!\""+supportedTypesMessageReference, 65 "FromType", leftRfType, "ToType", rightRfType) 66 } 67 68 isSameType := leftRfType == rightRfType 69 leftRv := reflect.ValueOf(from) 70 rightRv := reflect.ValueOf(toPointer) // right is pointer confirmed by previous validation 71 isLeftAnyNull := reflectinternal.IsNullUsingReflectValue(leftRv) || 72 reflectinternal.IsNull(leftRfType) 73 74 if isLeftAnyNull { 75 return errcore. 76 InvalidValueType. 77 SrcDestinationErr( 78 "`from` is nil, cannot set null or nil to destination.\"!"+supportedTypesMessageReference, 79 "FromType", leftRfType, 80 "ToType", rightRfType) 81 } 82 83 isLeftBytes := leftRfType == emptyBytesType 84 isLeftPointerBytes := leftRfType == emptyBytesPointerType 85 isLeftBytesOrPointerBytes := isLeftBytes || isLeftPointerBytes 86 isRightBytesPointer := rightRfType == emptyBytesPointerType 87 isAnyBytes := isLeftBytesOrPointerBytes || isRightBytesPointer 88 89 // case : From, To : (sameTypePointer, sameTypePointer) -- try reflection 90 if leftRfType == rightRfType { 91 // reflect, both same 92 rightRv.Elem().Set(leftRv.Elem()) 93 94 return nil 95 } 96 97 // case : From, To : (sameTypeNonPointer, sameTypePointer) -- try reflection 98 if leftRfType.Kind() != reflect.Ptr && !isLeftNull && leftRfType == rightRfType.Elem() { 99 rightRv.Elem().Set(leftRv) 100 101 return nil 102 } 103 104 isNotSupportedType := !(isSameType || isAnyBytes) 105 106 if isNotSupportedType { 107 return errcore. 108 TypeMismatchType. 109 SrcDestinationErr( 110 "supported: \"types are same pointer or any bytes or destination is pointer.\"!"+supportedTypesMessageReference, 111 "FromType", leftRfType, 112 "ToType", rightRfType) 113 } 114 115 // case : From, To : ([]byte or *[]byte, otherType) -- try unmarshal, reflect 116 if isLeftBytes { 117 return corejson. 118 Deserialize. 119 UsingBytes( 120 from.([]byte), 121 toPointer) 122 } 123 124 // case : From, To : (*[]byte, otherType) -- try unmarshal, reflect 125 if isLeftPointerBytes { 126 return corejson. 127 Deserialize. 128 UsingBytesPointer( 129 from.(*[]byte), 130 toPointer) 131 } 132 133 // case : From, To: (otherType, *[]byte) -- try marshal, reflect 134 var rawBytes []byte 135 var finalErr error 136 137 if isRightBytesPointer { 138 rawBytes, finalErr = json.Marshal(from) 139 } 140 141 if finalErr != nil { 142 return errcore. 143 MarshallingFailedType. 144 SrcDestinationErr( 145 finalErr.Error(), 146 "FromType", leftRfType, 147 "ToType", rightRfType) 148 } 149 150 err := json.Unmarshal( 151 rawBytes, 152 toPointer) 153 154 if err == nil { 155 return nil 156 } 157 158 // has error 159 return errcore. 160 UnMarshallingFailedType. 161 SrcDestinationErr( 162 err.Error(), 163 "FromType", leftRfType, 164 "ToType", rightRfType) 165 }