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 }