(changes *[]FieldChange, tokens []string, patchNode, oldNode, newNode interface{})
| 190 | } |
| 191 | |
| 192 | func walkPatch(changes *[]FieldChange, tokens []string, patchNode, oldNode, newNode interface{}) error { |
| 193 | switch typed := patchNode.(type) { |
| 194 | case map[string]interface{}: |
| 195 | if len(typed) == 0 { |
| 196 | return nil |
| 197 | } |
| 198 | oldMap, _ := oldNode.(map[string]interface{}) |
| 199 | newMap, _ := newNode.(map[string]interface{}) |
| 200 | keys := make([]string, 0, len(typed)) |
| 201 | for key := range typed { |
| 202 | keys = append(keys, key) |
| 203 | } |
| 204 | sort.Strings(keys) |
| 205 | |
| 206 | for _, key := range keys { |
| 207 | var oldChild interface{} |
| 208 | var newChild interface{} |
| 209 | if oldMap != nil { |
| 210 | oldChild = oldMap[key] |
| 211 | } |
| 212 | if newMap != nil { |
| 213 | newChild = newMap[key] |
| 214 | } |
| 215 | if err := walkPatch(changes, append(tokens, key), typed[key], oldChild, newChild); err != nil { |
| 216 | return err |
| 217 | } |
| 218 | } |
| 219 | case []interface{}: |
| 220 | return diffArrayNodes(changes, tokens, oldNode, newNode) |
| 221 | default: |
| 222 | path, field := splitTokens(tokens) |
| 223 | change := FieldChange{ |
| 224 | Path: path, |
| 225 | Field: field, |
| 226 | } |
| 227 | |
| 228 | if patchNode == nil { |
| 229 | change.Change = "remove" |
| 230 | change.OldValue = oldNode |
| 231 | } else { |
| 232 | if oldNode == nil { |
| 233 | change.Change = "add" |
| 234 | change.NewValue = newNode |
| 235 | } else { |
| 236 | if reflect.DeepEqual(oldNode, newNode) { |
| 237 | return nil |
| 238 | } |
| 239 | change.Change = "replace" |
| 240 | change.OldValue = oldNode |
| 241 | change.NewValue = newNode |
| 242 | } |
| 243 | } |
| 244 | *changes = append(*changes, change) |
| 245 | } |
| 246 | return nil |
| 247 | } |
| 248 | |
| 249 | func diffArrayNodes(changes *[]FieldChange, tokens []string, oldNode, newNode interface{}) error { |
no test coverage detected