Skip to content

Commit 45b6a15

Browse files
authored
Feature: Option to enable auto-throwing of Result failures (#7)
Signed-off-by: James Hall <[email protected]>
1 parent 830769e commit 45b6a15

File tree

5 files changed

+65
-8
lines changed

5 files changed

+65
-8
lines changed

QLoop.xcodeproj/project.pbxproj

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,10 @@
138138
DCC759272241D04100B4750E /* QLoop+ConvenienceInitTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DCC759262241D04100B4750E /* QLoop+ConvenienceInitTests.swift */; };
139139
DCC759282241D04100B4750E /* QLoop+ConvenienceInitTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DCC759262241D04100B4750E /* QLoop+ConvenienceInitTests.swift */; };
140140
DCC759292241D04100B4750E /* QLoop+ConvenienceInitTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DCC759262241D04100B4750E /* QLoop+ConvenienceInitTests.swift */; };
141+
DCFACAEB22D826C5004D6D7A /* Result+ErrorGettable.swift in Sources */ = {isa = PBXBuildFile; fileRef = DCFACAEA22D826C5004D6D7A /* Result+ErrorGettable.swift */; };
142+
DCFACAEC22D826C5004D6D7A /* Result+ErrorGettable.swift in Sources */ = {isa = PBXBuildFile; fileRef = DCFACAEA22D826C5004D6D7A /* Result+ErrorGettable.swift */; };
143+
DCFACAED22D826C5004D6D7A /* Result+ErrorGettable.swift in Sources */ = {isa = PBXBuildFile; fileRef = DCFACAEA22D826C5004D6D7A /* Result+ErrorGettable.swift */; };
144+
DCFACAEE22D826C5004D6D7A /* Result+ErrorGettable.swift in Sources */ = {isa = PBXBuildFile; fileRef = DCFACAEA22D826C5004D6D7A /* Result+ErrorGettable.swift */; };
141145
/* End PBXBuildFile section */
142146

143147
/* Begin PBXContainerItemProxy section */
@@ -250,6 +254,7 @@
250254
DCD9D7C3223DDE0900BBDEE2 /* QLoop.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = QLoop.md; sourceTree = "<group>"; };
251255
DCD9D7C4223DDF8900BBDEE2 /* QLParallelSegment.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = QLParallelSegment.md; sourceTree = "<group>"; };
252256
DCD9D7C5223DE0C800BBDEE2 /* QLSerialSegment.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = QLSerialSegment.md; sourceTree = "<group>"; };
257+
DCFACAEA22D826C5004D6D7A /* Result+ErrorGettable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Result+ErrorGettable.swift"; sourceTree = "<group>"; };
253258
/* End PBXFileReference section */
254259

255260
/* Begin PBXFrameworksBuildPhase section */
@@ -386,6 +391,7 @@
386391
DC6FAF5D222F4EF5008BB070 /* QLAnchor.swift */,
387392
DC5E449E224AFC2B0007FEAD /* QLAnchor+ConvenienceInit.swift */,
388393
DC8F2B58223342E000277F70 /* QLPath.swift */,
394+
DCFACAEA22D826C5004D6D7A /* Result+ErrorGettable.swift */,
389395
DCF860BF2239D02B0018C1A1 /* Common */,
390396
DC374A322231F28A006F1272 /* Iterating */,
391397
DCA1FD232230C8E5006015BD /* Segment */,
@@ -740,6 +746,7 @@
740746
DCA1FD1F2230C8DB006015BD /* QLSegment.swift in Sources */,
741747
DC374A372231F2AD006F1272 /* QLoopIteratorContinueNilMax.swift in Sources */,
742748
DCA1FD0C22303D22006015BD /* QLoop.swift in Sources */,
749+
DCFACAEB22D826C5004D6D7A /* Result+ErrorGettable.swift in Sources */,
743750
DC413D23223B191300000480 /* QLCommon.swift in Sources */,
744751
DC6FAF5E222F4EF5008BB070 /* QLAnchor.swift in Sources */,
745752
DC374A412231F361006F1272 /* QLoopIteratorContinueNil.swift in Sources */,
@@ -764,6 +771,7 @@
764771
DCA1FD202230C8DB006015BD /* QLSegment.swift in Sources */,
765772
DC374A342231F2AD006F1272 /* QLoopIteratorContinueNilMax.swift in Sources */,
766773
DCA1FD0D22303D22006015BD /* QLoop.swift in Sources */,
774+
DCFACAEC22D826C5004D6D7A /* Result+ErrorGettable.swift in Sources */,
767775
DC413D24223B191300000480 /* QLCommon.swift in Sources */,
768776
DC6FAF5F222F4EF5008BB070 /* QLAnchor.swift in Sources */,
769777
DC374A3E2231F361006F1272 /* QLoopIteratorContinueNil.swift in Sources */,
@@ -788,6 +796,7 @@
788796
DCA1FD212230C8DB006015BD /* QLSegment.swift in Sources */,
789797
DC374A352231F2AD006F1272 /* QLoopIteratorContinueNilMax.swift in Sources */,
790798
DCA1FD0E22303D22006015BD /* QLoop.swift in Sources */,
799+
DCFACAED22D826C5004D6D7A /* Result+ErrorGettable.swift in Sources */,
791800
DC413D25223B191300000480 /* QLCommon.swift in Sources */,
792801
DC6FAF60222F4EF5008BB070 /* QLAnchor.swift in Sources */,
793802
DC374A3F2231F361006F1272 /* QLoopIteratorContinueNil.swift in Sources */,
@@ -812,6 +821,7 @@
812821
DCA1FD222230C8DB006015BD /* QLSegment.swift in Sources */,
813822
DC374A362231F2AD006F1272 /* QLoopIteratorContinueNilMax.swift in Sources */,
814823
DCA1FD0F22303D22006015BD /* QLoop.swift in Sources */,
824+
DCFACAEE22D826C5004D6D7A /* Result+ErrorGettable.swift in Sources */,
815825
DC413D26223B191300000480 /* QLCommon.swift in Sources */,
816826
DC6FAF61222F4EF5008BB070 /* QLAnchor.swift in Sources */,
817827
DC374A402231F361006F1272 /* QLoopIteratorContinueNil.swift in Sources */,

