@@ -167,3 +167,77 @@ public extension RandomAccessCollection {
167167 }
168168 }
169169}
170+
171+
172+
173+ // MARK: - `nil` or `index(before:)`/`index(after:)`
174+
175+ public extension BidirectionalCollection {
176+
177+ /// Returns the position immediately after the given index, or `nil` if there is none.
178+ ///
179+ /// The successor of an index must be well defined. For an index `i` into an immutable
180+ /// collection `c`, calling `c.index(after: i)` returns the same index every
181+ /// time.
182+ ///
183+ /// - Parameter i: An index of the collection.
184+ /// - Returns: The index value immediately after `i`, or `nil` if such an index wouldn't be in the collection.
185+ func indexOrNil( after i: Index ) -> Index ? {
186+ guard i < endIndex else { return nil }
187+ return index ( after: i)
188+ }
189+
190+
191+ /// Replaces the given index with its successor, or `nil` if there is none.
192+ ///
193+ /// `i` is set to `nil` if the resulting index wouldn't be in the collection.
194+ ///
195+ /// - Parameter i: An index of the collection.
196+ func formIndexOrNil( after i: inout Index ? ) {
197+ guard let nonNilIndex = i else { return }
198+ i = indexOrNil ( after: nonNilIndex)
199+ }
200+
201+
202+ /// Returns the position immediately before the given index, or `nil` if there is none.
203+ ///
204+ /// - Parameter i: An index of the collection.
205+ /// - Returns: The index value immediately before `i`, or `nil` if such an index wouldn't be in the collection.
206+ func indexOrNil( before i: Index ) -> Index ? {
207+ guard i > startIndex else { return nil }
208+ return index ( before: i)
209+ }
210+
211+
212+ /// Replaces the given index with its predecessor, or `nil` if there is none.
213+ ///
214+ /// `i` is set to `nil` if the resulting index wouldn't be in the collection.
215+ ///
216+ /// - Parameter i: An index of the collection.
217+ func formIndexOrNil( before i: inout Index ? ) {
218+ guard let nonNilIndex = i else { return }
219+ i = indexOrNil ( before: nonNilIndex)
220+ }
221+
222+
223+ /// Returns an index that is the specified distance from the given index, or `nil` if there isn't one.
224+ ///
225+ /// - Parameters:
226+ /// - i: A valid index of the collection.
227+ /// - distance: The distance to offset `i`. `distance` must not be negative unless the collection conforms to the `BidirectionalCollection` protocol.
228+ /// - Returns: An index offset by `distance` from the index `i`.
229+ /// If `distance` is positive, this is the same value as the result of `distance` calls to `index(after:)`.
230+ /// If `distance` is negative, this is the same value as the result of `abs(distance)` calls to `index(before:)`.
231+ /// If the index which would be `distance` from `i` would lie outside this collection, this returns `nil`.
232+ func indexOrNil( _ i: Index , offsetBy distance: Int ) -> Index ? {
233+ if distance > 0 {
234+ index ( i, offsetBy: distance, limitedBy: endIndex)
235+ }
236+ else if distance < 0 {
237+ index ( i, offsetBy: distance, limitedBy: startIndex)
238+ }
239+ else {
240+ i
241+ }
242+ }
243+ }
0 commit comments