Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
76 changes: 76 additions & 0 deletions Sources/SafeCollectionAccess/Safe Collection Access.swift
Original file line number Diff line number Diff line change
Expand Up @@ -167,3 +167,79 @@ public extension RandomAccessCollection {
}
}
}



// MARK: - `nil` or `index(before:)`/`index(after:)`

public extension BidirectionalCollection {

/// Returns the position immediately after the given index, or `nil` if there is none.
///
/// The successor of an index must be well defined. For an index `i` into an immutable collection `c`, calling `c.index(after: i)` returns the same index every time.
///
/// - Parameter i: An index of the collection.
/// - Returns: The index value immediately after `i`, or `nil` if such an index wouldn't be in the collection.
func indexOrNil(after i: Index) -> Index? {
guard i < endIndex else { return nil }
return index(after: i)
}


/// Replaces the given index with its successor, or `nil` if there is none.
///
/// If you pass `nil` for `i`, this returns immediately because there's nothing after nothing.
/// If the resulting index wouldn't be in the collection, then `i` is set to `nil`.
///
/// - Parameter i: An index of the collection.
func formIndexOrNil(after i: inout Index?) {
guard let nonNilIndex = i else { return }
i = indexOrNil(after: nonNilIndex)
}


/// Returns the position immediately before the given index, or `nil` if there is none.
///
/// - Parameter i: An index of the collection.
/// - Returns: The index value immediately before `i`, or `nil` if such an index wouldn't be in the collection.
func indexOrNil(before i: Index) -> Index? {
guard i > startIndex else { return nil }
return index(before: i)
}


/// Replaces the given index with its predecessor, or `nil` if there is none.
///
/// If you pass `nil` for `i`, this returns immediately because there's nothing before nothing.
/// If the resulting index wouldn't be in the collection, then `i` is set to `nil`.
///
/// - Parameter i: An index of the collection.
func formIndexOrNil(before i: inout Index?) {
guard let nonNilIndex = i else { return }
i = indexOrNil(before: nonNilIndex)
}


/// Returns an index that is the specified distance from the given index, or `nil` if there isn't one.
///
/// - Parameters:
/// - i: A valid index of the collection.
/// - distance: The distance to offset `i`.
/// `distance` may be negative.
///
/// - Returns: An index offset by `distance` from the index `i`.
/// If `distance` is positive, this is the same value as the result of `distance` calls to `index(after:)`.
/// If `distance` is negative, this is the same value as the result of `abs(distance)` calls to `index(before:)`.
/// If the index which would be `distance` from `i` would lie outside this collection, this returns `nil`.
func indexOrNil(_ i: Index, offsetBy distance: Int) -> Index? {
if distance > 0 {
index(i, offsetBy: distance, limitedBy: endIndex)
}
else if distance < 0 {
index(i, offsetBy: distance, limitedBy: startIndex)
}
else {
i
}
}
}