github.com/moleculer-go/moleculer@v0.3.3/payload/mapTransformers.go (about) 1 package payload 2 3 import ( 4 "fmt" 5 "reflect" 6 "time" 7 ) 8 9 type getFunc func(path string, source *interface{}) (interface{}, bool) 10 type asMapFunc func(source *interface{}) map[string]interface{} 11 type lenFunc func(source *interface{}) int 12 type mapTransformer struct { 13 name string 14 AsMap asMapFunc 15 Len lenFunc 16 } 17 18 func (transformer *mapTransformer) get(path string, source *interface{}) (interface{}, bool) { 19 sourceAsMap := transformer.AsMap(source) 20 value, found := sourceAsMap[path] 21 return value, found 22 } 23 24 var mapTransformers = []mapTransformer{ 25 mapTransformer{ 26 "map[string]interface {}", 27 func(source *interface{}) map[string]interface{} { 28 return (*source).(map[string]interface{}) 29 }, 30 func(source *interface{}) int { 31 return len((*source).(map[string]interface{})) 32 }, 33 }, 34 mapTransformer{ 35 "map[string]string", 36 func(source *interface{}) map[string]interface{} { 37 result := make(map[string]interface{}, len((*source).(map[string]string))) 38 for key, value := range (*source).(map[string]string) { 39 result[key] = value 40 } 41 return result 42 }, 43 func(source *interface{}) int { 44 return len((*source).(map[string]string)) 45 }, 46 }, 47 mapTransformer{ 48 "map[string]int", 49 func(source *interface{}) map[string]interface{} { 50 result := make(map[string]interface{}, len((*source).(map[string]int))) 51 for key, value := range (*source).(map[string]int) { 52 result[key] = value 53 } 54 return result 55 }, 56 func(source *interface{}) int { 57 return len((*source).(map[string]int)) 58 }, 59 }, 60 mapTransformer{ 61 "map[string]int64", 62 func(source *interface{}) map[string]interface{} { 63 result := make(map[string]interface{}, len((*source).(map[string]int64))) 64 for key, value := range (*source).(map[string]int64) { 65 result[key] = value 66 } 67 return result 68 }, 69 func(source *interface{}) int { 70 return len((*source).(map[string]int64)) 71 }, 72 }, 73 mapTransformer{ 74 "map[string]uint64", 75 func(source *interface{}) map[string]interface{} { 76 result := make(map[string]interface{}, len((*source).(map[string]uint64))) 77 for key, value := range (*source).(map[string]uint64) { 78 result[key] = value 79 } 80 return result 81 }, 82 func(source *interface{}) int { 83 return len((*source).(map[string]uint64)) 84 }, 85 }, 86 mapTransformer{ 87 "map[string]float32", 88 func(source *interface{}) map[string]interface{} { 89 result := make(map[string]interface{}, len((*source).(map[string]float32))) 90 for key, value := range (*source).(map[string]float32) { 91 result[key] = value 92 } 93 return result 94 }, 95 func(source *interface{}) int { 96 return len((*source).(map[string]float32)) 97 }, 98 }, 99 mapTransformer{ 100 "map[string]float64", 101 func(source *interface{}) map[string]interface{} { 102 result := make(map[string]interface{}, len((*source).(map[string]float64))) 103 for key, value := range (*source).(map[string]float64) { 104 result[key] = value 105 } 106 return result 107 }, 108 func(source *interface{}) int { 109 return len((*source).(map[string]float64)) 110 }, 111 }, 112 mapTransformer{ 113 "map[string]time.Time", 114 func(source *interface{}) map[string]interface{} { 115 result := make(map[string]interface{}, len((*source).(map[string]time.Time))) 116 for key, value := range (*source).(map[string]time.Time) { 117 result[key] = value 118 } 119 return result 120 }, 121 func(source *interface{}) int { 122 return len((*source).(map[string]time.Time)) 123 }, 124 }, 125 } 126 127 // GetValueType : return a string that represents the map type. 128 // examples: map[string]int , map[string]string, map[string]float32 and etc 129 // there are a few possible implementations, Reflection is not very 130 // popular in GO.. so this uses mt.Sprintf .. but we need to 131 // test a second version of this with Reflect to check what is faster 132 func GetValueType(value *interface{}) string { 133 return fmt.Sprintf("%T", (*value)) 134 } 135 136 func rawPayloadMapTransformer(source *interface{}) map[string]interface{} { 137 sourcePayload := (*source).(*RawPayload) 138 return sourcePayload.RawMap() 139 } 140 141 func rawPayloadMapLen(source *interface{}) int { 142 sourcePayload := (*source).(*RawPayload) 143 return sourcePayload.Len() 144 } 145 146 func reflectionMapLen(source *interface{}) int { 147 rv := reflect.ValueOf(*source) 148 return rv.Len() 149 } 150 151 // reflectionMapTransformer takes a value that is map like and transform into a generic map. 152 func reflectionMapTransformer(source *interface{}) map[string]interface{} { 153 rv := reflect.ValueOf(*source) 154 result := make(map[string]interface{}, rv.Len()) 155 for _, mkey := range rv.MapKeys() { 156 item := rv.MapIndex(mkey) 157 key := mkey.String() 158 value := item.Interface() 159 if item.Kind() == reflect.Map { 160 mt := MapTransformer(&value) 161 result[key] = mt.AsMap(&value) 162 } else if item.Kind() == reflect.Array || item.Kind() == reflect.Slice { 163 at := ArrayTransformer(&value) 164 result[key] = at.InterfaceArray(&value) 165 } else { 166 result[key] = value 167 } 168 } 169 return result 170 } 171 172 // MapTransformer : return the map transformer for the specific map type 173 func MapTransformer(value *interface{}) *mapTransformer { 174 175 //try this 176 // switch vt := (*value).(type) { 177 // case map[string]interface{}: 178 // //do something. 179 // fmt.Println("worked vt: ", vt) 180 // default: 181 // //do something else 182 // fmt.Println("worked also vt: ", vt) 183 // } 184 185 valueType := GetValueType(value) 186 for _, transformer := range mapTransformers { 187 if valueType == transformer.name { 188 return &transformer 189 } 190 } 191 if valueType == "*payload.RawPayload" { 192 transformer := mapTransformer{ 193 "*payload.RawPayload", 194 rawPayloadMapTransformer, 195 rawPayloadMapLen, 196 } 197 return &transformer 198 } 199 200 //try to use reflection 201 rt := reflect.TypeOf(*value) 202 if rt != nil && rt.Kind() == reflect.Map { 203 //fmt.Println("MapTransformer - reflection transformer will be used for valueType: ", valueType) 204 return &mapTransformer{"reflection", reflectionMapTransformer, reflectionMapLen} 205 } 206 //fmt.Println("MapTransformer - transformer not found for type: ", valueType) 207 return nil 208 }