@@ -20,6 +20,7 @@ public struct CollectionDifference<ChangeElement> {
20
20
/// each `remove` refers to the offset of its `element` in the original
21
21
/// state. Non-`nil` values of `associatedWith` refer to the offset of the
22
22
/// complementary change.
23
+ @_frozen
23
24
public enum Change {
24
25
case insert( offset: Int , element: ChangeElement , associatedWith: Int ? )
25
26
case remove( offset: Int , element: ChangeElement , associatedWith: Int ? )
@@ -87,22 +88,22 @@ public struct CollectionDifference<ChangeElement> {
87
88
var insertOffset = Set < Int > ( )
88
89
var removeOffset = Set < Int > ( )
89
90
90
- for c in changes {
91
- let offset = c . _offset
91
+ for change in changes {
92
+ let offset = change . _offset
92
93
if offset < 0 { return false }
93
94
94
- switch c {
95
+ switch change {
95
96
case . remove( _, _, _) :
96
97
if removeOffset. contains ( offset) { return false }
97
98
removeOffset. insert ( offset)
98
99
case . insert( _, _, _) :
99
100
if insertOffset. contains ( offset) { return false }
100
101
insertOffset. insert ( offset)
101
- }
102
+ }
102
103
103
- if let assoc = c . _associatedOffset {
104
+ if let assoc = change . _associatedOffset {
104
105
if assoc < 0 { return false }
105
- switch c {
106
+ switch change {
106
107
case . remove( _, _, _) :
107
108
if removeOffsetToAssoc [ offset] != nil { return false }
108
109
removeOffsetToAssoc [ offset] = assoc
@@ -137,7 +138,7 @@ public struct CollectionDifference<ChangeElement> {
137
138
public init ? < Changes: Collection > (
138
139
_ changes: Changes
139
140
) where Changes. Element == Change {
140
- if ! CollectionDifference < ChangeElement > . _validateChanges( changes) {
141
+ guard CollectionDifference< ChangeElement> . _validateChanges( changes) else {
141
142
return nil
142
143
}
143
144
@@ -217,8 +218,10 @@ public struct CollectionDifference<ChangeElement> {
217
218
extension CollectionDifference : Collection {
218
219
public typealias Element = Change
219
220
220
- public struct Index : Equatable , Hashable , Comparable {
221
+ @_fixed_layout
222
+ public struct Index {
221
223
// Opaque index type is isomorphic to Int
224
+ @usableFromInline
222
225
internal let _offset : Int
223
226
224
227
internal init ( _offset offset: Int ) {
@@ -259,7 +262,19 @@ extension CollectionDifference: Collection {
259
262
}
260
263
261
264
@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
263
278
public static func < (
264
279
lhs: CollectionDifference . Index ,
265
280
rhs: CollectionDifference . Index
@@ -268,6 +283,14 @@ extension CollectionDifference.Index { // Comparable
268
283
}
269
284
}
270
285
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
+
271
294
@available ( macOS 9999 , iOS 9999 , tvOS 9999 , watchOS 9999 , * ) // FIXME(availability-5.1)
272
295
extension CollectionDifference . Change : Equatable where ChangeElement: Equatable { }
273
296
@@ -289,50 +312,50 @@ extension CollectionDifference where ChangeElement: Hashable {
289
312
///
290
313
/// - Complexity: O(*n*) where *n* is `self.count`
291
314
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)
298
321
} else {
299
- res [ element] = . some( r . _offset)
322
+ result [ element] = . some( removal . _offset)
300
323
}
301
324
}
302
- return res . filter { ( _, v) -> Bool in v != . none }
325
+ return result . filter { ( _, v) -> Bool in v != . none }
303
326
} ( )
304
327
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)
311
334
} else {
312
- res [ element] = . some( i . _offset)
335
+ result [ element] = . some( insertion . _offset)
313
336
}
314
337
}
315
- return res . filter { ( _, v) -> Bool in v != . none }
338
+ return result . filter { ( _, v) -> Bool in v != . none }
316
339
} ( )
317
340
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
323
346
}
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)
326
349
}
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
330
353
}
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)
333
356
}
334
357
}
335
- return c
358
+ return change
336
359
} ) )
337
360
}
338
361
}
0 commit comments