Skip to content

Commit 6ded168

Browse files
committed
Revert "Revert "quick rewrite of semantic equality for sets""
This reverts commit b37dde1.
1 parent 6641eb4 commit 6ded168

File tree

1 file changed

+34
-19
lines changed

1 file changed

+34
-19
lines changed

internal/fwschemadata/value_semantic_equality_set.go

Lines changed: 34 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,10 @@ func ValueSemanticEqualitySetElements(ctx context.Context, req ValueSemanticEqua
128128
// Short circuit flag
129129
updatedElements := false
130130

131+
// The underlying loop will mutate priorValueElements to avoid keeping
132+
// duplicate semantically equal elements. Need the original length to avoid panicks
133+
originalPriorElementsLength := len(priorValueElements)
134+
131135
// Loop through proposed elements by delegating to the recursive semantic
132136
// equality logic. This ensures that recursion will catch a further
133137
// underlying element type has its semantic equality logic checked, even if
@@ -136,33 +140,44 @@ func ValueSemanticEqualitySetElements(ctx context.Context, req ValueSemanticEqua
136140
// Ensure new value always contains all of proposed new value
137141
newValueElements[idx] = proposedNewValueElement
138142

139-
if idx >= len(priorValueElements) {
143+
if idx >= originalPriorElementsLength {
140144
continue
141145
}
142146

143-
elementReq := ValueSemanticEqualityRequest{
144-
Path: req.Path.AtSetValue(proposedNewValueElement),
145-
PriorValue: priorValueElements[idx],
146-
ProposedNewValue: proposedNewValueElement,
147-
}
148-
elementResp := &ValueSemanticEqualityResponse{
149-
NewValue: elementReq.ProposedNewValue,
150-
}
147+
// Loop through all prior value elements and see if there are any semantically equal elements
148+
for pIdx, priorValue := range priorValueElements {
149+
elementReq := ValueSemanticEqualityRequest{
150+
Path: req.Path.AtSetValue(proposedNewValueElement),
151+
PriorValue: priorValue,
152+
ProposedNewValue: proposedNewValueElement,
153+
}
154+
elementResp := &ValueSemanticEqualityResponse{
155+
NewValue: elementReq.ProposedNewValue,
156+
}
151157

152-
ValueSemanticEquality(ctx, elementReq, elementResp)
158+
ValueSemanticEquality(ctx, elementReq, elementResp)
153159

154-
resp.Diagnostics.Append(elementResp.Diagnostics...)
160+
resp.Diagnostics.Append(elementResp.Diagnostics...)
155161

156-
if resp.Diagnostics.HasError() {
157-
return
158-
}
162+
if resp.Diagnostics.HasError() {
163+
return
164+
}
159165

160-
if elementResp.NewValue.Equal(elementReq.ProposedNewValue) {
161-
continue
162-
}
166+
if elementResp.NewValue.Equal(elementReq.ProposedNewValue) {
167+
// This prior value element didn't match, but there could be other elements that do
168+
continue
169+
}
170+
171+
// Prior state was kept, meaning that we found a semantically equal element
172+
updatedElements = true
163173

164-
updatedElements = true
165-
newValueElements[idx] = elementResp.NewValue
174+
// Remove the semantically equal element from the slice of candidates
175+
priorValueElements = append(priorValueElements[:pIdx], priorValueElements[pIdx+1:]...)
176+
177+
// Order doesn't matter, so we can just set the prior state element to this index
178+
newValueElements[idx] = elementResp.NewValue
179+
break
180+
}
166181
}
167182

168183
// No changes required if the elements were not updated.

0 commit comments

Comments
 (0)