github.com/lmorg/murex@v0.0.0-20240217211045-e081c89cd4ef/utils/alter/merge.go (about)

     1  package alter
     2  
     3  import (
     4  	"fmt"
     5  	"reflect"
     6  
     7  	"github.com/lmorg/murex/debug"
     8  )
     9  
    10  func mergeArray(v interface{}, new *interface{}) (ret interface{}, err error) {
    11  	if !debug.Enabled {
    12  		defer func() {
    13  			if r := recover(); r != nil {
    14  				err = fmt.Errorf("cannot merge new array into old. Likely this is because of a data-type mismatch: %s", r)
    15  			}
    16  		}()
    17  	}
    18  
    19  	switch v := v.(type) {
    20  	case []string:
    21  		ret = append(v, (*new).([]string)...)
    22  
    23  	case []float64:
    24  		ret = append(v, (*new).([]float64)...)
    25  
    26  	case []int:
    27  		ret = append(v, (*new).([]int)...)
    28  
    29  	case []bool:
    30  		ret = append(v, (*new).([]bool)...)
    31  
    32  	case []interface{}:
    33  		ret = append(v, (*new).([]interface{})...)
    34  
    35  	default:
    36  		return v, fmt.Errorf("path either points to an object that's not an array or no condition has been made for %T", v)
    37  	}
    38  
    39  	return
    40  }
    41  
    42  func mergeMap(v interface{}, new *interface{}) (ret interface{}, err error) {
    43  	if !debug.Enabled {
    44  		defer func() {
    45  			if r := recover(); r != nil {
    46  				err = fmt.Errorf("cannot merge new map into old. Likely this is because of a data-type mismatch: %s", r)
    47  			}
    48  		}()
    49  	}
    50  
    51  	switch v.(type) {
    52  
    53  	//interface
    54  
    55  	case map[string]interface{}:
    56  		ret = v
    57  		for key, val := range (*new).(map[string]interface{}) {
    58  			switch t := val.(type) {
    59  			case string, int, float64, bool, nil:
    60  				ret.(map[string]interface{})[key] = t
    61  			default:
    62  				oldKind := reflect.TypeOf(ret.(map[string]interface{})[key]).Kind()
    63  				newKind := reflect.TypeOf(val).Kind()
    64  				switch {
    65  				case oldKind != newKind:
    66  					ret.(map[string]interface{})[key] = t
    67  				case newKind == reflect.Slice:
    68  					ret.(map[string]interface{})[key], err = mergeArray(ret.(map[string]interface{})[key], &val)
    69  				case newKind == reflect.Map:
    70  					ret.(map[string]interface{})[key], err = mergeMap(ret.(map[string]interface{})[key], &val)
    71  				default:
    72  					// possibly not an object so lets just overwrite...
    73  					ret.(map[string]interface{})[key] = t
    74  				}
    75  			}
    76  		}
    77  
    78  	case map[interface{}]interface{}:
    79  		ret = v
    80  		for key, val := range (*new).(map[interface{}]interface{}) {
    81  			ret.(map[interface{}]interface{})[key] = val
    82  		}
    83  
    84  		// string
    85  
    86  	case map[string]string:
    87  		ret = v
    88  		for key, val := range (*new).(map[string]interface{}) {
    89  			ret.(map[string]interface{})[key] = val
    90  		}
    91  
    92  	case map[interface{}]string:
    93  		ret = v
    94  		for key, val := range (*new).(map[interface{}]interface{}) {
    95  			ret.(map[interface{}]interface{})[key] = val
    96  		}
    97  
    98  		// integer
    99  
   100  	case map[string]int:
   101  		ret = v
   102  		for key, val := range (*new).(map[string]interface{}) {
   103  			ret.(map[string]interface{})[key] = val
   104  		}
   105  
   106  	case map[interface{}]int:
   107  		ret = v
   108  		for key, val := range (*new).(map[interface{}]interface{}) {
   109  			ret.(map[interface{}]interface{})[key] = val
   110  		}
   111  
   112  		// float
   113  
   114  	case map[string]float64:
   115  		ret = v
   116  		for key, val := range (*new).(map[string]interface{}) {
   117  			ret.(map[string]interface{})[key] = val
   118  		}
   119  
   120  	case map[interface{}]float64:
   121  		ret = v
   122  		for key, val := range (*new).(map[interface{}]interface{}) {
   123  			ret.(map[interface{}]interface{})[key] = val
   124  		}
   125  
   126  		// bool
   127  
   128  	case map[string]bool:
   129  		ret = v
   130  		for key, val := range (*new).(map[string]interface{}) {
   131  			ret.(map[string]interface{})[key] = val
   132  		}
   133  
   134  	case map[interface{}]bool:
   135  		ret = v
   136  		for key, val := range (*new).(map[interface{}]interface{}) {
   137  			ret.(map[interface{}]interface{})[key] = val
   138  		}
   139  
   140  	default:
   141  		return v, fmt.Errorf("path either points to an object that's not an map or no condition has been made for %T", v)
   142  	}
   143  
   144  	return
   145  }