gitlab.com/evatix-go/core@v1.3.55/coredata/coredynamic/reflectGetUsingReflectValue.go (about)

     1  package coredynamic
     2  
     3  import (
     4  	"reflect"
     5  	"unsafe"
     6  
     7  	"gitlab.com/evatix-go/core/constants"
     8  	"gitlab.com/evatix-go/core/errcore"
     9  	"gitlab.com/evatix-go/core/internal/reflectinternal"
    10  )
    11  
    12  type reflectGetUsingReflectValue struct{}
    13  
    14  // PublicValuesMapStruct
    15  //
    16  //  returns structs fields map[string]Interface{}
    17  //  map[string:fieldName]Interface{}:PublicValue
    18  //
    19  //  Only public values will be collected into map values
    20  func (it reflectGetUsingReflectValue) PublicValuesMapStruct(structValue reflect.Value) (
    21  	map[string]interface{}, error,
    22  ) {
    23  	if structValue.Kind() != reflect.Struct {
    24  		return nil, errcore.Expected.ReflectButFound(
    25  			reflect.Struct,
    26  			structValue.Kind())
    27  	}
    28  
    29  	structType := structValue.Type()
    30  	structNumFields := structType.NumField()
    31  	fieldToValueMap := make(map[string]interface{}, structNumFields)
    32  
    33  	for i := 0; i < structNumFields; i++ {
    34  		fieldStruct := structType.Field(i)
    35  
    36  		// ignore unexported fields
    37  		if fieldStruct.PkgPath != "" {
    38  			continue
    39  		}
    40  
    41  		field := structValue.Field(i)
    42  		fieldToValueMap[fieldStruct.Name] = field.Interface()
    43  	}
    44  
    45  	return fieldToValueMap, nil
    46  }
    47  
    48  // FieldNameWithTypeMap
    49  //
    50  //  returns structs fields map[string]Interface{}
    51  //  map[string:fieldName]reflect.Type:fieldType
    52  //
    53  //  Only public values will be collected into map values
    54  func (it reflectGetUsingReflectValue) FieldNameWithTypeMap(
    55  	rv reflect.Value,
    56  ) map[string]reflect.Type {
    57  	structValue := rv
    58  	structValueKind := structValue.Kind()
    59  
    60  	for structValueKind == reflect.Ptr || structValueKind == reflect.Interface {
    61  		// mutating dangerous code
    62  		structValue = structValue.Elem()
    63  		structValueKind = structValue.Kind()
    64  	}
    65  
    66  	if !structValue.IsValid() || structValueKind != reflect.Struct {
    67  		return nil
    68  	}
    69  
    70  	structType := structValue.Type()
    71  	fieldsLength := structType.NumField()
    72  	fieldsHashset :=
    73  		make(
    74  			map[string]reflect.Type,
    75  			fieldsLength)
    76  
    77  	var name string
    78  
    79  	for i := 0; i < fieldsLength; i++ {
    80  		field := structType.Field(i)
    81  		name = field.Name
    82  		fieldsHashset[name] = field.Type
    83  	}
    84  
    85  	return fieldsHashset
    86  }
    87  
    88  // FieldNameWithValuesMap
    89  //
    90  //  returns structs all fields (public, private) map[string]Interface{}
    91  //  map[string:fieldName]interface{}:fieldValuePublicOrPrivate
    92  //
    93  //  unlike PublicValuesMapStruct to map it collects
    94  //  all fields with values including the private ones.
    95  //
    96  // However, this one will be slower in performance than PublicValuesMapStruct.
    97  func (it reflectGetUsingReflectValue) FieldNameWithValuesMap(
    98  	structValue reflect.Value,
    99  ) (
   100  	map[string]interface{}, error,
   101  ) {
   102  	structType := structValue.Type()
   103  	structNumFields := structType.NumField()
   104  	fieldToValueMap := make(map[string]interface{}, structNumFields)
   105  
   106  	// structValue is not addressable, create a temporary copy
   107  	if !structValue.CanAddr() {
   108  		newType := reflect.New(structType).Elem()
   109  		newType.Set(structValue)
   110  		// structValue is now addressable
   111  		structValue = newType
   112  	}
   113  
   114  	for i := 0; i < structNumFields; i++ {
   115  		fieldType := structType.Field(i)
   116  		fieldValue := structValue.Field(i)
   117  
   118  		if fieldType.PkgPath != "" {
   119  			unexportedField := reflect.NewAt(
   120  				fieldType.Type,
   121  				unsafe.Pointer(fieldValue.UnsafeAddr())).Elem()
   122  			fieldToValueMap[fieldType.Name] = unexportedField.Interface()
   123  		} else {
   124  			fieldToValueMap[fieldType.Name] = fieldValue.Interface()
   125  		}
   126  	}
   127  
   128  	return fieldToValueMap, nil
   129  }
   130  
   131  // FieldNamesMap
   132  //
   133  //  returns structs fields map[string]bool
   134  //  map[string:fieldName]bool
   135  func (it reflectGetUsingReflectValue) FieldNamesMap(
   136  	rv reflect.Value,
   137  ) (map[string]bool, error) {
   138  	structValue := rv
   139  	structValueKind := structValue.Kind()
   140  
   141  	for structValueKind == reflect.Ptr || structValueKind == reflect.Interface {
   142  		// mutating dangerous code
   143  		structValue = structValue.Elem()
   144  		structValueKind = structValue.Kind()
   145  	}
   146  
   147  	if !structValue.IsValid() || structValueKind != reflect.Struct {
   148  		return map[string]bool{},
   149  			errcore.Expected.ReflectButFound(
   150  				reflect.Struct, structValueKind)
   151  	}
   152  
   153  	structType := structValue.Type()
   154  	fieldsLength := structType.NumField()
   155  	fieldsMap := make(
   156  		map[string]bool,
   157  		fieldsLength+1)
   158  
   159  	for i := 0; i < fieldsLength; i++ {
   160  		name := structType.Field(i).Name
   161  		fieldsMap[name] = true
   162  	}
   163  
   164  	return fieldsMap, nil
   165  }
   166  
   167  // StructFieldsMap
   168  //
   169  //  returns structs all fields (public, private) map[string]reflect.StructField
   170  //  map[string:fieldName]reflect.StructField:StructField
   171  func (it reflectGetUsingReflectValue) StructFieldsMap(
   172  	rv reflect.Value,
   173  ) map[string]reflect.StructField {
   174  	structValue := rv
   175  	structValueKind := structValue.Kind()
   176  
   177  	for structValueKind == reflect.Ptr || structValueKind == reflect.Interface {
   178  		// mutating dangerous code
   179  		structValue = structValue.Elem()
   180  		structValueKind = structValue.Kind()
   181  	}
   182  
   183  	if !structValue.IsValid() || structValueKind != reflect.Struct {
   184  		return nil
   185  	}
   186  
   187  	structType := structValue.Type()
   188  	fieldsLength := structType.NumField()
   189  	fieldsHashset :=
   190  		make(
   191  			map[string]reflect.StructField,
   192  			fieldsLength)
   193  
   194  	var name string
   195  
   196  	for i := 0; i < fieldsLength; i++ {
   197  		field := structType.Field(i)
   198  		name = field.Name
   199  		fieldsHashset[name] = field
   200  	}
   201  
   202  	return fieldsHashset
   203  }
   204  
   205  // NullFieldsMap
   206  //
   207  //  returns structs all fields (public, private) map[string]bool
   208  //  null fields map only
   209  func (it reflectGetUsingReflectValue) NullFieldsMap(
   210  	level int,
   211  	reflectVal reflect.Value,
   212  ) map[string]bool {
   213  	structType := reflectVal.Type()
   214  	structValueKind := reflectVal.Kind()
   215  	hasLevel := level > constants.InvalidIndex
   216  	structValue := reflectVal
   217  
   218  	// reducing ****ToValue to ToValue
   219  	for structValueKind == reflect.Ptr || structValueKind == reflect.Interface {
   220  		// mutating dangerous code
   221  		structValue = structValue.Elem()
   222  		structValueKind = structValue.Kind()
   223  
   224  		level--
   225  		if hasLevel && level <= 0 {
   226  			break
   227  		}
   228  	}
   229  
   230  	if !structValue.IsValid() || structValueKind != reflect.Struct {
   231  		return map[string]bool{}
   232  	}
   233  
   234  	structNumFields := structType.NumField()
   235  	hashset := make(
   236  		map[string]bool,
   237  		structNumFields+1)
   238  	var fieldValue reflect.Value
   239  	var fieldType reflect.StructField
   240  
   241  	for i := 0; i < structNumFields; i++ {
   242  		fieldValue = structValue.Field(i)
   243  
   244  		if reflectinternal.IsNullUsingReflectValue(fieldValue) {
   245  			fieldType = structType.Field(i)
   246  			hashset[fieldType.Name] = true
   247  		}
   248  	}
   249  
   250  	return hashset
   251  }
   252  
   253  // NullOrZeroFieldsMap
   254  //
   255  //  returns structs all fields (public, private) map[string]bool
   256  //  null or zero fields map only
   257  func (it reflectGetUsingReflectValue) NullOrZeroFieldsMap(
   258  	level int,
   259  	reflectVal reflect.Value,
   260  ) map[string]bool {
   261  	structType := reflectVal.Type()
   262  	structValueKind := reflectVal.Kind()
   263  	hasLevel := level > constants.InvalidIndex
   264  	structValue := reflectVal
   265  
   266  	// reducing ****ToValue to ToValue
   267  	for structValueKind == reflect.Ptr || structValueKind == reflect.Interface {
   268  		// mutating dangerous code
   269  		structValue = structValue.Elem()
   270  		structValueKind = structValue.Kind()
   271  
   272  		level--
   273  		if hasLevel && level <= 0 {
   274  			break
   275  		}
   276  	}
   277  
   278  	if !structValue.IsValid() || structValueKind != reflect.Struct {
   279  		return map[string]bool{}
   280  	}
   281  
   282  	structNumFields := structType.NumField()
   283  	hashset := make(
   284  		map[string]bool,
   285  		structNumFields+1)
   286  	var fieldValue reflect.Value
   287  	var fieldType reflect.StructField
   288  
   289  	for i := 0; i < structNumFields; i++ {
   290  		fieldValue = structValue.Field(i)
   291  
   292  		if reflectinternal.IsZeroReflectValue(fieldValue) {
   293  			fieldType = structType.Field(i)
   294  			hashset[fieldType.Name] = true
   295  		}
   296  	}
   297  
   298  	return hashset
   299  }