@@ -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,47 +213,60 @@ public struct CollectionDifference<ChangeElement> {
207
213
/// }
208
214
/// }
209
215
/// ```
210
- extension CollectionDifference : Collection {
211
- public typealias Element = CollectionDifference < ChangeElement > . Change
216
+ extension CollectionDifference : Collection {
217
+ public typealias Element = Change
212
218
213
- // Opaque index type is isomorphic to Int
214
- public struct Index : Comparable , Hashable {
215
- public static func < ( lhs: CollectionDifference < ChangeElement > . Index , rhs: CollectionDifference < ChangeElement > . Index ) -> Bool {
216
- return lhs. i < rhs. i
217
- }
218
-
219
- let i : Int
220
- init ( _ index: Int ) {
221
- i = index
219
+ public struct Index {
220
+ // Opaque index type is isomorphic to Int
221
+ internal let _offset : Int
222
+
223
+ internal init ( _offset offset: Int ) {
224
+ _offset = offset
222
225
}
223
226
}
224
227
225
- public var startIndex : CollectionDifference < ChangeElement > . Index {
226
- return Index ( 0 )
228
+ public var startIndex : Index {
229
+ return Index ( _offset : 0 )
227
230
}
228
231
229
- public var endIndex : CollectionDifference < ChangeElement > . Index {
230
- return Index ( removals. count + insertions. count)
232
+ public var endIndex : Index {
233
+ return Index ( _offset : removals. count + insertions. count)
231
234
}
232
235
233
- public func index( after index: CollectionDifference < ChangeElement > . Index ) -> CollectionDifference < ChangeElement > . Index {
234
- return Index ( index. i + 1 )
236
+ public func index( after index: Index ) -> Index {
237
+ return Index ( _offset : index. _offset + 1 )
235
238
}
236
239
237
- public subscript( position: CollectionDifference < ChangeElement > . Index ) -> Element {
238
- return position. i < removals. count ? removals [ removals. count - ( position. i + 1 ) ] : insertions [ position. i - removals. count]
240
+ public subscript( position: Index ) -> Element {
241
+ if position. _offset < removals. count {
242
+ return removals [ removals. count - ( position. _offset + 1 ) ]
243
+ }
244
+ return insertions [ position. _offset - removals. count]
239
245
}
240
246
241
- public func index( before index: CollectionDifference < ChangeElement > . Index ) -> CollectionDifference < ChangeElement > . Index {
242
- return Index ( index. i - 1 )
247
+ public func index( before index: Index ) -> Index {
248
+ return Index ( _offset : index. _offset - 1 )
243
249
}
244
250
245
- public func formIndex( _ index: inout CollectionDifference < ChangeElement > . Index , offsetBy distance: Int ) {
246
- index = Index ( index. i + distance)
251
+ public func formIndex( _ index: inout Index , offsetBy distance: Int ) {
252
+ index = Index ( _offset : index. _offset + distance)
247
253
}
248
254
249
- public func distance( from start: CollectionDifference < ChangeElement > . Index , to end: CollectionDifference < ChangeElement > . Index ) -> Int {
250
- return end. i - start. i
255
+ public func distance( from start: Index , to end: Index ) -> Int {
256
+ return end. _offset - start. _offset
257
+ }
258
+ }
259
+
260
+ extension CollectionDifference . Index : Equatable { } // synthesized
261
+
262
+ extension CollectionDifference . Index : Hashable { } // synthesized
263
+
264
+ extension CollectionDifference . Index : Comparable {
265
+ public static func < (
266
+ lhs: CollectionDifference . Index ,
267
+ rhs: CollectionDifference . Index
268
+ ) -> Bool {
269
+ return lhs. _offset < rhs. _offset
251
270
}
252
271
}
253
272
@@ -257,8 +276,9 @@ extension CollectionDifference: Equatable where ChangeElement: Equatable {}
257
276
258
277
extension CollectionDifference . Change : Hashable where ChangeElement: Hashable { }
259
278
260
- extension CollectionDifference : Hashable where ChangeElement: Hashable {
279
+ extension CollectionDifference : Hashable where ChangeElement: Hashable { }
261
280
281
+ extension CollectionDifference where ChangeElement: Hashable {
262
282
/// Infers which `ChangeElement`s have been both inserted and removed only
263
283
/// once and returns a new difference with those associations.
264
284
///
@@ -269,11 +289,11 @@ extension CollectionDifference: Hashable where ChangeElement: Hashable {
269
289
let removeDict : [ ChangeElement : Int ? ] = {
270
290
var res = [ ChangeElement: Int? ] ( minimumCapacity: Swift . min ( removals. count, insertions. count) )
271
291
for r in removals {
272
- let element = r. element
292
+ let element = r. _element
273
293
if res [ element] != . none {
274
294
res [ element] = . some( . none)
275
295
} else {
276
- res [ element] = . some( r. offset )
296
+ res [ element] = . some( r. _offset )
277
297
}
278
298
}
279
299
return res. filter { ( _, v) -> Bool in v != . none }
@@ -282,17 +302,17 @@ extension CollectionDifference: Hashable where ChangeElement: Hashable {
282
302
let insertDict : [ ChangeElement : Int ? ] = {
283
303
var res = [ ChangeElement: Int? ] ( minimumCapacity: Swift . min ( removals. count, insertions. count) )
284
304
for i in insertions {
285
- let element = i. element
305
+ let element = i. _element
286
306
if res [ element] != . none {
287
307
res [ element] = . some( . none)
288
308
} else {
289
- res [ element] = . some( i. offset )
309
+ res [ element] = . some( i. _offset )
290
310
}
291
311
}
292
312
return res. filter { ( _, v) -> Bool in v != . none }
293
313
} ( )
294
314
295
- return CollectionDifference . init ( validatedChanges : map ( { ( c: CollectionDifference < ChangeElement > . Change ) -> CollectionDifference < ChangeElement > . Change in
315
+ return CollectionDifference ( _validatedChanges : map ( { ( c: Change ) -> Change in
296
316
switch c {
297
317
case . remove( offset: let o, element: let e, associatedWith: _) :
298
318
if removeDict [ e] == nil {
@@ -315,15 +335,15 @@ extension CollectionDifference: Hashable where ChangeElement: Hashable {
315
335
}
316
336
317
337
extension CollectionDifference . Change : Codable where ChangeElement: Codable {
318
- private enum CodingKeys : String , CodingKey {
338
+ private enum _CodingKeys : String , CodingKey {
319
339
case offset
320
340
case element
321
341
case associatedOffset
322
342
case isRemove
323
343
}
324
344
325
345
public init ( from decoder: Decoder ) throws {
326
- let values = try decoder. container ( keyedBy: CodingKeys . self)
346
+ let values = try decoder. container ( keyedBy: _CodingKeys . self)
327
347
let offset = try values. decode ( Int . self, forKey: . offset)
328
348
let element = try values. decode ( ChangeElement . self, forKey: . element)
329
349
let associatedOffset = try values. decode ( Int ? . self, forKey: . associatedOffset)
@@ -336,17 +356,17 @@ extension CollectionDifference.Change: Codable where ChangeElement: Codable {
336
356
}
337
357
338
358
public func encode( to encoder: Encoder ) throws {
339
- var container = encoder. container ( keyedBy: CodingKeys . self)
359
+ var container = encoder. container ( keyedBy: _CodingKeys . self)
340
360
switch self {
341
361
case . remove( _, _, _) :
342
362
try container. encode ( true , forKey: . isRemove)
343
363
case . insert( _, _, _) :
344
364
try container. encode ( false , forKey: . isRemove)
345
365
}
346
366
347
- try container. encode ( offset , forKey: . offset)
348
- try container. encode ( element , forKey: . element)
349
- try container. encode ( associatedOffset , forKey: . associatedOffset)
367
+ try container. encode ( _offset , forKey: . offset)
368
+ try container. encode ( _element , forKey: . element)
369
+ try container. encode ( _associatedOffset , forKey: . associatedOffset)
350
370
}
351
371
}
352
372
0 commit comments