-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #8 from RougeWare/develop
Sync develop into master
- Loading branch information
Showing
6 changed files
with
243 additions
and
6 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,95 @@ | ||
// | ||
// Ranges or nil.swift | ||
// Safe Collection Access | ||
// | ||
// Created by Ben Leggiero on 2020-05-20. | ||
// Copyright © 2020 Ben Leggiero BH-1-PS. | ||
// | ||
|
||
import Foundation | ||
|
||
|
||
|
||
public extension RandomAccessCollection | ||
where Index: Strideable, | ||
Index.Stride: SignedInteger | ||
{ | ||
/// Safely access ranges in this collection. | ||
/// If the range you pass extends outside this collection, `nil` is returned. | ||
/// | ||
/// - Complexity: O(n) | ||
/// | ||
/// - Parameter range: A range of valid lower and upper indices of characters in the string. | ||
/// - Returns: The characters at the given index-range in this string, or `nil` if the given range is not contained | ||
/// within `0` (inclusive) and `count` (exclusive). | ||
@inlinable | ||
subscript(orNil range: ClosedRange<Index>) -> SubSequence? { | ||
return contains(allIn: range) | ||
? self[range] | ||
: nil | ||
} | ||
|
||
|
||
/// Safely access ranges in this collection. | ||
/// If the range you pass extends outside this collection, `nil` is returned. | ||
/// | ||
/// - Complexity: O(n) | ||
/// | ||
/// - Parameter range: A range of valid lower and upper indices of characters in the string. | ||
/// - Returns: The characters at the given index-range in this string, or `nil` if the given range is not contained | ||
/// within `0` (inclusive) and `count` (inclusive). | ||
@inlinable | ||
subscript(orNil range: Range<Index>) -> SubSequence? { | ||
return contains(allIn: range) | ||
? self[range] | ||
: nil | ||
} | ||
|
||
|
||
/// Safely access ranges in this collection. | ||
/// If the range you pass extends outside this collection, `nil` is returned. | ||
/// | ||
/// - Complexity: O(1) | ||
/// | ||
/// - Parameter range: A range of a valid lower index of characters in the string. | ||
/// - Returns: The characters at the given index-range in this string, or `nil` if the given range is not contained | ||
/// within `0` (inclusive) and `count` (exclusive). | ||
@inlinable | ||
subscript(orNil range: PartialRangeFrom<Index>) -> SubSequence? { | ||
return contains(index: range.lowerBound) | ||
? self[orNil: Range(uncheckedBounds: (lower: range.lowerBound, upper: endIndex))] | ||
: nil | ||
} | ||
|
||
|
||
/// Safely access ranges in this collection. | ||
/// If the range you pass extends outside this collection, `nil` is returned. | ||
/// | ||
/// - Complexity: O(1) | ||
/// | ||
/// - Parameter range: A range of a valid upper index of characters in the string. | ||
/// - Returns: The characters at the given index-range in this string, or `nil` if the given range's bound is not | ||
/// within `0` (inclusive) and `count` (inclusive). | ||
@inlinable | ||
subscript(orNil range: PartialRangeUpTo<Index>) -> SubSequence? { | ||
return contains(index: index(before: range.upperBound)) | ||
? self[orNil: startIndex ..< range.upperBound] | ||
: nil | ||
} | ||
|
||
|
||
/// Safely access ranges in this collection. | ||
/// If the range you pass extends outside this collection, `nil` is returned. | ||
/// | ||
/// - Complexity: O(1) | ||
/// | ||
/// - Parameter range: A range of a valid upper index of characters in the string. | ||
/// - Returns: The characters at the given index-range in this string, or `nil` if the given range's bound is not | ||
/// within `0` (inclusive) and `count` (exclusive). | ||
@inlinable | ||
subscript(orNil range: PartialRangeThrough<Index>) -> SubSequence? { | ||
return contains(index: range.upperBound) | ||
? self[orNil: startIndex ... range.upperBound] | ||
: nil | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,109 @@ | ||
// | ||
// RangesOrNilTests.swift | ||
// Safe Collection Access | ||
// | ||
// Created by Ben Leggiero on 2020-05-20. | ||
// Copyright © 2020 Ben Leggiero BH-1-PS. | ||
// | ||
|
||
import XCTest | ||
@testable import SafeCollectionAccess | ||
|
||
|
||
|
||
final class RangeOrNilTests: XCTestCase { | ||
|
||
let first5Fibonacci = [1, 1, 2, 3, 5] | ||
|
||
|
||
func testSubscriptOrNil_Range() { | ||
XCTAssertEqual(first5Fibonacci[orNil: 0..<5], [1, 1, 2, 3, 5]) | ||
XCTAssertEqual(first5Fibonacci[orNil: 1..<5], [1, 2, 3, 5]) | ||
XCTAssertEqual(first5Fibonacci[orNil: 2..<5], [2, 3, 5]) | ||
XCTAssertEqual(first5Fibonacci[orNil: 3..<5], [3, 5]) | ||
XCTAssertEqual(first5Fibonacci[orNil: 4..<5], [5]) | ||
XCTAssertEqual(first5Fibonacci[orNil: 5..<5], []) | ||
|
||
XCTAssertEqual(first5Fibonacci[orNil: 0..<5], [1, 1, 2, 3, 5]) | ||
XCTAssertEqual(first5Fibonacci[orNil: 0..<4], [1, 1, 2, 3]) | ||
XCTAssertEqual(first5Fibonacci[orNil: 0..<3], [1, 1, 2]) | ||
XCTAssertEqual(first5Fibonacci[orNil: 0..<2], [1, 1]) | ||
XCTAssertEqual(first5Fibonacci[orNil: 0..<1], [1]) | ||
XCTAssertEqual(first5Fibonacci[orNil: 0..<0], []) | ||
|
||
XCTAssertNil(first5Fibonacci[orNil: -1 ..< 0]) | ||
XCTAssertNil(first5Fibonacci[orNil: 0 ..< 6]) | ||
XCTAssertNil(first5Fibonacci[orNil: -20 ..< -10]) | ||
XCTAssertNil(first5Fibonacci[orNil: 7 ..< 9]) | ||
} | ||
|
||
|
||
func testSubscriptOrNil_ClosedRange() { | ||
XCTAssertEqual(first5Fibonacci[orNil: 0...4], [1, 1, 2, 3, 5]) | ||
XCTAssertEqual(first5Fibonacci[orNil: 1...4], [1, 2, 3, 5]) | ||
XCTAssertEqual(first5Fibonacci[orNil: 2...4], [2, 3, 5]) | ||
XCTAssertEqual(first5Fibonacci[orNil: 3...4], [3, 5]) | ||
XCTAssertEqual(first5Fibonacci[orNil: 4...4], [5]) | ||
|
||
XCTAssertEqual(first5Fibonacci[orNil: 0...4], [1, 1, 2, 3, 5]) | ||
XCTAssertEqual(first5Fibonacci[orNil: 0...3], [1, 1, 2, 3]) | ||
XCTAssertEqual(first5Fibonacci[orNil: 0...2], [1, 1, 2]) | ||
XCTAssertEqual(first5Fibonacci[orNil: 0...1], [1, 1]) | ||
XCTAssertEqual(first5Fibonacci[orNil: 0...0], [1]) | ||
|
||
XCTAssertNil(first5Fibonacci[orNil: -1 ... 0]) | ||
XCTAssertNil(first5Fibonacci[orNil: 0 ... 6]) | ||
XCTAssertNil(first5Fibonacci[orNil: -20 ... -10]) | ||
XCTAssertNil(first5Fibonacci[orNil: 7 ... 9]) | ||
} | ||
|
||
|
||
func testSubscriptOrNil_PartialRangeFrom() { | ||
XCTAssertEqual(first5Fibonacci[orNil: 0...], [1, 1, 2, 3, 5]) | ||
XCTAssertEqual(first5Fibonacci[orNil: 1...], [1, 2, 3, 5]) | ||
XCTAssertEqual(first5Fibonacci[orNil: 2...], [2, 3, 5]) | ||
XCTAssertEqual(first5Fibonacci[orNil: 3...], [3, 5]) | ||
XCTAssertEqual(first5Fibonacci[orNil: 4...], [5]) | ||
|
||
XCTAssertNil(first5Fibonacci[orNil: ( 5)...]) | ||
XCTAssertNil(first5Fibonacci[orNil: ( -1)...]) | ||
XCTAssertNil(first5Fibonacci[orNil: (-20)...]) | ||
XCTAssertNil(first5Fibonacci[orNil: ( 7)...]) | ||
} | ||
|
||
|
||
func testSubscriptOrNil_PartialRangeUpTo() { | ||
XCTAssertEqual(first5Fibonacci[orNil: ..<5], [1, 1, 2, 3, 5]) | ||
XCTAssertEqual(first5Fibonacci[orNil: ..<4], [1, 1, 2, 3]) | ||
XCTAssertEqual(first5Fibonacci[orNil: ..<3], [1, 1, 2]) | ||
XCTAssertEqual(first5Fibonacci[orNil: ..<2], [1, 1]) | ||
XCTAssertEqual(first5Fibonacci[orNil: ..<1], [1]) | ||
|
||
XCTAssertNil(first5Fibonacci[orNil: ..<( 0 )]) | ||
XCTAssertNil(first5Fibonacci[orNil: ..<( 6 )]) | ||
XCTAssertNil(first5Fibonacci[orNil: ..<(-10)]) | ||
XCTAssertNil(first5Fibonacci[orNil: ..<( 9 )]) | ||
} | ||
|
||
|
||
func testSubscriptOrNil_PartialRangeUpThrough() { | ||
XCTAssertEqual(first5Fibonacci[orNil: ...4], [1, 1, 2, 3, 5]) | ||
XCTAssertEqual(first5Fibonacci[orNil: ...3], [1, 1, 2, 3]) | ||
XCTAssertEqual(first5Fibonacci[orNil: ...2], [1, 1, 2]) | ||
XCTAssertEqual(first5Fibonacci[orNil: ...1], [1, 1]) | ||
XCTAssertEqual(first5Fibonacci[orNil: ...0], [1]) | ||
|
||
XCTAssertNil(first5Fibonacci[orNil: ...( 6 )]) | ||
XCTAssertNil(first5Fibonacci[orNil: ...(-10)]) | ||
XCTAssertNil(first5Fibonacci[orNil: ...( 9 )]) | ||
} | ||
|
||
|
||
static var allTests = [ | ||
("testSubscriptOrNil_Range", testSubscriptOrNil_Range), | ||
("testSubscriptOrNil_ClosedRange", testSubscriptOrNil_ClosedRange), | ||
("testSubscriptOrNil_PartialRangeFrom", testSubscriptOrNil_PartialRangeFrom), | ||
("testSubscriptOrNil_PartialRangeUpTo", testSubscriptOrNil_PartialRangeUpTo), | ||
("testSubscriptOrNil_PartialRangeUpThrough", testSubscriptOrNil_PartialRangeUpThrough), | ||
] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters