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  }