@@ -102,15 +102,15 @@ extension Chain2: Collection where Base1: Collection, Base2: Collection {
102
102
/// Converts an index of `Base1` to the corresponding `Index` by mapping
103
103
/// `base1.endIndex` to `base2.startIndex`.
104
104
@inlinable
105
- internal func convertIndex ( _ i: Base1 . Index ) -> Index {
105
+ internal func normalizeIndex ( _ i: Base1 . Index ) -> Index {
106
106
i == base1. endIndex ? Index ( second: base2. startIndex) : Index ( first: i)
107
107
}
108
108
109
109
@inlinable
110
110
public var startIndex : Index {
111
111
// if `base1` is empty, this will return `base2.startIndex` - if `base2` is
112
112
// also empty, this will correctly equal `base2.endIndex`
113
- convertIndex ( base1. startIndex)
113
+ normalizeIndex ( base1. startIndex)
114
114
}
115
115
116
116
@inlinable
@@ -133,109 +133,116 @@ extension Chain2: Collection where Base1: Collection, Base2: Collection {
133
133
switch i. position {
134
134
case let . first( i) :
135
135
assert ( i != base1. endIndex)
136
- return convertIndex ( base1. index ( after: i) )
136
+ return normalizeIndex ( base1. index ( after: i) )
137
137
case let . second( i) :
138
138
return Index ( second: base2. index ( after: i) )
139
139
}
140
140
}
141
141
142
142
@inlinable
143
- public func index( _ i: Index , offsetBy n: Int ) -> Index {
144
- if n == 0 { return i }
145
- return n > 0
146
- ? offsetForward ( i, by: n, limitedBy: endIndex) !
147
- : offsetBackward ( i, by: - n, limitedBy: startIndex) !
143
+ public func index( _ i: Index , offsetBy distance: Int ) -> Index {
144
+ guard distance != 0 else { return i }
145
+
146
+ return distance > 0
147
+ ? offsetForward ( i, by: distance)
148
+ : offsetBackward ( i, by: - distance)
148
149
}
149
-
150
+
150
151
@inlinable
151
152
public func index(
152
153
_ i: Index ,
153
- offsetBy n : Int ,
154
+ offsetBy distance : Int ,
154
155
limitedBy limit: Index
155
156
) -> Index ? {
156
- if n == 0 { return i }
157
- return n > 0
158
- ? offsetForward ( i, by: n, limitedBy: limit)
159
- : offsetBackward ( i, by: - n, limitedBy: limit)
157
+ if distance >= 0 {
158
+ return limit >= i
159
+ ? offsetForward ( i, by: distance, limitedBy: limit)
160
+ : offsetForward ( i, by: distance)
161
+ } else {
162
+ return limit <= i
163
+ ? offsetBackward ( i, by: - distance, limitedBy: limit)
164
+ : offsetBackward ( i, by: - distance)
165
+ }
166
+ }
167
+
168
+ @inlinable
169
+ internal func offsetForward( _ i: Index , by distance: Int ) -> Index {
170
+ guard let index = offsetForward ( i, by: distance, limitedBy: endIndex)
171
+ else { fatalError ( " Index is out of bounds " ) }
172
+ return index
173
+ }
174
+
175
+ @inlinable
176
+ internal func offsetBackward( _ i: Index , by distance: Int ) -> Index {
177
+ guard let index = offsetBackward ( i, by: distance, limitedBy: startIndex)
178
+ else { fatalError ( " Index is out of bounds " ) }
179
+ return index
160
180
}
161
181
162
182
@inlinable
163
183
internal func offsetForward(
164
- _ i: Index , by n : Int , limitedBy limit: Index
184
+ _ i: Index , by distance : Int , limitedBy limit: Index
165
185
) -> Index ? {
186
+ assert ( distance >= 0 )
187
+ assert ( limit >= i)
188
+
166
189
switch ( i. position, limit. position) {
167
190
case let ( . first( i) , . first( limit) ) :
168
- if limit >= i {
169
- // `limit` is relevant, so `base2` cannot be reached
170
- return base1. index ( i, offsetBy: n, limitedBy: limit)
171
- . map ( Index . init ( first: ) )
172
- } else if let j = base1. index ( i, offsetBy: n, limitedBy: base1. endIndex) {
173
- // the offset stays within the bounds of `base1`
174
- return convertIndex ( j)
175
- } else {
176
- // the offset overflows the bounds of `base1` by `n - d`
177
- let d = base1. distance ( from: i, to: base1. endIndex)
178
- return Index ( second: base2. index ( base2. startIndex, offsetBy: n - d) )
179
- }
191
+ return base1. index ( i, offsetBy: distance, limitedBy: limit)
192
+ . map ( Index . init ( first: ) )
180
193
181
194
case let ( . first( i) , . second( limit) ) :
182
- if let j = base1. index ( i, offsetBy: n , limitedBy: base1. endIndex) {
195
+ if let j = base1. index ( i, offsetBy: distance , limitedBy: base1. endIndex) {
183
196
// the offset stays within the bounds of `base1`
184
- return convertIndex ( j)
197
+ return normalizeIndex ( j)
185
198
} else {
186
199
// the offset overflows the bounds of `base1` by `n - d`
187
200
let d = base1. distance ( from: i, to: base1. endIndex)
188
- return base2. index ( base2. startIndex, offsetBy: n - d, limitedBy: limit)
201
+ return base2. index ( base2. startIndex, offsetBy: distance - d, limitedBy: limit)
189
202
. map ( Index . init ( second: ) )
190
203
}
191
204
192
- case let ( . second( i ) , . first) :
193
- // `limit` has no effect here
194
- return Index ( second : base2 . index ( i , offsetBy : n ) )
205
+ case ( . second, . first) :
206
+ // impossible because `limit >= i`
207
+ fatalError ( )
195
208
196
209
case let ( . second( i) , . second( limit) ) :
197
- return base2. index ( i, offsetBy: n , limitedBy: limit)
210
+ return base2. index ( i, offsetBy: distance , limitedBy: limit)
198
211
. map ( Index . init ( second: ) )
199
212
}
200
213
}
201
214
202
215
@inlinable
203
216
internal func offsetBackward(
204
- _ i: Index , by n : Int , limitedBy limit: Index
217
+ _ i: Index , by distance : Int , limitedBy limit: Index
205
218
) -> Index ? {
219
+ assert ( distance >= 0 )
220
+ assert ( limit <= i)
221
+
206
222
switch ( i. position, limit. position) {
207
223
case let ( . first( i) , . first( limit) ) :
208
- return base1. index ( i, offsetBy: - n , limitedBy: limit)
224
+ return base1. index ( i, offsetBy: - distance , limitedBy: limit)
209
225
. map ( Index . init ( first: ) )
210
226
211
- case let ( . first( i ) , . second) :
212
- // `limit` has no effect here
213
- return Index ( first : base1 . index ( i , offsetBy : - n ) )
227
+ case ( . first, . second) :
228
+ // impossible because `limit <= i`
229
+ fatalError ( )
214
230
215
231
case let ( . second( i) , . first( limit) ) :
216
- if let j = base2. index ( i, offsetBy: - n , limitedBy: base2. startIndex) {
232
+ if let j = base2. index ( i, offsetBy: - distance , limitedBy: base2. startIndex) {
217
233
// the offset stays within the bounds of `base2`
218
234
return Index ( second: j)
219
235
} else {
220
236
// the offset overflows the bounds of `base2` by `n - d`
221
237
let d = base2. distance ( from: base2. startIndex, to: i)
222
- return base1. index ( base1. endIndex, offsetBy: - ( n - d) , limitedBy: limit)
238
+ return base1. index ( base1. endIndex, offsetBy: - ( distance - d) , limitedBy: limit)
223
239
. map ( Index . init ( first: ) )
224
240
}
225
241
226
242
case let ( . second( i) , . second( limit) ) :
227
- if limit <= i {
228
- // `limit` is relevant, so `base1` cannot be reached
229
- return base2. index ( i, offsetBy: - n, limitedBy: limit)
230
- . map ( Index . init ( second: ) )
231
- } else if let j = base2. index ( i, offsetBy: - n, limitedBy: base2. startIndex) {
232
- // the offset stays within the bounds of `base2`
233
- return Index ( second: j)
234
- } else {
235
- // the offset overflows the bounds of `base2` by `n - d`
236
- let d = base2. distance ( from: base2. startIndex, to: i)
237
- return Index ( first: base1. index ( base1. endIndex, offsetBy: - ( n - d) ) )
238
- }
243
+ // `limit` is relevant, so `base1` cannot be reached
244
+ return base2. index ( i, offsetBy: - distance, limitedBy: limit)
245
+ . map ( Index . init ( second: ) )
239
246
}
240
247
}
241
248
0 commit comments