11
11
//===----------------------------------------------------------------------===//
12
12
13
13
/// A type that represents the difference between two ordered collection states.
14
- @available ( swift , introduced : 5.1 )
14
+ @available ( macOS 9999 , iOS 9999 , tvOS 9999 , watchOS 9999 , * ) // FIXME(availability- 5.1)
15
15
public struct CollectionDifference < ChangeElement> {
16
16
/// A type that represents a single change to a collection.
17
17
///
@@ -25,7 +25,7 @@ public struct CollectionDifference<ChangeElement> {
25
25
case remove( offset: Int , element: ChangeElement , associatedWith: Int ? )
26
26
27
27
// Internal common field accessors
28
- var offset : Int {
28
+ internal var _offset : Int {
29
29
get {
30
30
switch self {
31
31
case . insert( offset: let o, element: _, associatedWith: _) :
@@ -35,7 +35,7 @@ public struct CollectionDifference<ChangeElement> {
35
35
}
36
36
}
37
37
}
38
- var element : ChangeElement {
38
+ internal var _element : ChangeElement {
39
39
get {
40
40
switch self {
41
41
case . insert( offset: _, element: let e, associatedWith: _) :
@@ -45,7 +45,7 @@ public struct CollectionDifference<ChangeElement> {
45
45
}
46
46
}
47
47
}
48
- var associatedOffset : Int ? {
48
+ internal var _associatedOffset : Int ? {
49
49
get {
50
50
switch self {
51
51
case . insert( offset: _, element: _, associatedWith: let o) :
@@ -57,6 +57,12 @@ public struct CollectionDifference<ChangeElement> {
57
57
}
58
58
}
59
59
60
+ /// The `.insert` changes contained by this difference, from lowest offset to highest
61
+ public let insertions : [ Change ]
62
+
63
+ /// The `.remove` changes contained by this difference, from lowest offset to highest
64
+ public let removals : [ Change ]
65
+
60
66
/// The public initializer calls this function to ensure that its parameter
61
67
/// meets the conditions set in its documentation.
62
68
///
@@ -71,7 +77,9 @@ public struct CollectionDifference<ChangeElement> {
71
77
/// 3. All associations between insertions and removals are symmetric
72
78
///
73
79
/// Complexity: O(`changes.count`)
74
- private static func validateChanges< C> ( _ changes : C ) -> Bool where C: Collection , C. Element == Change {
80
+ private static func _validateChanges< Changes: Collection > (
81
+ _ changes : Changes
82
+ ) -> Bool where Changes. Element == Change {
75
83
if changes. count == 0 { return true }
76
84
77
85
var insertAssocToOffset = Dictionary < Int , Int > ( )
@@ -80,7 +88,7 @@ public struct CollectionDifference<ChangeElement> {
80
88
var removeOffset = Set < Int > ( )
81
89
82
90
for c in changes {
83
- let offset = c. offset
91
+ let offset = c. _offset
84
92
if offset < 0 { return false }
85
93
86
94
switch c {
@@ -92,7 +100,7 @@ public struct CollectionDifference<ChangeElement> {
92
100
insertOffset. insert ( offset)
93
101
}
94
102
95
- if let assoc = c. associatedOffset {
103
+ if let assoc = c. _associatedOffset {
96
104
if assoc < 0 { return false }
97
105
switch c {
98
106
case . remove( _, _, _) :
@@ -126,12 +134,14 @@ public struct CollectionDifference<ChangeElement> {
126
134
///
127
135
/// - Complexity: O(*n* * log(*n*)), where *n* is the length of the
128
136
/// parameter.
129
- public init ? < C> ( _ c: C ) where C: Collection , C. Element == Change {
130
- if !CollectionDifference < ChangeElement > . validateChanges( c) {
137
+ public init ? < Changes: Collection > (
138
+ _ changes: Changes
139
+ ) where Changes. Element == Change {
140
+ if !CollectionDifference < ChangeElement > . _validateChanges( changes) {
131
141
return nil
132
142
}
133
143
134
- self . init ( validatedChanges : c )
144
+ self . init ( _validatedChanges : changes )
135
145
}
136
146
137
147
/// Internal initializer for use by algorithms that cannot produce invalid
@@ -146,27 +156,29 @@ public struct CollectionDifference<ChangeElement> {
146
156
///
147
157
/// - Complexity: O(*n* * log(*n*)), where *n* is the length of the
148
158
/// parameter.
149
- init < C> ( validatedChanges c: C ) where C: Collection , C. Element == Change {
150
- let changes = c. sorted { ( a, b) -> Bool in
159
+ internal init < Changes: Collection > (
160
+ _validatedChanges changes: Changes
161
+ ) where Changes. Element == Change {
162
+ let sortedChanges = changes. sorted { ( a, b) -> Bool in
151
163
switch ( a, b) {
152
164
case ( . remove( _, _, _) , . insert( _, _, _) ) :
153
165
return true
154
166
case ( . insert( _, _, _) , . remove( _, _, _) ) :
155
167
return false
156
168
default :
157
- return a. offset < b. offset
169
+ return a. _offset < b. _offset
158
170
}
159
171
}
160
172
161
173
// Find first insertion via binary search
162
174
let firstInsertIndex : Int
163
- if changes . count == 0 {
175
+ if sortedChanges . count == 0 {
164
176
firstInsertIndex = 0
165
177
} else {
166
- var range = 0 ... changes . count
178
+ var range = 0 ... sortedChanges . count
167
179
while range. lowerBound != range. upperBound {
168
180
let i = ( range. lowerBound + range. upperBound) / 2
169
- switch changes [ i] {
181
+ switch sortedChanges [ i] {
170
182
case . insert( _, _, _) :
171
183
range = range. lowerBound... i
172
184
case . remove( _, _, _) :
@@ -176,15 +188,9 @@ public struct CollectionDifference<ChangeElement> {
176
188
firstInsertIndex = range. lowerBound
177
189
}
178
190
179
- removals = Array ( changes [ 0 ..< firstInsertIndex] )
180
- insertions = Array ( changes [ firstInsertIndex..< changes . count] )
191
+ removals = Array ( sortedChanges [ 0 ..< firstInsertIndex] )
192
+ insertions = Array ( sortedChanges [ firstInsertIndex..< sortedChanges . count] )
181
193
}
182
-
183
- /// The `.insert` changes contained by this difference, from lowest offset to highest
184
- public let insertions : [ Change ]
185
-
186
- /// The `.remove` changes contained by this difference, from lowest offset to highest
187
- public let removals : [ Change ]
188
194
}
189
195
190
196
/// A CollectionDifference is itself a Collection.
@@ -207,61 +213,75 @@ public struct CollectionDifference<ChangeElement> {
207
213
/// }
208
214
/// }
209
215
/// ```
210
- extension CollectionDifference : Collection {
211
- public typealias Element = CollectionDifference < ChangeElement > . Change
212
-
213
- // Opaque index type is isomorphic to Int
214
- public struct Index : Comparable , Hashable {
215
- public static func < (
216
- lhs: CollectionDifference < ChangeElement > . Index ,
217
- rhs: CollectionDifference < ChangeElement > . Index
218
- ) -> Bool {
219
- return lhs. i < rhs. i
220
- }
221
-
222
- let i : Int
223
- init ( _ index: Int ) {
224
- i = index
216
+ @available ( macOS 9999 , iOS 9999 , tvOS 9999 , watchOS 9999 , * ) // FIXME(availability-5.1)
217
+ extension CollectionDifference : Collection {
218
+ public typealias Element = Change
219
+
220
+ public struct Index : Equatable , Hashable , Comparable {
221
+ // Opaque index type is isomorphic to Int
222
+ internal let _offset : Int
223
+
224
+ internal init ( _offset offset: Int ) {
225
+ _offset = offset
225
226
}
226
227
}
227
228
228
- public var startIndex : CollectionDifference < ChangeElement > . Index {
229
- return Index ( 0 )
229
+ public var startIndex : Index {
230
+ return Index ( _offset : 0 )
230
231
}
231
-
232
- public var endIndex : CollectionDifference < ChangeElement > . Index {
233
- return Index ( removals. count + insertions. count)
232
+
233
+ public var endIndex : Index {
234
+ return Index ( _offset : removals. count + insertions. count)
234
235
}
235
-
236
- public func index( after index: CollectionDifference < ChangeElement > . Index ) -> CollectionDifference < ChangeElement > . Index {
237
- return Index ( index. i + 1 )
236
+
237
+ public func index( after index: Index ) -> Index {
238
+ return Index ( _offset : index. _offset + 1 )
238
239
}
239
-
240
- public subscript( position: CollectionDifference < ChangeElement > . Index ) -> Element {
241
- return position. i < removals. count ? removals [ removals. count - ( position. i + 1 ) ] : insertions [ position. i - removals. count]
240
+
241
+ public subscript( position: Index ) -> Element {
242
+ if position. _offset < removals. count {
243
+ return removals [ removals. count - ( position. _offset + 1 ) ]
244
+ }
245
+ return insertions [ position. _offset - removals. count]
242
246
}
243
-
244
- public func index( before index: CollectionDifference < ChangeElement > . Index ) -> CollectionDifference < ChangeElement > . Index {
245
- return Index ( index. i - 1 )
247
+
248
+ public func index( before index: Index ) -> Index {
249
+ return Index ( _offset : index. _offset - 1 )
246
250
}
247
-
248
- public func formIndex( _ index: inout CollectionDifference < ChangeElement > . Index , offsetBy distance: Int ) {
249
- index = Index ( index. i + distance)
251
+
252
+ public func formIndex( _ index: inout Index , offsetBy distance: Int ) {
253
+ index = Index ( _offset : index. _offset + distance)
250
254
}
251
-
252
- public func distance( from start: CollectionDifference < ChangeElement > . Index , to end: CollectionDifference < ChangeElement > . Index ) -> Int {
253
- return end. i - start. i
255
+
256
+ public func distance( from start: Index , to end: Index ) -> Int {
257
+ return end. _offset - start. _offset
258
+ }
259
+ }
260
+
261
+ @available ( macOS 9999 , iOS 9999 , tvOS 9999 , watchOS 9999 , * ) // FIXME(availability-5.1)
262
+ extension CollectionDifference . Index { // Comparable
263
+ public static func < (
264
+ lhs: CollectionDifference . Index ,
265
+ rhs: CollectionDifference . Index
266
+ ) -> Bool {
267
+ return lhs. _offset < rhs. _offset
254
268
}
255
269
}
256
270
271
+ @available ( macOS 9999 , iOS 9999 , tvOS 9999 , watchOS 9999 , * ) // FIXME(availability-5.1)
257
272
extension CollectionDifference . Change : Equatable where ChangeElement: Equatable { }
258
273
274
+ @available ( macOS 9999 , iOS 9999 , tvOS 9999 , watchOS 9999 , * ) // FIXME(availability-5.1)
259
275
extension CollectionDifference : Equatable where ChangeElement: Equatable { }
260
276
277
+ @available ( macOS 9999 , iOS 9999 , tvOS 9999 , watchOS 9999 , * ) // FIXME(availability-5.1)
261
278
extension CollectionDifference . Change : Hashable where ChangeElement: Hashable { }
262
279
263
- extension CollectionDifference : Hashable where ChangeElement: Hashable {
280
+ @available ( macOS 9999 , iOS 9999 , tvOS 9999 , watchOS 9999 , * ) // FIXME(availability-5.1)
281
+ extension CollectionDifference : Hashable where ChangeElement: Hashable { }
264
282
283
+ @available ( macOS 9999 , iOS 9999 , tvOS 9999 , watchOS 9999 , * ) // FIXME(availability-5.1)
284
+ extension CollectionDifference where ChangeElement: Hashable {
265
285
/// Infers which `ChangeElement`s have been both inserted and removed only
266
286
/// once and returns a new difference with those associations.
267
287
///
@@ -272,11 +292,11 @@ extension CollectionDifference: Hashable where ChangeElement: Hashable {
272
292
let removeDict : [ ChangeElement : Int ? ] = {
273
293
var res = [ ChangeElement: Int? ] ( minimumCapacity: Swift . min ( removals. count, insertions. count) )
274
294
for r in removals {
275
- let element = r. element
295
+ let element = r. _element
276
296
if res [ element] != . none {
277
297
res [ element] = . some( . none)
278
298
} else {
279
- res [ element] = . some( r. offset )
299
+ res [ element] = . some( r. _offset )
280
300
}
281
301
}
282
302
return res. filter { ( _, v) -> Bool in v != . none }
@@ -285,17 +305,17 @@ extension CollectionDifference: Hashable where ChangeElement: Hashable {
285
305
let insertDict : [ ChangeElement : Int ? ] = {
286
306
var res = [ ChangeElement: Int? ] ( minimumCapacity: Swift . min ( removals. count, insertions. count) )
287
307
for i in insertions {
288
- let element = i. element
308
+ let element = i. _element
289
309
if res [ element] != . none {
290
310
res [ element] = . some( . none)
291
311
} else {
292
- res [ element] = . some( i. offset )
312
+ res [ element] = . some( i. _offset )
293
313
}
294
314
}
295
315
return res. filter { ( _, v) -> Bool in v != . none }
296
316
} ( )
297
317
298
- return CollectionDifference . init ( validatedChanges : map ( { ( c: CollectionDifference < ChangeElement > . Change ) -> CollectionDifference < ChangeElement > . Change in
318
+ return CollectionDifference ( _validatedChanges : map ( { ( c: Change ) -> Change in
299
319
switch c {
300
320
case . remove( offset: let o, element: let e, associatedWith: _) :
301
321
if removeDict [ e] == nil {
@@ -317,16 +337,17 @@ extension CollectionDifference: Hashable where ChangeElement: Hashable {
317
337
}
318
338
}
319
339
340
+ @available ( macOS 9999 , iOS 9999 , tvOS 9999 , watchOS 9999 , * ) // FIXME(availability-5.1)
320
341
extension CollectionDifference . Change : Codable where ChangeElement: Codable {
321
- private enum CodingKeys : String , CodingKey {
342
+ private enum _CodingKeys : String , CodingKey {
322
343
case offset
323
344
case element
324
345
case associatedOffset
325
346
case isRemove
326
347
}
327
348
328
349
public init ( from decoder: Decoder ) throws {
329
- let values = try decoder. container ( keyedBy: CodingKeys . self)
350
+ let values = try decoder. container ( keyedBy: _CodingKeys . self)
330
351
let offset = try values. decode ( Int . self, forKey: . offset)
331
352
let element = try values. decode ( ChangeElement . self, forKey: . element)
332
353
let associatedOffset = try values. decode ( Int ? . self, forKey: . associatedOffset)
@@ -337,20 +358,21 @@ extension CollectionDifference.Change: Codable where ChangeElement: Codable {
337
358
self = . insert( offset: offset, element: element, associatedWith: associatedOffset)
338
359
}
339
360
}
340
-
361
+
341
362
public func encode( to encoder: Encoder ) throws {
342
- var container = encoder. container ( keyedBy: CodingKeys . self)
363
+ var container = encoder. container ( keyedBy: _CodingKeys . self)
343
364
switch self {
344
365
case . remove( _, _, _) :
345
366
try container. encode ( true , forKey: . isRemove)
346
367
case . insert( _, _, _) :
347
368
try container. encode ( false , forKey: . isRemove)
348
369
}
349
370
350
- try container. encode ( offset , forKey: . offset)
351
- try container. encode ( element , forKey: . element)
352
- try container. encode ( associatedOffset , forKey: . associatedOffset)
371
+ try container. encode ( _offset , forKey: . offset)
372
+ try container. encode ( _element , forKey: . element)
373
+ try container. encode ( _associatedOffset , forKey: . associatedOffset)
353
374
}
354
375
}
355
376
377
+ @available ( macOS 9999 , iOS 9999 , tvOS 9999 , watchOS 9999 , * ) // FIXME(availability-5.1)
356
378
extension CollectionDifference : Codable where ChangeElement: Codable { }
0 commit comments