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  }