Skip to content

Commit 6c533b1

Browse files
authored
Add case path for optional chaining (#141)
* Test resolution * Add case path for optional chaining
1 parent 45d8ed7 commit 6c533b1

File tree

2 files changed

+27
-0
lines changed

2 files changed

+27
-0
lines changed

Sources/CasePaths/Optional+CasePathable.swift

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
extension Optional: CasePathable {
2+
@dynamicMemberLookup
23
public struct AllCasePaths {
34
/// A case path to the absence of a value.
45
public var none: AnyCasePath<Optional, Void> {
@@ -21,6 +22,21 @@ extension Optional: CasePathable {
2122
}
2223
)
2324
}
25+
26+
/// A case path to an optional-chained value.
27+
public subscript<Member>(
28+
dynamicMember keyPath: KeyPath<Wrapped.AllCasePaths, AnyCasePath<Wrapped, Member>>
29+
) -> AnyCasePath<Optional, Member?>
30+
where Wrapped: CasePathable {
31+
let casePath = Wrapped.allCasePaths[keyPath: keyPath]
32+
return AnyCasePath(
33+
embed: { $0.map(casePath.embed) },
34+
extract: {
35+
guard case let .some(value) = $0 else { return nil }
36+
return casePath.extract(from: value)
37+
}
38+
)
39+
}
2440
}
2541

2642
public static var allCasePaths: AllCasePaths {

Tests/CasePathsTests/CasePathsTests.swift

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,13 @@ final class CasePathsTests: XCTestCase {
2525
let buzzPath3 = \Fizz.Cases.buzz
2626
XCTAssertNotEqual(buzzPath1, buzzPath3)
2727
XCTAssertEqual(buzzPath2, buzzPath3)
28+
XCTAssertEqual(ifLet(state: \Fizz.buzz, action: \Fizz.Cases.buzz), 42)
29+
XCTAssertEqual(ifLet(state: \Fizz.buzz, action: \Foo.Cases.bar), nil)
30+
let fizzBuzzPath1: CaseKeyPath<Fizz, Int?> = \Fizz.Cases.buzz.fizzBuzz.int
31+
let fizzBuzzPath2: CaseKeyPath<Fizz, Int> = \Fizz.Cases.buzz.fizzBuzz.int
32+
let fizzBuzzPath3 = \Fizz.Cases.buzz.fizzBuzz.int
33+
XCTAssertNotEqual(fizzBuzzPath1, fizzBuzzPath3)
34+
XCTAssertEqual(fizzBuzzPath2, fizzBuzzPath3)
2835
#endif
2936
}
3037

@@ -180,4 +187,8 @@ final class CasePathsTests: XCTestCase {
180187
@CasePathable @dynamicMemberLookup enum FizzBuzz: Equatable {
181188
case int(Int)
182189
}
190+
191+
func ifLet<A, B, C, D>(state: KeyPath<A, B?>, action: CaseKeyPath<C, D?>) -> Int? { 42 }
192+
@_disfavoredOverload
193+
func ifLet<A, B, C, D>(state: KeyPath<A, B?>, action: CaseKeyPath<C, D>) -> Int? { nil }
183194
#endif

0 commit comments

Comments
 (0)