package engine import ( "cmp" "slices" "go.maximumdirect.net/configkit/internal/document" ) // compareResolutionValues reports field-level changes at stable list positions. func compareResolutionValues(before, after *document.Node, correspondence ...resolutionCorrespondence) []documentDelta { var deltas []documentDelta var compare func(*document.Node, *document.Node, Path) compare = func(left, right *document.Node, path Path) { if left == nil || right == nil || left.Kind != right.Kind { compareConfigurationValue(left, right, path, &deltas) return } switch left.Kind { case document.Mapping: leftEntries := make(map[string]*document.Node, len(left.Mapping)) for _, entry := range left.Mapping { leftEntries[entry.Key] = entry.Value } for _, entry := range right.Mapping { compare(leftEntries[entry.Key], entry.Value, path.Key(entry.Key)) delete(leftEntries, entry.Key) } for key, value := range leftEntries { compare(value, nil, path.Key(key)) } case document.Sequence: if len(correspondence) != 0 { if collection, registered := correspondence[0].collections[path.String()]; registered { if !collection.eligible { if !configurationValuesEqual(left, right) { deltas = append(deltas, documentDelta{path: path.clone(), kind: documentReplaced}) } return } if collection.structural { deltas = append(deltas, documentDelta{path: path.clone(), kind: documentReplaced}) } for finalIndex, entryIndex := range collection.finalToEntry { if entryIndex >= 0 { compare(left.Sequence[entryIndex], right.Sequence[finalIndex], path.Index(finalIndex)) } } return } } if len(left.Sequence) != len(right.Sequence) { deltas = append(deltas, documentDelta{path: path.clone(), kind: documentReplaced}) return } for index := range left.Sequence { compare(left.Sequence[index], right.Sequence[index], path.Index(index)) } default: compareConfigurationValue(left, right, path, &deltas) } } compare(before, after, Path{}) slices.SortFunc(deltas, func(a, b documentDelta) int { if order := cmp.Compare(a.path.String(), b.path.String()); order != 0 { return order } return int(a.kind) - int(b.kind) }) return deltas }