github.com/graywolf-at-work-2/terraform-vendor@v1.4.5/internal/command/jsonformat/collections/slice.go (about) 1 package collections 2 3 import ( 4 "reflect" 5 6 "github.com/hashicorp/terraform/internal/command/jsonformat/computed" 7 8 "github.com/hashicorp/terraform/internal/plans" 9 "github.com/hashicorp/terraform/internal/plans/objchange" 10 ) 11 12 type TransformIndices func(before, after int) computed.Diff 13 type ProcessIndices func(before, after int) 14 type IsObjType[Input any] func(input Input) bool 15 16 func TransformSlice[Input any](before, after []Input, process TransformIndices, isObjType IsObjType[Input]) ([]computed.Diff, plans.Action) { 17 current := plans.NoOp 18 if before != nil && after == nil { 19 current = plans.Delete 20 } 21 if before == nil && after != nil { 22 current = plans.Create 23 } 24 25 var elements []computed.Diff 26 ProcessSlice(before, after, func(before, after int) { 27 element := process(before, after) 28 elements = append(elements, element) 29 current = CompareActions(current, element.Action) 30 }, isObjType) 31 return elements, current 32 } 33 34 func ProcessSlice[Input any](before, after []Input, process ProcessIndices, isObjType IsObjType[Input]) { 35 lcs := objchange.LongestCommonSubsequence(before, after, func(before, after Input) bool { 36 return reflect.DeepEqual(before, after) 37 }) 38 39 var beforeIx, afterIx, lcsIx int 40 for beforeIx < len(before) || afterIx < len(after) || lcsIx < len(lcs) { 41 // Step through all the before values until we hit the next item in the 42 // longest common subsequence. We are going to just say that all of 43 // these have been deleted. 44 for beforeIx < len(before) && (lcsIx >= len(lcs) || !reflect.DeepEqual(before[beforeIx], lcs[lcsIx])) { 45 isObjectDiff := isObjType(before[beforeIx]) && afterIx < len(after) && isObjType(after[afterIx]) && (lcsIx >= len(lcs) || !reflect.DeepEqual(after[afterIx], lcs[lcsIx])) 46 if isObjectDiff { 47 process(beforeIx, afterIx) 48 beforeIx++ 49 afterIx++ 50 continue 51 } 52 53 process(beforeIx, len(after)) 54 beforeIx++ 55 } 56 57 // Now, step through all the after values until hit the next item in the 58 // LCS. We are going to say that all of these have been created. 59 for afterIx < len(after) && (lcsIx >= len(lcs) || !reflect.DeepEqual(after[afterIx], lcs[lcsIx])) { 60 process(len(before), afterIx) 61 afterIx++ 62 } 63 64 // Finally, add the item in common as unchanged. 65 if lcsIx < len(lcs) { 66 process(beforeIx, afterIx) 67 beforeIx++ 68 afterIx++ 69 lcsIx++ 70 } 71 } 72 }