@@ -67,32 +67,46 @@ public extension StagedChangeset where Collection: RangeReplaceableCollection, C
6767 }
6868
6969 var firstStageElements = ContiguousArray < Collection . Element > ( )
70+ var secondStageElements = ContiguousArray < Collection . Element > ( )
71+
72+ firstStageElements. reserveCapacity ( sourceElements. count)
7073
7174 let result = differentiate (
7275 source: sourceElements,
7376 target: targetElements,
7477 trackTargetIndexAsUpdated: false ,
7578 mapIndex: { ElementPath ( element: $0, section: section) } ,
76- remainedInTarget: { firstStageElements. append ( $0) }
79+ updatedElements: { firstStageElements. append ( $0) } ,
80+ undeletedElements: { secondStageElements. append ( $0) }
7781 )
7882
7983 var changesets = ContiguousArray < Changeset < Collection > > ( )
8084
8185 // The 1st stage changeset.
8286 // - Includes:
83- // - element deletes
8487 // - element updates
85- if !result. deleted . isEmpty || !result . updated. isEmpty {
88+ if !result. updated. isEmpty {
8689 changesets. append (
8790 Changeset (
8891 data: Collection ( firstStageElements) ,
89- elementDeleted: result. deleted,
9092 elementUpdated: result. updated
9193 )
9294 )
9395 }
9496
95- // The 2st stage changeset.
97+ // The 2nd stage changeset.
98+ // - Includes:
99+ // - element deletes
100+ if !result. deleted. isEmpty {
101+ changesets. append (
102+ Changeset (
103+ data: Collection ( secondStageElements) ,
104+ elementDeleted: result. deleted
105+ )
106+ )
107+ }
108+
109+ // The 3rd stage changeset.
96110 // - Includes:
97111 // - element inserts
98112 // - element moves
@@ -149,9 +163,10 @@ public extension StagedChangeset where Collection: RangeReplaceableCollection, C
149163 let contiguousSourceSections = ContiguousArray ( sourceSections. map { ContiguousArray ( $0. elements) } )
150164 let contiguousTargetSections = ContiguousArray ( targetSections. map { ContiguousArray ( $0. elements) } )
151165
152- var firstStageSections = ContiguousArray < Section > ( )
166+ var firstStageSections = sourceSections
153167 var secondStageSections = ContiguousArray < Section > ( )
154168 var thirdStageSections = ContiguousArray < Section > ( )
169+ var fourthStageSections = ContiguousArray < Section > ( )
155170
156171 var sourceElementTraces = contiguousSourceSections. map { section in
157172 ContiguousArray ( repeating: Trace < ElementPath > ( ) , count: section. count)
@@ -164,8 +179,8 @@ public extension StagedChangeset where Collection: RangeReplaceableCollection, C
164179 var flattenSourceIdentifiers = ContiguousArray < ElementIdentifier > ( )
165180 var flattenSourceElementPaths = ContiguousArray < ElementPath > ( )
166181
167- secondStageSections. reserveCapacity ( contiguousTargetSections. count)
168182 thirdStageSections. reserveCapacity ( contiguousTargetSections. count)
183+ fourthStageSections. reserveCapacity ( contiguousTargetSections. count)
169184
170185 flattenSourceIdentifiers. reserveCapacity ( flattenSourceCount)
171186 flattenSourceElementPaths. reserveCapacity ( flattenSourceCount)
@@ -252,43 +267,50 @@ public extension StagedChangeset where Collection: RangeReplaceableCollection, C
252267
253268 // Record the element deletions.
254269 for sourceSectionIndex in contiguousSourceSections. indices {
270+ let sourceSection = sourceSections [ sourceSectionIndex]
271+ let sourceElements = contiguousSourceSections [ sourceSectionIndex]
272+ var firstStageElements = sourceElements
273+
255274 // Should not calculate the element deletions in the deleted section.
256- guard case . some = sectionResult. metadata. sourceTraces [ sourceSectionIndex] . reference else {
257- continue
258- }
275+ if case . some = sectionResult. metadata. sourceTraces [ sourceSectionIndex] . reference {
276+ var offsetByDelete = 0
259277
260- var offsetByDelete = 0
261- var firstStageElements = ContiguousArray < Element > ( )
262- let sourceElements = contiguousSourceSections [ sourceSectionIndex]
278+ var secondStageElements = ContiguousArray < Element > ( )
263279
264- for sourceElementIndex in sourceElements. indices {
265- let sourceElementPath = ElementPath ( element: sourceElementIndex, section: sourceSectionIndex)
280+ for sourceElementIndex in sourceElements. indices {
281+ let sourceElementPath = ElementPath ( element: sourceElementIndex, section: sourceSectionIndex)
282+
283+ sourceElementTraces [ sourceElementPath] . deleteOffset = offsetByDelete
266284
267- sourceElementTraces [ sourceElementPath] . deleteOffset = offsetByDelete
285+ // If the element target section is recorded as insertion, record its element path as deletion.
286+ if let targetElementPath = sourceElementTraces [ sourceElementPath] . reference,
287+ case . some = sectionResult. metadata. targetReferences [ targetElementPath. section] {
288+ let targetElement = contiguousTargetSections [ targetElementPath]
289+ firstStageElements [ sourceElementIndex] = targetElement
290+ secondStageElements. append ( targetElement)
291+ continue
292+ }
268293
269- // If the element target section is recorded as insertion, record its element path as deletion.
270- if let targetElementPath = sourceElementTraces [ sourceElementPath] . reference,
271- case . some = sectionResult. metadata. targetReferences [ targetElementPath. section] {
272- let targetElement = contiguousTargetSections [ targetElementPath]
273- firstStageElements. append ( targetElement)
274- continue
294+ elementDeleted. append ( sourceElementPath)
295+ sourceElementTraces [ sourceElementPath] . isTracked = true
296+ offsetByDelete += 1
275297 }
276298
277- elementDeleted . append ( sourceElementPath )
278- sourceElementTraces [ sourceElementPath ] . isTracked = true
279- offsetByDelete += 1
299+ let secondStageSection = Section ( source : sourceSection , elements : secondStageElements )
300+ secondStageSections . append ( secondStageSection )
301+
280302 }
281303
282- let firstStageSection = Section ( source: sourceSections [ sourceSectionIndex ] , elements: firstStageElements)
283- firstStageSections. append ( firstStageSection)
304+ let firstStageSection = Section ( source: sourceSection , elements: firstStageElements)
305+ firstStageSections [ sourceSectionIndex ] = firstStageSection
284306 }
285307
286308 // Record the element updates/moves/insertions.
287309 for targetSectionIndex in contiguousTargetSections. indices {
288310 // Should not calculate the element updates/moves/insertions in the inserted section.
289311 guard let sourceSectionIndex = sectionResult. metadata. targetReferences [ targetSectionIndex] else {
290- secondStageSections. append ( targetSections [ targetSectionIndex] )
291312 thirdStageSections. append ( targetSections [ targetSectionIndex] )
313+ fourthStageSections. append ( targetSections [ targetSectionIndex] )
292314 continue
293315 }
294316
@@ -297,11 +319,11 @@ public extension StagedChangeset where Collection: RangeReplaceableCollection, C
297319
298320 let sectionDeleteOffset = sectionResult. metadata. sourceTraces [ sourceSectionIndex] . deleteOffset
299321
300- let secondStageSection = firstStageSections [ sourceSectionIndex - sectionDeleteOffset]
301- secondStageSections . append ( secondStageSection )
322+ let thirdStageSection = secondStageSections [ sourceSectionIndex - sectionDeleteOffset]
323+ thirdStageSections . append ( thirdStageSection )
302324
303- var thirdStageElements = ContiguousArray < Element > ( )
304- thirdStageElements . reserveCapacity ( targetElements. count)
325+ var fourthStageElements = ContiguousArray < Element > ( )
326+ fourthStageElements . reserveCapacity ( targetElements. count)
305327
306328 for targetElementIndex in targetElements. indices {
307329 untrackedSourceIndex = untrackedSourceIndex. flatMap { index in
@@ -314,15 +336,15 @@ public extension StagedChangeset where Collection: RangeReplaceableCollection, C
314336 // If the element source section is recorded as deletion, record its element path as insertion.
315337 guard let sourceElementPath = targetElementReferences [ targetElementPath] ,
316338 let movedSourceSectionIndex = sectionResult. metadata. sourceTraces [ sourceElementPath. section] . reference else {
317- thirdStageElements . append ( targetElement)
339+ fourthStageElements . append ( targetElement)
318340 elementInserted. append ( targetElementPath)
319341 continue
320342 }
321343
322344 sourceElementTraces [ sourceElementPath] . isTracked = true
323345
324346 let sourceElement = contiguousSourceSections [ sourceElementPath]
325- thirdStageElements . append ( targetElement)
347+ fourthStageElements . append ( targetElement)
326348
327349 if !targetElement. isContentEqual ( to: sourceElement) {
328350 elementUpdated. append ( sourceElementPath)
@@ -335,57 +357,67 @@ public extension StagedChangeset where Collection: RangeReplaceableCollection, C
335357 }
336358 }
337359
338- let thirdStageSection = Section ( source: secondStageSection , elements: thirdStageElements )
339- thirdStageSections . append ( thirdStageSection )
360+ let fourthStageSection = Section ( source: thirdStageSection , elements: fourthStageElements )
361+ fourthStageSections . append ( fourthStageSection )
340362 }
341363
342364 var changesets = ContiguousArray < Changeset < Collection > > ( )
343365
344366 // The 1st stage changeset.
345367 // - Includes:
346- // - section deletes
347- // - element deletes
348368 // - element updates
349- if !sectionResult . deleted . isEmpty || !elementDeleted . isEmpty || ! elementUpdated. isEmpty {
369+ if !elementUpdated. isEmpty {
350370 changesets. append (
351371 Changeset (
352372 data: Collection ( firstStageSections) ,
353- sectionDeleted: sectionResult. deleted,
354- elementDeleted: elementDeleted,
355373 elementUpdated: elementUpdated
356374 )
357375 )
358376 }
359377
360378 // The 2nd stage changeset.
361379 // - Includes:
380+ // - section deletes
381+ // - element deletes
382+ if !sectionResult. deleted. isEmpty || !elementDeleted. isEmpty {
383+ changesets. append (
384+ Changeset (
385+ data: Collection ( secondStageSections) ,
386+ sectionDeleted: sectionResult. deleted,
387+ elementDeleted: elementDeleted
388+ )
389+ )
390+ }
391+
392+ // The 3rd stage changeset.
393+ // - Includes:
362394 // - section inserts
363395 // - section moves
364396 if !sectionResult. inserted. isEmpty || !sectionResult. moved. isEmpty {
365397 changesets. append (
366398 Changeset (
367- data: Collection ( secondStageSections ) ,
399+ data: Collection ( thirdStageSections ) ,
368400 sectionInserted: sectionResult. inserted,
369401 sectionMoved: sectionResult. moved
370402 )
371403 )
372404 }
373405
374- // The 3rd stage changeset.
406+ // The 4th stage changeset.
375407 // - Includes:
376408 // - element inserts
377409 // - element moves
378410 if !elementInserted. isEmpty || !elementMoved. isEmpty {
379411 changesets. append (
380412 Changeset (
381- data: Collection ( thirdStageSections ) ,
413+ data: Collection ( fourthStageSections ) ,
382414 elementInserted: elementInserted,
383415 elementMoved: elementMoved
384416 )
385417 )
386418 }
387419
388- // The 4th stage changeset.
420+ // The 5th stage changeset.
389421 // - Includes:
390422 // - section updates
391423 if !sectionResult. updated. isEmpty {
@@ -415,7 +447,8 @@ internal func differentiate<E: Differentiable, I>(
415447 target: ContiguousArray < E > ,
416448 trackTargetIndexAsUpdated: Bool ,
417449 mapIndex: ( Int ) -> I ,
418- remainedInTarget: ( ( E ) -> Void ) ? = nil
450+ updatedElements: ( ( E ) -> Void ) ? = nil ,
451+ undeletedElements: ( ( E ) -> Void ) ? = nil
419452 ) -> DifferentiateResult < I > {
420453 var deleted = [ I] ( )
421454 var inserted = [ I] ( )
@@ -489,11 +522,15 @@ internal func differentiate<E: Differentiable, I>(
489522
490523 if let targetIndex = sourceTraces [ sourceIndex] . reference {
491524 let targetElement = target [ targetIndex]
492- remainedInTarget ? ( targetElement)
493- } else {
525+ updatedElements ? ( targetElement)
526+ undeletedElements ? ( targetElement)
527+ }
528+ else {
529+ let sourceElement = source [ sourceIndex]
494530 deleted. append ( mapIndex ( sourceIndex) )
495531 sourceTraces [ sourceIndex] . isTracked = true
496532 offsetByDelete += 1
533+ updatedElements ? ( sourceElement)
497534 }
498535 }
499536
@@ -517,7 +554,8 @@ internal func differentiate<E: Differentiable, I>(
517554 let deleteOffset = sourceTraces [ sourceIndex] . deleteOffset
518555 moved. append ( ( source: mapIndex ( sourceIndex - deleteOffset) , target: mapIndex ( targetIndex) ) )
519556 }
520- } else {
557+ }
558+ else {
521559 inserted. append ( mapIndex ( targetIndex) )
522560 }
523561 }
0 commit comments