github.com/influx6/npkg@v0.8.8/nreflect/reflection.go (about)

     1  package nreflect
     2  
     3  import (
     4  	"errors"
     5  	"fmt"
     6  	"reflect"
     7  	"strings"
     8  )
     9  
    10  // ErrInvalid is returned when a type fails certain conditions.
    11  var ErrInvalid = errors.New("invalid types, failed conditions")
    12  
    13  // ErrPanic is returned when a panic happens.
    14  var ErrPanic = errors.New("panic occured")
    15  
    16  // ErrNotFunction is returned when the type is not a reflect.Func.
    17  var ErrNotFunction = errors.New("Not A Function Type")
    18  
    19  // IsFuncType returns true/false if the interface provided is a func type.
    20  func IsFuncType(elem interface{}) bool {
    21  	_, err := FuncType(elem)
    22  	if err != nil {
    23  		return false
    24  	}
    25  	return true
    26  }
    27  
    28  // TypeValidation defines a function which validates a
    29  // a given set against some condition.
    30  type TypeValidation func([]reflect.Type) error
    31  
    32  // AreaValidation defines a function which validates a
    33  // a given set against some condition.
    34  type AreaValidation func(arguments []reflect.Type, returns []reflect.Type) error
    35  
    36  // ValidateFuncArea validates giving function arguments and returns types against AreaValidation
    37  // functions.
    38  func ValidateFuncArea(fn interface{}, conditions ...AreaValidation) error {
    39  	if len(conditions) == 0 {
    40  		return nil
    41  	}
    42  
    43  	funcTl, err := FuncType(fn)
    44  	if err != nil {
    45  		return err
    46  	}
    47  
    48  	args, err := getFuncArgumentsType(funcTl)
    49  	if err != nil {
    50  		return err
    51  	}
    52  
    53  	rets, err := getFuncReturnsType(funcTl)
    54  	if err != nil {
    55  		return err
    56  	}
    57  
    58  	for _, cond := range conditions {
    59  		if err = cond(args, rets); err != nil {
    60  			return err
    61  		}
    62  	}
    63  
    64  	return nil
    65  }
    66  
    67  // TypeName returns the original typename of giving target.
    68  func TypeName(t interface{}) string {
    69  	var ref = reflect.ValueOf(t)
    70  	if ref.Kind() == reflect.Ptr {
    71  		ref = ref.Elem()
    72  	}
    73  	return ref.Type().Name()
    74  }
    75  
    76  func NameOf(obj interface{}) string {
    77  	name, ok := obj.(string)
    78  	if ok {
    79  		return name
    80  	}
    81  	return nameOfType(reflect.TypeOf(obj))
    82  }
    83  
    84  func nameOfType(t reflect.Type) string {
    85  	stars := ""
    86  	if t == nil {
    87  		return "nil"
    88  	}
    89  
    90  	for t.Kind() == reflect.Ptr {
    91  		stars += "*"
    92  		t = t.Elem()
    93  	}
    94  
    95  	if t.Kind() == reflect.Interface {
    96  		stars = ""
    97  	}
    98  	return t.PkgPath() + "/" + stars + t.Name()
    99  }
   100  
   101  // ValidateFunc validates giving function arguments and returns types against TypeValidation
   102  // functions.
   103  func ValidateFunc(fn interface{}, argRules, returnRules []TypeValidation) error {
   104  	funcTl, err := FuncType(fn)
   105  	if err != nil {
   106  		return err
   107  	}
   108  
   109  	args, err := getFuncArgumentsType(funcTl)
   110  	if err != nil {
   111  		return err
   112  	}
   113  
   114  	for _, cond := range argRules {
   115  		if err = cond(args); err != nil {
   116  			return err
   117  		}
   118  	}
   119  
   120  	rets, err := getFuncReturnsType(funcTl)
   121  	if err != nil {
   122  		return err
   123  	}
   124  
   125  	for _, cond := range returnRules {
   126  		if err = cond(rets); err != nil {
   127  			return err
   128  		}
   129  	}
   130  
   131  	return nil
   132  }
   133  
   134  // CallFuncType attempts to call a giving function with provided arguments
   135  // assuming all of them match the ff:
   136  // 1. Exected number of arguments
   137  // 2. Expected type of arguments
   138  // It returns an error if not possible or returns the response for calling said
   139  // function or if type is not a function.
   140  // Note that the function call follows some rules:
   141  // 1. If the function expects no arguments and some is supplied,
   142  // they will be ignored.
   143  func CallFunc(fn interface{}, args ...interface{}) (res []interface{}, err error) {
   144  	var funcTl reflect.Type
   145  	var funcVl reflect.Value
   146  
   147  	funcTl, err = FuncType(fn)
   148  	if err != nil {
   149  		return
   150  	}
   151  
   152  	res = make([]interface{}, funcTl.NumOut())
   153  
   154  	funcVl, err = FuncValue(fn)
   155  	if err != nil {
   156  		return
   157  	}
   158  
   159  	if funcTl.NumIn() == 0 {
   160  		for index, item := range funcVl.Call(nil) {
   161  			res[index] = item.Interface()
   162  		}
   163  		return
   164  	}
   165  
   166  	argLen := len(args)
   167  	argValues := make([]reflect.Value, len(args))
   168  	for index, arg := range args {
   169  		argValues[index] = reflect.ValueOf(arg)
   170  	}
   171  
   172  	if funcTl.NumIn() == 1 {
   173  		if funcTl.IsVariadic() && len(args) == 0 {
   174  			for index, item := range funcVl.CallSlice(nil) {
   175  				res[index] = item.Interface()
   176  			}
   177  			return
   178  		}
   179  
   180  		for index, item := range funcVl.Call(argValues) {
   181  			res[index] = item.Interface()
   182  		}
   183  		return
   184  	}
   185  
   186  	// if argument and expected are not equal in length
   187  	// and the last is variadic, we can treat has providing
   188  	// a nil towards that part.
   189  	if argLen != funcTl.NumIn() {
   190  		last := funcTl.NumIn() - 1
   191  		argItem := funcTl.In(last)
   192  		if argItem.IsVariadic() && argLen == last {
   193  			for index, item := range funcVl.Call(argValues) {
   194  				res[index] = item.Interface()
   195  			}
   196  			return
   197  		} else {
   198  			err = errors.New("argument length does not match number of wanted")
   199  			return
   200  		}
   201  	}
   202  
   203  	for i := 0; i < funcTl.NumIn(); i++ {
   204  		item := funcTl.In(i)
   205  		inarg := argValues[i]
   206  
   207  		canSet, mustConvert := CanSetFor(item, inarg)
   208  		if !canSet {
   209  			err = fmt.Errorf("argument at %d does not match function argument at postion", i)
   210  			return
   211  		}
   212  
   213  		if mustConvert {
   214  			converted, err2 := Convert(item, inarg)
   215  			if err2 != nil {
   216  				err = err2
   217  				return
   218  			}
   219  
   220  			argValues[i] = converted
   221  		}
   222  	}
   223  
   224  	if funcTl.IsVariadic() {
   225  		for index, item := range funcVl.CallSlice(argValues) {
   226  			res[index] = item.Interface()
   227  		}
   228  		return
   229  	}
   230  
   231  	for index, item := range funcVl.Call(argValues) {
   232  		res[index] = item.Interface()
   233  	}
   234  
   235  	return
   236  }
   237  
   238  // FuncValue return the Function reflect.Value of the provided function else
   239  // returns a non-nil error.
   240  func FuncValue(elem interface{}) (reflect.Value, error) {
   241  	tl := reflect.ValueOf(elem)
   242  
   243  	if tl.Kind() == reflect.Ptr {
   244  		tl = tl.Elem()
   245  	}
   246  
   247  	if tl.Kind() != reflect.Func {
   248  		return reflect.Value{}, ErrNotFunction
   249  	}
   250  	return tl, nil
   251  }
   252  
   253  // FuncType return the Function reflect.Type of the provided function else
   254  // returns a non-nil error.
   255  func FuncType(elem interface{}) (reflect.Type, error) {
   256  	tl := reflect.TypeOf(elem)
   257  
   258  	if tl.Kind() == reflect.Ptr {
   259  		tl = tl.Elem()
   260  	}
   261  
   262  	if tl.Kind() != reflect.Func {
   263  		return nil, ErrNotFunction
   264  	}
   265  
   266  	return tl, nil
   267  }
   268  
   269  // MatchElement attempts to validate that both element are equal in type and value.
   270  func MatchElement(me interface{}, other interface{}, allowFunctions bool) bool {
   271  	meType := reflect.TypeOf(me)
   272  	otherType := reflect.TypeOf(other)
   273  
   274  	// if one is pointer, then both must be.
   275  	if meType.Kind() == reflect.Ptr && otherType.Kind() != reflect.Ptr {
   276  		return false
   277  	}
   278  
   279  	// if one is pointer, then both must be.
   280  	if otherType.Kind() == reflect.Ptr && meType.Kind() != reflect.Ptr {
   281  		return false
   282  	}
   283  
   284  	if meType.Kind() == reflect.Ptr {
   285  		meType = meType.Elem()
   286  	}
   287  
   288  	if otherType.Kind() == reflect.Ptr {
   289  		otherType = otherType.Elem()
   290  	}
   291  
   292  	if meType.Kind() == reflect.Func {
   293  		if allowFunctions {
   294  			return MatchFunction(me, other)
   295  		}
   296  
   297  		return false
   298  	}
   299  
   300  	if otherType.AssignableTo(meType) {
   301  		return true
   302  	}
   303  
   304  	return true
   305  }
   306  
   307  // MatchFunction attempts to validate if giving types are functions and
   308  // exactly match in arguments and returns.
   309  func MatchFunction(me interface{}, other interface{}) bool {
   310  	meType := reflect.TypeOf(me)
   311  	otherType := reflect.TypeOf(other)
   312  
   313  	// if one is pointer, then both must be.
   314  	if meType.Kind() == reflect.Ptr && otherType.Kind() != reflect.Ptr {
   315  		return false
   316  	}
   317  
   318  	// if one is pointer, then both must be.
   319  	if otherType.Kind() == reflect.Ptr && meType.Kind() != reflect.Ptr {
   320  		return false
   321  	}
   322  
   323  	if meType.Kind() == reflect.Ptr {
   324  		meType = meType.Elem()
   325  	}
   326  
   327  	if otherType.Kind() == reflect.Ptr {
   328  		otherType = otherType.Elem()
   329  	}
   330  
   331  	if meType.Kind() != reflect.Func {
   332  		return false
   333  	}
   334  
   335  	if otherType.Kind() != reflect.Func {
   336  		return false
   337  	}
   338  
   339  	if otherType.NumIn() != meType.NumIn() {
   340  		return false
   341  	}
   342  
   343  	if otherType.NumOut() != meType.NumOut() {
   344  		return false
   345  	}
   346  
   347  	for i := 0; i < meType.NumIn(); i++ {
   348  		item := meType.In(i)
   349  		otherItem := otherType.In(i)
   350  		if item.Kind() != reflect.Func && !MatchElement(item, otherItem, true) {
   351  			return false
   352  		}
   353  
   354  		if item.Kind() == reflect.Func && !MatchFunction(item, otherItem) {
   355  			return false
   356  		}
   357  	}
   358  
   359  	for i := 0; i < meType.NumOut(); i++ {
   360  		item := meType.Out(i)
   361  		otherItem := otherType.Out(i)
   362  		if item.Kind() != reflect.Func && !MatchElement(item, otherItem, true) {
   363  			return false
   364  		}
   365  
   366  		if item.Kind() == reflect.Func && !MatchFunction(item, otherItem) {
   367  			return false
   368  		}
   369  	}
   370  
   371  	return true
   372  }
   373  
   374  // TypeAndFields returns the type of the giving element and a slice of
   375  // all composed types.
   376  func TypeAndFields(elem interface{}) (reflect.Type, []reflect.Type, error) {
   377  	tl := reflect.ValueOf(elem)
   378  
   379  	if tl.Kind() == reflect.Ptr {
   380  		tl = tl.Elem()
   381  	}
   382  
   383  	if tl.Kind() != reflect.Struct {
   384  		return nil, nil, ErrNotStruct
   385  	}
   386  
   387  	var embeded []reflect.Type
   388  
   389  	for ind := 0; ind < tl.NumField(); ind++ {
   390  		item := tl.Field(ind).Type()
   391  		embeded = append(embeded, item)
   392  	}
   393  
   394  	return tl.Type(), embeded, nil
   395  }
   396  
   397  var internalTypes = []string{
   398  	"string", "int", "int64", "int32", "float32",
   399  	"float64", "bool", "char",
   400  	"rune", "byte",
   401  }
   402  
   403  // FieldType defines a struct which holds details the name and package which
   404  // a giving field belongs to.
   405  type FieldType struct {
   406  	TypeName string `json:"field_type"`
   407  	Pkg      string `json:"ngpkg"`
   408  }
   409  
   410  // ExternalTypeNames returns the name and field names of the provided
   411  // elem which must be a struct, excluding all internal types.
   412  func ExternalTypeNames(elem interface{}) (FieldType, []FieldType, error) {
   413  	tl := reflect.TypeOf(elem)
   414  
   415  	if tl.Kind() == reflect.Ptr {
   416  		tl = tl.Elem()
   417  	}
   418  
   419  	if tl.Kind() == reflect.Interface {
   420  		tl = tl.Elem()
   421  	}
   422  
   423  	if tl.Kind() != reflect.Struct {
   424  		return FieldType{}, nil, ErrNotStruct
   425  	}
   426  
   427  	var item FieldType
   428  	item.TypeName = tl.Name()
   429  	item.Pkg = tl.PkgPath()
   430  
   431  	var embeded []FieldType
   432  
   433  	{
   434  	fieldLoop:
   435  		for ind := 0; ind < tl.NumField(); ind++ {
   436  			item := tl.Field(ind).Type
   437  
   438  			for _, except := range internalTypes {
   439  				if except == item.Name() {
   440  					continue fieldLoop
   441  				}
   442  			}
   443  
   444  			if item.Name() == "" {
   445  				if item.Kind() == reflect.Slice || item.Kind() == reflect.Array || item.Kind() == reflect.Interface {
   446  					for _, except := range internalTypes {
   447  						if except == item.Elem().Name() {
   448  							continue fieldLoop
   449  						}
   450  					}
   451  
   452  					embeded = append(embeded, FieldType{
   453  						TypeName: item.Elem().Name(),
   454  						Pkg:      item.Elem().PkgPath(),
   455  					})
   456  				}
   457  
   458  				continue
   459  			}
   460  
   461  			embeded = append(embeded, FieldType{
   462  				TypeName: item.Name(),
   463  				Pkg:      item.PkgPath(),
   464  			})
   465  		}
   466  	}
   467  
   468  	return item, embeded, nil
   469  }
   470  
   471  // HasArgumentSize return true/false to indicate if the function type has the
   472  // size of arguments. It will return false if the interface is not a function
   473  // type.
   474  func HasArgumentSize(elem interface{}, len int) bool {
   475  	tl := reflect.TypeOf(elem)
   476  
   477  	if tl.Kind() == reflect.Ptr {
   478  		tl = tl.Elem()
   479  	}
   480  
   481  	if tl.Kind() != reflect.Func {
   482  		return false
   483  	}
   484  
   485  	if tl.NumIn() != len {
   486  		return false
   487  	}
   488  
   489  	return true
   490  }
   491  
   492  // GetFuncReturnsType returns the returns type of function which should be
   493  // a function type,else returns a non-nil error.
   494  func GetFuncReturnsType(elem interface{}) ([]reflect.Type, error) {
   495  	tl := reflect.TypeOf(elem)
   496  	if tl.Kind() == reflect.Ptr {
   497  		tl = tl.Elem()
   498  	}
   499  
   500  	if tl.Kind() != reflect.Func {
   501  		return nil, ErrNotFunction
   502  	}
   503  
   504  	return getFuncReturnsType(tl)
   505  }
   506  
   507  func getFuncReturnsType(tl reflect.Type) ([]reflect.Type, error) {
   508  	totalFields := tl.NumOut()
   509  	if totalFields == 0 {
   510  		return nil, nil
   511  	}
   512  
   513  	input := make([]reflect.Type, 0, totalFields)
   514  	for i := 0; i < totalFields; i++ {
   515  		indElem := tl.Out(i)
   516  		input = append(input, indElem)
   517  	}
   518  	return input, nil
   519  }
   520  
   521  // GetFuncArgumentsType returns the arguments type of function which should be
   522  // a function type,else returns a non-nil error.
   523  func GetFuncArgumentsType(elem interface{}) ([]reflect.Type, error) {
   524  	tl := reflect.TypeOf(elem)
   525  	if tl.Kind() == reflect.Ptr {
   526  		tl = tl.Elem()
   527  	}
   528  
   529  	if tl.Kind() != reflect.Func {
   530  		return nil, ErrNotFunction
   531  	}
   532  
   533  	return getFuncArgumentsType(tl)
   534  }
   535  
   536  func getFuncArgumentsType(tl reflect.Type) ([]reflect.Type, error) {
   537  	totalFields := tl.NumIn()
   538  	if totalFields == 0 {
   539  		return nil, nil
   540  	}
   541  
   542  	input := make([]reflect.Type, 0, totalFields)
   543  	for i := 0; i < totalFields; i++ {
   544  		indElem := tl.In(i)
   545  		input = append(input, indElem)
   546  	}
   547  	return input, nil
   548  }
   549  
   550  // MatchFuncArgumentTypeWithValues validates specific values matches the elems
   551  // function arguments.
   552  func MatchFuncArgumentTypeWithValues(elem interface{}, vals []reflect.Value) int {
   553  	ma, err := GetFuncArgumentsType(elem)
   554  	if err != nil {
   555  		return -1
   556  	}
   557  
   558  	if len(ma) != len(vals) {
   559  		return -1
   560  	}
   561  
   562  	for index, item := range ma {
   563  		val := vals[index]
   564  
   565  		if ok, _ := CanSetFor(item, val); !ok {
   566  			return index
   567  		}
   568  	}
   569  
   570  	return -1
   571  }
   572  
   573  // StrictCanSetForType checks if a val reflect.Type can be used for the target type.
   574  // It returns true/false if value matches the expected type and another true/false
   575  // if the value can be converted to the expected type.
   576  // Difference between this version and the other CanSet is that, it returns
   577  // only true/false for the Assignability of the types and not based on the Assignability
   578  // and convertibility.
   579  func StrictCanSetForType(target, val reflect.Type) (canSet bool, mustConvert bool) {
   580  	if val.AssignableTo(target) {
   581  		canSet = true
   582  	}
   583  
   584  	if val.ConvertibleTo(target) {
   585  		mustConvert = true
   586  	}
   587  
   588  	return
   589  }
   590  
   591  // IsStrictlyAssignableType returns true/false if the element(elem) is of
   592  // for ref type.
   593  func IsStrictlyAssignableType(ref reflect.Type, elem reflect.Type) bool {
   594  	canset, _ := CanSetForType(ref, elem)
   595  	return canset
   596  }
   597  
   598  // IsStrictlyAssignable returns true/false if the element(elem) can be used for
   599  // for ref type.
   600  func IsStrictlyAssignable(ref reflect.Type, elem reflect.Value) bool {
   601  	canset, _ := CanSetFor(ref, elem)
   602  	return canset
   603  }
   604  
   605  // IsSettableType returns true/false if the element(elem) can be used for
   606  // for ref type.
   607  func IsSettableType(ref reflect.Type, elem reflect.Type) bool {
   608  	canset, canConvert := CanSetForType(ref, elem)
   609  	return canset || canConvert
   610  }
   611  
   612  // IsSettable returns true/false if the element(elem) can be used for
   613  // for ref type.
   614  func IsSettable(ref reflect.Type, elem reflect.Value) bool {
   615  	canset, canConvert := CanSetFor(ref, elem)
   616  	return canset || canConvert
   617  }
   618  
   619  // CanSetForType checks if a val reflect.Type can be used for the target type.
   620  // It returns true bool, where the first returns if the value can be used and if
   621  // it must be converted into the type first.
   622  func CanSetForType(target, val reflect.Type) (canSet bool, mustConvert bool) {
   623  	if val.AssignableTo(target) {
   624  		canSet = true
   625  		return
   626  	}
   627  
   628  	if val.ConvertibleTo(target) {
   629  		canSet = true
   630  		mustConvert = true
   631  		return
   632  	}
   633  
   634  	return
   635  }
   636  
   637  // CanSetFor checks if the giving val can be set in the place of the target type.
   638  // It returns true bool, where the first returns if the value can be used and if
   639  // it must be converted into the type first.
   640  func CanSetFor(target reflect.Type, val reflect.Value) (canSet bool, mustConvert bool) {
   641  	valType := val.Type()
   642  
   643  	if valType.AssignableTo(target) {
   644  		canSet = true
   645  		return
   646  	}
   647  
   648  	if valType.ConvertibleTo(target) {
   649  		canSet = true
   650  		mustConvert = true
   651  		return
   652  	}
   653  
   654  	return
   655  }
   656  
   657  // Convert takes a val and converts it into the target type provided if possible.
   658  func Convert(target reflect.Type, val reflect.Value) (reflect.Value, error) {
   659  	valType := val.Type()
   660  
   661  	if !valType.ConvertibleTo(target) {
   662  		return reflect.Value{}, errors.New("Can not convert type")
   663  	}
   664  
   665  	return val.Convert(target), nil
   666  }
   667  
   668  // MakeValueFor makes a new reflect.Value for the reflect.Type.
   669  func MakeValueFor(t reflect.Type) reflect.Value {
   670  	mtl := reflect.New(t)
   671  
   672  	if t.Kind() != reflect.Ptr && mtl.Kind() == reflect.Ptr {
   673  		mtl = mtl.Elem()
   674  	}
   675  
   676  	return mtl
   677  }
   678  
   679  // MakeArgumentsValues takes a list of reflect.Types and returns a new version of
   680  // those types, ensuring to dereference if it receives a pointer reflect.Type.
   681  func MakeArgumentsValues(args []reflect.Type) []reflect.Value {
   682  	var inputs []reflect.Value
   683  
   684  	for _, tl := range args {
   685  		inputs = append(inputs, MakeValueFor(tl))
   686  	}
   687  
   688  	return inputs
   689  }
   690  
   691  // InterfaceFromValues returns a list of interfaces representing the concrete
   692  // values within the lists of reflect.Value types.
   693  func InterfaceFromValues(vals []reflect.Value) []interface{} {
   694  	var data []interface{}
   695  
   696  	for _, val := range vals {
   697  		if val.Kind() == reflect.Ptr {
   698  			val = val.Elem()
   699  		}
   700  
   701  		data = append(data, val.Interface())
   702  	}
   703  
   704  	return data
   705  }
   706  
   707  //==============================================================================
   708  
   709  // ErrNotStruct is returned when the reflect type is not a struct.
   710  var ErrNotStruct = errors.New("Not a struct type")
   711  
   712  // Field defines a specific tag field with its details from a giving struct.
   713  type Field struct {
   714  	Index       int
   715  	Name        string
   716  	Tag         string
   717  	NameLC      string
   718  	TypeName    string
   719  	Type        reflect.Type
   720  	Value       reflect.Value
   721  	IsSlice     bool
   722  	IsArray     bool
   723  	IsFunc      bool
   724  	IsPointer   bool
   725  	IsInterface bool
   726  	IsMap       bool
   727  	IsChan      bool
   728  	IsStruct    bool
   729  }
   730  
   731  // Fields defines a lists of Field instances.
   732  type Fields []Field
   733  
   734  // GetTagFields retrieves all fields of the giving elements with the giving tag
   735  // type.
   736  func GetTagFields(elem interface{}, tag string, allowNaturalNames bool) (Fields, error) {
   737  	if !IsStruct(elem) {
   738  		return nil, ErrNotStruct
   739  	}
   740  
   741  	tl := reflect.TypeOf(elem)
   742  	tlVal := reflect.ValueOf(elem)
   743  
   744  	if tl.Kind() == reflect.Ptr {
   745  		tl = tl.Elem()
   746  	}
   747  
   748  	if tlVal.Kind() == reflect.Ptr {
   749  		if tlVal.IsNil() {
   750  			return nil, errors.New("invalid value: must be non-nil struct")
   751  		}
   752  
   753  		tlVal = tlVal.Elem()
   754  	}
   755  
   756  	var fields Fields
   757  
   758  	for i := 0; i < tl.NumField(); i++ {
   759  		field := tl.Field(i)
   760  
   761  		// Get the specified tag from this field if it exists.
   762  		tagVal := strings.TrimSpace(field.Tag.Get(tag))
   763  
   764  		// If its a - item in the tag then skip or if its an empty string.
   765  		if tagVal == "-" {
   766  			continue
   767  		}
   768  
   769  		if !allowNaturalNames && tagVal == "" {
   770  			continue
   771  		}
   772  
   773  		if tagVal == "" {
   774  			tagVal = strings.ToLower(field.Name)
   775  		}
   776  
   777  		fields = append(fields, Field{
   778  			Index:       i,
   779  			Tag:         tagVal,
   780  			Name:        field.Name,
   781  			Type:        field.Type,
   782  			Value:       tlVal.Field(i),
   783  			TypeName:    field.Type.Name(),
   784  			NameLC:      strings.ToLower(field.Name),
   785  			IsMap:       field.Type.Kind() == reflect.Map,
   786  			IsFunc:      field.Type.Kind() == reflect.Func,
   787  			IsChan:      field.Type.Kind() == reflect.Chan,
   788  			IsSlice:     field.Type.Kind() == reflect.Slice,
   789  			IsArray:     field.Type.Kind() == reflect.Array,
   790  			IsStruct:    field.Type.Kind() == reflect.Struct,
   791  			IsInterface: field.Type.Kind() == reflect.Interface,
   792  			IsPointer:   field.Type.Kind() == reflect.UnsafePointer,
   793  		})
   794  	}
   795  
   796  	return fields, nil
   797  }
   798  
   799  // GetFieldByTagAndValue returns a giving struct field which has giving tag and value pair.
   800  func GetFieldByTagAndValue(elem interface{}, tag string, value string) (reflect.StructField, error) {
   801  	if !IsStruct(elem) {
   802  		return reflect.StructField{}, ErrNotStruct
   803  	}
   804  
   805  	tl := reflect.TypeOf(elem)
   806  	if tl.Kind() == reflect.Ptr {
   807  		tl = tl.Elem()
   808  	}
   809  
   810  	for i := 0; i < tl.NumField(); i++ {
   811  		field := tl.Field(i)
   812  		if field.Tag.Get(tag) == value {
   813  			return field, nil
   814  		}
   815  	}
   816  
   817  	return reflect.StructField{}, ErrNoFieldWithTagFound
   818  }
   819  
   820  // GetFields retrieves all fields of the giving elements with the giving tag
   821  // type.
   822  func GetFields(elem interface{}) (Fields, error) {
   823  	if !IsStruct(elem) {
   824  		return nil, ErrNotStruct
   825  	}
   826  
   827  	tl := reflect.TypeOf(elem)
   828  	tlVal := reflect.ValueOf(elem)
   829  
   830  	if tl.Kind() == reflect.Ptr {
   831  		tl = tl.Elem()
   832  	}
   833  
   834  	if tlVal.Kind() == reflect.Ptr {
   835  		if tlVal.IsNil() {
   836  			return nil, errors.New("invalid value: must be non-nil struct")
   837  		}
   838  
   839  		tlVal = tlVal.Elem()
   840  	}
   841  
   842  	var fields Fields
   843  
   844  	for i := 0; i < tl.NumField(); i++ {
   845  		field := tl.Field(i)
   846  		fieldVal := Field{
   847  			Index:       i,
   848  			Name:        field.Name,
   849  			Type:        field.Type,
   850  			Value:       tlVal.Field(i),
   851  			TypeName:    field.Type.Name(),
   852  			NameLC:      strings.ToLower(field.Name),
   853  			IsMap:       field.Type.Kind() == reflect.Map,
   854  			IsFunc:      field.Type.Kind() == reflect.Func,
   855  			IsChan:      field.Type.Kind() == reflect.Chan,
   856  			IsSlice:     field.Type.Kind() == reflect.Slice,
   857  			IsArray:     field.Type.Kind() == reflect.Array,
   858  			IsStruct:    field.Type.Kind() == reflect.Struct,
   859  			IsInterface: field.Type.Kind() == reflect.Interface,
   860  			IsPointer:   field.Type.Kind() == reflect.UnsafePointer,
   861  		}
   862  
   863  		fields = append(fields, fieldVal)
   864  	}
   865  
   866  	return fields, nil
   867  }
   868  
   869  // ToMap returns a map of the giving values from a struct using a provided
   870  // tag to capture the needed values, it extracts those tags values out into
   871  // a map. It returns an error if the element is not a struct.
   872  func ToMap(tag string, elem interface{}, allowNaturalNames bool) (map[string]interface{}, error) {
   873  	// Collect the fields that match the giving tag.
   874  	fields, err := GetTagFields(elem, tag, allowNaturalNames)
   875  	if err != nil {
   876  		return nil, err
   877  	}
   878  
   879  	// If there exists no field matching the tag skip.
   880  	if len(fields) == 0 {
   881  		return nil, errors.New("No Tag Matches")
   882  	}
   883  
   884  	data := make(map[string]interface{})
   885  
   886  	// Loop through  the fields and set the appropriate value as needed.
   887  	for _, field := range fields {
   888  		if !field.Value.CanInterface() {
   889  			continue
   890  		}
   891  
   892  		itemType := field.Type
   893  		item := field.Value.Interface()
   894  
   895  		switch itemType.Kind() {
   896  		case reflect.Struct:
   897  			if subItem, err := ToMap(tag, item, allowNaturalNames); err == nil {
   898  				data[field.Tag] = subItem
   899  			} else {
   900  				data[field.Tag] = item
   901  			}
   902  
   903  		default:
   904  			data[field.Tag] = item
   905  		}
   906  	}
   907  
   908  	return data, nil
   909  }
   910  
   911  // MergeMap merges the key names of the provided map into the appropriate field
   912  // place where the element has the provided tag.
   913  func MergeMap(tag string, elem interface{}, values map[string]interface{}, allowAll bool) error {
   914  
   915  	// Collect the fields that match the giving tag.
   916  	fields, err := GetTagFields(elem, tag, allowAll)
   917  	if err != nil {
   918  		return err
   919  	}
   920  
   921  	// If there exists no field matching the tag skip.
   922  	if len(fields) == 0 {
   923  		return nil
   924  	}
   925  
   926  	tl := reflect.ValueOf(elem)
   927  
   928  	if tl.Kind() == reflect.Ptr {
   929  		tl = tl.Elem()
   930  	}
   931  
   932  	// Loop through  the fields and set the appropriate value as needed.
   933  	for _, field := range fields {
   934  
   935  		item := values[field.Tag]
   936  
   937  		if item == nil {
   938  			continue
   939  		}
   940  
   941  		fl := tl.Field(field.Index)
   942  
   943  		// If we can't set this field, then skip.
   944  		if !fl.CanSet() {
   945  			continue
   946  		}
   947  
   948  		fl.Set(reflect.ValueOf(item))
   949  	}
   950  
   951  	return nil
   952  }
   953  
   954  // IsStruct returns true/false if the elem provided is a type of struct.
   955  func IsStruct(elem interface{}) bool {
   956  	mc := reflect.TypeOf(elem)
   957  
   958  	if mc.Kind() == reflect.Ptr {
   959  		mc = mc.Elem()
   960  	}
   961  
   962  	if mc.Kind() != reflect.Struct {
   963  		return false
   964  	}
   965  
   966  	return true
   967  }
   968  
   969  func IsTypePtr(me interface{}, other interface{}) bool {
   970  	var mc = reflect.TypeOf(me)
   971  	var oc = reflect.TypeOf(other)
   972  	return mc == oc
   973  }
   974  
   975  func IsSameName(me interface{}, other interface{}) bool {
   976  	return TypeName(me) == TypeName(other)
   977  }
   978  
   979  func IsSameTypeName(me interface{}, other interface{}) bool {
   980  	var mc = reflect.TypeOf(me)
   981  	var oc = reflect.TypeOf(other)
   982  	return nameOfType(mc) == nameOfType(oc)
   983  }
   984  
   985  func IsType(me interface{}, other interface{}) bool {
   986  	var mc = reflect.TypeOf(me)
   987  	if mc.Kind() == reflect.Ptr {
   988  		mc = mc.Elem()
   989  	}
   990  
   991  	var oc = reflect.TypeOf(other)
   992  	if oc.Kind() == reflect.Ptr {
   993  		oc = oc.Elem()
   994  	}
   995  
   996  	return mc == oc
   997  }
   998  
   999  // MakeNew returns a new version of the giving type, returning a nonpointer type.
  1000  // If the type is not a struct then an error is returned.
  1001  func MakeNew(elem interface{}) (interface{}, error) {
  1002  	mc := reflect.TypeOf(elem)
  1003  
  1004  	if mc.Kind() != reflect.Struct {
  1005  		return nil, ErrNotStruct
  1006  	}
  1007  
  1008  	return reflect.New(mc).Interface(), nil
  1009  }