Sources/QLoop/Common/QLCommon.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ public struct QLCommon {
1111
return false
1212
#endif
1313
}()
14+
15+
public static var autoThrowResultFailures: Bool = true
1416
}
1517
}
1618

Sources/QLoop/QLAnchor.swift

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@ public final class QLAnchor<Input>: AnyAnchor {
88
public typealias OnChange = (Input?)->()
99
public typealias OnError = (Error)->()
1010

11-
lazy var inputQueue = DispatchQueue(label: "\(self).inputQueue")
11+
lazy var inputQueue = DispatchQueue(label: "\(self).inputQueue",
12+
qos: .userInitiated)
1213

1314
public required init(onChange: @escaping OnChange,
1415
onError: @escaping OnError) {
@@ -24,8 +25,14 @@ public final class QLAnchor<Input>: AnyAnchor {
2425
}
2526
set {
2627
inputQueue.sync { self._value = newValue }
27-
DispatchQueue.main.async {
28-
self.onChange(newValue)
28+
if QLCommon.Config.Anchor.autoThrowResultFailures,
29+
let errGettable = newValue as? ErrorGettable,
30+
let err = errGettable.getError() {
31+
self.error = err
32+
} else {
33+
DispatchQueue.main.async {
34+
self.onChange(newValue)
35+
}
2936
}
3037

3138
if (QLCommon.Config.Anchor.releaseValues) {
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
internal protocol ErrorGettable {
2+
func getError() -> Error?
3+
}
4+
5+
extension Result: ErrorGettable {
6+
func getError() -> Error? {
7+
if case let .failure(err) = self {
8+
return err
9+
}
10+
return nil
11+
}
12+
}

Tests/QLoopTests/QLAnchorTests.swift

Lines changed: 31 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,21 +21,48 @@ final class QLAnchorTests: XCTestCase {
2121
func test_when_input_set_then_it_invokes_onChange() {
2222
var received: Int = -1
2323
let expect = expectation(description: "should set")
24-
2524
let subject = QLAnchor<Int>(onChange: { received = $0!; expect.fulfill() })
25+
2626
subject.value = 99
2727

2828
wait(for: [expect], timeout: 8.0)
2929
XCTAssertEqual(received, 99)
3030
}
3131

32+
func test_when_input_set_is_result_error_then_it_invokes_onError_and_not_onChange() {
33+
var receivedInput: Result<Int, Error>? = nil
34+
var receivedError: Error? = nil
35+
let expect = expectation(description: "should error")
36+
let subject = QLAnchor<Result<Int, Error>>(onChange: { receivedInput = $0; expect.fulfill() },
37+
onError: { receivedError = $0; expect.fulfill() })
38+
39+
subject.value = .failure(QLCommon.Error.Unknown)
40+
41+
wait(for: [expect], timeout: 8.0)
42+
XCTAssertNil(receivedInput)
43+
XCTAssertNotNil(receivedError)
44+
}
45+
46+
func test_when_input_set_is_result_value_then_it_invokes_onChange_and_not_onError_like_normal() {
47+
var receivedInput: Result<Int, Error>? = nil
48+
var receivedError: Error? = nil
49+
let expect = expectation(description: "should value")
50+
let subject = QLAnchor<Result<Int, Error>>(onChange: { receivedInput = $0; expect.fulfill() },
51+
onError: { receivedError = $0; expect.fulfill() })
52+
53+
subject.value = .success(11)
54+
55+
wait(for: [expect], timeout: 8.0)
56+
XCTAssertNotNil(receivedInput)
57+
XCTAssertNil(receivedError)
58+
}
59+
3260
func test_when_error_set_then_it_invokes_onError() {
3361
var receivedError: Error? = nil
3462
let expect = expectation(description: "should set")
35-
3663
let subject = QLAnchor<Int>(onChange: { _ in },
3764
onError: { receivedError = $0; expect.fulfill() })
38-
subject.onChange(nil)
65+
3966
subject.error = QLCommon.Error.Unknown
4067

4168
wait(for: [expect], timeout: 8.0)
@@ -45,10 +72,9 @@ final class QLAnchorTests: XCTestCase {
4572
func test_when_error_set_nil_then_it_invokes_onError_with_ErrorThrownButNotSet() {
4673
var receivedError: Error? = nil
4774
let expect = expectation(description: "should set")
48-
4975
let subject = QLAnchor<Int>(onChange: { _ in },
5076
onError: { receivedError = $0; expect.fulfill() })
51-
subject.onChange(nil)
77+
5278
subject.error = nil
5379

5480
wait(for: [expect], timeout: 8.0)

0 commit comments

Comments
 (0)