@@ -102,15 +102,15 @@ extension Chain2: Collection where Base1: Collection, Base2: Collection {
102102 /// Converts an index of `Base1` to the corresponding `Index` by mapping
103103 /// `base1.endIndex` to `base2.startIndex`.
104104 @inlinable
105- internal func convertIndex ( _ i: Base1 . Index ) -> Index {
105+ internal func normalizeIndex ( _ i: Base1 . Index ) -> Index {
106106 i == base1. endIndex ? Index ( second: base2. startIndex) : Index ( first: i)
107107 }
108108
109109 @inlinable
110110 public var startIndex : Index {
111111 // if `base1` is empty, this will return `base2.startIndex` - if `base2` is
112112 // also empty, this will correctly equal `base2.endIndex`
113- convertIndex ( base1. startIndex)
113+ normalizeIndex ( base1. startIndex)
114114 }
115115
116116 @inlinable
@@ -133,109 +133,116 @@ extension Chain2: Collection where Base1: Collection, Base2: Collection {
133133 switch i. position {
134134 case let . first( i) :
135135 assert ( i != base1. endIndex)
136- return convertIndex ( base1. index ( after: i) )
136+ return normalizeIndex ( base1. index ( after: i) )
137137 case let . second( i) :
138138 return Index ( second: base2. index ( after: i) )
139139 }
140140 }
141141
142142 @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)
148149 }
149-
150+
150151 @inlinable
151152 public func index(
152153 _ i: Index ,
153- offsetBy n : Int ,
154+ offsetBy distance : Int ,
154155 limitedBy limit: Index
155156 ) -> 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
160180 }
161181
162182 @inlinable
163183 internal func offsetForward(
164- _ i: Index , by n : Int , limitedBy limit: Index
184+ _ i: Index , by distance : Int , limitedBy limit: Index
165185 ) -> Index ? {
186+ assert ( distance >= 0 )
187+ assert ( limit >= i)
188+
166189 switch ( i. position, limit. position) {
167190 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: ) )
180193
181194 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) {
183196 // the offset stays within the bounds of `base1`
184- return convertIndex ( j)
197+ return normalizeIndex ( j)
185198 } else {
186199 // the offset overflows the bounds of `base1` by `n - d`
187200 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)
189202 . map ( Index . init ( second: ) )
190203 }
191204
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 ( )
195208
196209 case let ( . second( i) , . second( limit) ) :
197- return base2. index ( i, offsetBy: n , limitedBy: limit)
210+ return base2. index ( i, offsetBy: distance , limitedBy: limit)
198211 . map ( Index . init ( second: ) )
199212 }
200213 }
201214
202215 @inlinable
203216 internal func offsetBackward(
204- _ i: Index , by n : Int , limitedBy limit: Index
217+ _ i: Index , by distance : Int , limitedBy limit: Index
205218 ) -> Index ? {
219+ assert ( distance >= 0 )
220+ assert ( limit <= i)
221+
206222 switch ( i. position, limit. position) {
207223 case let ( . first( i) , . first( limit) ) :
208- return base1. index ( i, offsetBy: - n , limitedBy: limit)
224+ return base1. index ( i, offsetBy: - distance , limitedBy: limit)
209225 . map ( Index . init ( first: ) )
210226
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 ( )
214230
215231 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) {
217233 // the offset stays within the bounds of `base2`
218234 return Index ( second: j)
219235 } else {
220236 // the offset overflows the bounds of `base2` by `n - d`
221237 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)
223239 . map ( Index . init ( first: ) )
224240 }
225241
226242 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: ) )
239246 }
240247 }
241248
0 commit comments