@@ -20,6 +20,7 @@ public struct CollectionDifference<ChangeElement> {
2020 /// each `remove` refers to the offset of its `element` in the original
2121 /// state. Non-`nil` values of `associatedWith` refer to the offset of the
2222 /// complementary change.
23+ @_frozen
2324 public enum Change {
2425 case insert( offset: Int , element: ChangeElement , associatedWith: Int ? )
2526 case remove( offset: Int , element: ChangeElement , associatedWith: Int ? )
@@ -87,22 +88,22 @@ public struct CollectionDifference<ChangeElement> {
8788 var insertOffset = Set < Int > ( )
8889 var removeOffset = Set < Int > ( )
8990
90- for c in changes {
91- let offset = c . _offset
91+ for change in changes {
92+ let offset = change . _offset
9293 if offset < 0 { return false }
9394
94- switch c {
95+ switch change {
9596 case . remove( _, _, _) :
9697 if removeOffset. contains ( offset) { return false }
9798 removeOffset. insert ( offset)
9899 case . insert( _, _, _) :
99100 if insertOffset. contains ( offset) { return false }
100101 insertOffset. insert ( offset)
101- }
102+ }
102103
103- if let assoc = c . _associatedOffset {
104+ if let assoc = change . _associatedOffset {
104105 if assoc < 0 { return false }
105- switch c {
106+ switch change {
106107 case . remove( _, _, _) :
107108 if removeOffsetToAssoc [ offset] != nil { return false }
108109 removeOffsetToAssoc [ offset] = assoc
@@ -137,7 +138,7 @@ public struct CollectionDifference<ChangeElement> {
137138 public init ? < Changes: Collection > (
138139 _ changes: Changes
139140 ) where Changes. Element == Change {
140- if ! CollectionDifference < ChangeElement > . _validateChanges( changes) {
141+ guard CollectionDifference< ChangeElement> . _validateChanges( changes) else {
141142 return nil
142143 }
143144
@@ -217,8 +218,10 @@ public struct CollectionDifference<ChangeElement> {
217218extension CollectionDifference : Collection {
218219 public typealias Element = Change
219220
220- public struct Index : Equatable , Hashable , Comparable {
221+ @_fixed_layout
222+ public struct Index {
221223 // Opaque index type is isomorphic to Int
224+ @usableFromInline
222225 internal let _offset : Int
223226
224227 internal init ( _offset offset: Int ) {
@@ -259,7 +262,19 @@ extension CollectionDifference: Collection {
259262}
260263
261264@available ( macOS 9999 , iOS 9999 , tvOS 9999 , watchOS 9999 , * ) // FIXME(availability-5.1)
262- extension CollectionDifference . Index { // Comparable
265+ extension CollectionDifference . Index : Equatable {
266+ @inlinable
267+ public static func == (
268+ lhs: CollectionDifference . Index ,
269+ rhs: CollectionDifference . Index
270+ ) -> Bool {
271+ return lhs. _offset == rhs. _offset
272+ }
273+ }
274+
275+ @available ( macOS 9999 , iOS 9999 , tvOS 9999 , watchOS 9999 , * ) // FIXME(availability-5.1)
276+ extension CollectionDifference . Index : Comparable {
277+ @inlinable
263278 public static func < (
264279 lhs: CollectionDifference . Index ,
265280 rhs: CollectionDifference . Index
@@ -268,6 +283,14 @@ extension CollectionDifference.Index { // Comparable
268283 }
269284}
270285
286+ @available ( macOS 9999 , iOS 9999 , tvOS 9999 , watchOS 9999 , * ) // FIXME(availability-5.1)
287+ extension CollectionDifference . Index : Hashable {
288+ @inlinable
289+ public func hash( into hasher: inout Hasher ) {
290+ hasher. combine ( _offset)
291+ }
292+ }
293+
271294@available ( macOS 9999 , iOS 9999 , tvOS 9999 , watchOS 9999 , * ) // FIXME(availability-5.1)
272295extension CollectionDifference . Change : Equatable where ChangeElement: Equatable { }
273296
@@ -289,50 +312,50 @@ extension CollectionDifference where ChangeElement: Hashable {
289312 ///
290313 /// - Complexity: O(*n*) where *n* is `self.count`
291314 public func inferringMoves( ) -> CollectionDifference < ChangeElement > {
292- let removeDict : [ ChangeElement : Int ? ] = {
293- var res = [ ChangeElement: Int? ] ( minimumCapacity: Swift . min ( removals. count, insertions. count) )
294- for r in removals {
295- let element = r . _element
296- if res [ element] != . none {
297- res [ element] = . some( . none)
315+ let uniqueRemovals : [ ChangeElement : Int ? ] = {
316+ var result = [ ChangeElement: Int? ] ( minimumCapacity: Swift . min ( removals. count, insertions. count) )
317+ for removal in removals {
318+ let element = removal . _element
319+ if result [ element] != . none {
320+ result [ element] = . some( . none)
298321 } else {
299- res [ element] = . some( r . _offset)
322+ result [ element] = . some( removal . _offset)
300323 }
301324 }
302- return res . filter { ( _, v) -> Bool in v != . none }
325+ return result . filter { ( _, v) -> Bool in v != . none }
303326 } ( )
304327
305- let insertDict : [ ChangeElement : Int ? ] = {
306- var res = [ ChangeElement: Int? ] ( minimumCapacity: Swift . min ( removals. count, insertions. count) )
307- for i in insertions {
308- let element = i . _element
309- if res [ element] != . none {
310- res [ element] = . some( . none)
328+ let uniqueInsertions : [ ChangeElement : Int ? ] = {
329+ var result = [ ChangeElement: Int? ] ( minimumCapacity: Swift . min ( removals. count, insertions. count) )
330+ for insertion in insertions {
331+ let element = insertion . _element
332+ if result [ element] != . none {
333+ result [ element] = . some( . none)
311334 } else {
312- res [ element] = . some( i . _offset)
335+ result [ element] = . some( insertion . _offset)
313336 }
314337 }
315- return res . filter { ( _, v) -> Bool in v != . none }
338+ return result . filter { ( _, v) -> Bool in v != . none }
316339 } ( )
317340
318- return CollectionDifference ( _validatedChanges: map ( { ( c : Change ) -> Change in
319- switch c {
320- case . remove( offset: let o , element: let e , associatedWith: _) :
321- if removeDict [ e ] == nil {
322- return c
341+ return CollectionDifference ( _validatedChanges: map ( { ( change : Change ) -> Change in
342+ switch change {
343+ case . remove( offset: let offset , element: let element , associatedWith: _) :
344+ if uniqueRemovals [ element ] == nil {
345+ return change
323346 }
324- if let assoc = insertDict [ e ] {
325- return . remove( offset: o , element: e , associatedWith: assoc)
347+ if let assoc = uniqueInsertions [ element ] {
348+ return . remove( offset: offset , element: element , associatedWith: assoc)
326349 }
327- case . insert( offset: let o , element: let e , associatedWith: _) :
328- if insertDict [ e ] == nil {
329- return c
350+ case . insert( offset: let offset , element: let element , associatedWith: _) :
351+ if uniqueInsertions [ element ] == nil {
352+ return change
330353 }
331- if let assoc = removeDict [ e ] {
332- return . insert( offset: o , element: e , associatedWith: assoc)
354+ if let assoc = uniqueRemovals [ element ] {
355+ return . insert( offset: offset , element: element , associatedWith: assoc)
333356 }
334357 }
335- return c
358+ return change
336359 } ) )
337360 }
338361}
0 commit comments