Skip to content

Commit d7f60d9

Browse files
authored
New observer abstraction for future backpressure support and decluttered stack traces (#799)
* Subscriber * /Subscriber/Observer/g; Create the `Operators` namespace.
1 parent 04d406a commit d7f60d9

File tree

11 files changed

+222
-93
lines changed

11 files changed

+222
-93
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ PlaygroundUtility.remap
2323
# SwiftPM
2424
.build
2525
Packages
26+
.swiftpm
2627

2728
# Carthage
2829
Carthage/Build

ReactiveSwift.xcodeproj/project.pbxproj

Lines changed: 72 additions & 10 deletions
Large diffs are not rendered by default.

Sources/Event.swift

Lines changed: 32 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -205,75 +205,29 @@ extension Signal.Event: EventProtocol {
205205
// This operator performs side effect upon interruption.
206206

207207
extension Signal.Event {
208-
internal typealias Transformation<U, E: Swift.Error> = (@escaping Signal<U, E>.Observer.Action, Lifetime) -> Signal<Value, Error>.Observer.Action
208+
internal typealias Transformation<U, E: Swift.Error> = (ReactiveSwift.Observer<U, E>, Lifetime) -> ReactiveSwift.Observer<Value, Error>
209209

210210
internal static func filter(_ isIncluded: @escaping (Value) -> Bool) -> Transformation<Value, Error> {
211-
return { action, _ in
212-
return { event in
213-
switch event {
214-
case let .value(value):
215-
if isIncluded(value) {
216-
action(.value(value))
217-
}
218-
219-
case .completed:
220-
action(.completed)
221-
222-
case let .failed(error):
223-
action(.failed(error))
224-
225-
case .interrupted:
226-
action(.interrupted)
227-
}
228-
}
211+
return { downstream, _ in
212+
Operators.Filter(downstream: downstream, predicate: isIncluded)
229213
}
230214
}
231215

232216
internal static func compactMap<U>(_ transform: @escaping (Value) -> U?) -> Transformation<U, Error> {
233-
return { action, _ in
234-
return { event in
235-
switch event {
236-
case let .value(value):
237-
if let newValue = transform(value) {
238-
action(.value(newValue))
239-
}
240-
241-
case .completed:
242-
action(.completed)
243-
244-
case let .failed(error):
245-
action(.failed(error))
246-
247-
case .interrupted:
248-
action(.interrupted)
249-
}
250-
}
217+
return { downstream, _ in
218+
Operators.CompactMap(downstream: downstream, transform: transform)
251219
}
252220
}
253221

254222
internal static func map<U>(_ transform: @escaping (Value) -> U) -> Transformation<U, Error> {
255223
return { action, _ in
256-
return { event in
257-
switch event {
258-
case let .value(value):
259-
action(.value(transform(value)))
260-
261-
case .completed:
262-
action(.completed)
263-
264-
case let .failed(error):
265-
action(.failed(error))
266-
267-
case .interrupted:
268-
action(.interrupted)
269-
}
270-
}
224+
Operators.Map(downstream: action, transform: transform)
271225
}
272226
}
273227

274228
internal static func mapError<E>(_ transform: @escaping (Error) -> E) -> Transformation<Value, E> {
275229
return { action, _ in
276-
return { event in
230+
return Signal.Observer { event in
277231
switch event {
278232
case let .value(value):
279233
action(.value(value))
@@ -293,7 +247,7 @@ extension Signal.Event {
293247

294248
internal static var materialize: Transformation<Signal<Value, Error>.Event, Never> {
295249
return { action, _ in
296-
return { event in
250+
return Signal.Observer { event in
297251
action(.value(event))
298252

299253
switch event {
@@ -312,7 +266,7 @@ extension Signal.Event {
312266

313267
internal static var materializeResults: Transformation<Result<Value, Error>, Never> {
314268
return { action, _ in
315-
return { event in
269+
return Signal.Observer { event in
316270
switch event {
317271
case .value(let value):
318272
action(.value(Result(success: value)))
@@ -333,7 +287,7 @@ extension Signal.Event {
333287

334288
internal static func attemptMap<U>(_ transform: @escaping (Value) -> Result<U, Error>) -> Transformation<U, Error> {
335289
return { action, _ in
336-
return { event in
290+
return Signal.Observer { event in
337291
switch event {
338292
case let .value(value):
339293
switch transform(value) {
@@ -382,7 +336,7 @@ extension Signal.Event {
382336
return { action, _ in
383337
var taken = 0
384338

385-
return { event in
339+
return Signal.Observer { event in
386340
guard let value = event.value else {
387341
action(event)
388342
return
@@ -405,7 +359,7 @@ extension Signal.Event {
405359
var buffer: [Value] = []
406360
buffer.reserveCapacity(count)
407361

408-
return { event in
362+
return Signal.Observer { event in
409363
switch event {
410364
case let .value(value):
411365
// To avoid exceeding the reserved capacity of the buffer,
@@ -430,7 +384,7 @@ extension Signal.Event {
430384

431385
internal static func take(while shouldContinue: @escaping (Value) -> Bool) -> Transformation<Value, Error> {
432386
return { action, _ in
433-
return { event in
387+
return Signal.Observer { event in
434388
if let value = event.value, !shouldContinue(value) {
435389
action(.completed)
436390
} else {
@@ -446,7 +400,7 @@ extension Signal.Event {
446400
return { action, _ in
447401
var skipped = 0
448402

449-
return { event in
403+
return Signal.Observer { event in
450404
if case .value = event, skipped < count {
451405
skipped += 1
452406
} else {
@@ -460,7 +414,7 @@ extension Signal.Event {
460414
return { action, _ in
461415
var isSkipping = true
462416

463-
return { event in
417+
return Signal.Observer { event in
464418
switch event {
465419
case let .value(value):
466420
isSkipping = isSkipping && shouldContinue(value)
@@ -479,7 +433,7 @@ extension Signal.Event {
479433
extension Signal.Event where Value: EventProtocol, Error == Never {
480434
internal static var dematerialize: Transformation<Value.Value, Value.Error> {
481435
return { action, _ in
482-
return { event in
436+
return Signal.Observer { event in
483437
switch event {
484438
case let .value(innerEvent):
485439
action(innerEvent.event)
@@ -501,7 +455,7 @@ extension Signal.Event where Value: EventProtocol, Error == Never {
501455
extension Signal.Event where Value: ResultProtocol, Error == Never {
502456
internal static var dematerializeResults: Transformation<Value.Success, Value.Failure> {
503457
return { action, _ in
504-
return { event in
458+
return Signal.Observer { event in
505459
let event = event.map { $0.result }
506460

507461
switch event {
@@ -577,7 +531,7 @@ extension Signal.Event {
577531
return { action, _ in
578532
let state = CollectState<Value>()
579533

580-
return { event in
534+
return Signal.Observer { event in
581535
switch event {
582536
case let .value(value):
583537
state.append(value)
@@ -603,7 +557,7 @@ extension Signal.Event {
603557
return { action, _ in
604558
let state = CollectState<Value>()
605559

606-
return { event in
560+
return Signal.Observer { event in
607561
switch event {
608562
case let .value(value):
609563
if shouldEmit(state.values, value) {
@@ -633,7 +587,7 @@ extension Signal.Event {
633587
return { action, _ in
634588
var previous = initial
635589

636-
return { event in
590+
return Signal.Observer { event in
637591
switch event {
638592
case let .value(value):
639593
if let previous = previous {
@@ -655,7 +609,7 @@ extension Signal.Event {
655609
return { action, _ in
656610
var previous: Value?
657611

658-
return { event in
612+
return Signal.Observer { event in
659613
switch event {
660614
case let .value(value):
661615
if let previous = previous, isEquivalent(previous, value) {
@@ -674,7 +628,7 @@ extension Signal.Event {
674628
return { action, _ in
675629
var seenValues: Set<Identity> = []
676630

677-
return { event in
631+
return Signal.Observer { event in
678632
switch event {
679633
case let .value(value):
680634
let identity = transform(value)
@@ -694,7 +648,7 @@ extension Signal.Event {
694648
return { action, _ in
695649
var accumulator = initialResult
696650

697-
return { event in
651+
return Signal.Observer { event in
698652
switch event {
699653
case let .value(value):
700654
nextPartialResult(&accumulator, value)
@@ -729,7 +683,7 @@ extension Signal.Event {
729683
return { action, _ in
730684
var accumulator = initialState
731685

732-
return { event in
686+
return Signal.Observer { event in
733687
switch event {
734688
case let .value(value):
735689
let output = next(&accumulator, value)
@@ -761,7 +715,7 @@ extension Signal.Event {
761715
}
762716
}
763717

764-
return { event in
718+
return Signal.Observer { event in
765719
scheduler.schedule {
766720
if !lifetime.hasEnded {
767721
action(event)
@@ -786,7 +740,7 @@ extension Signal.Event {
786740
}
787741
}
788742

789-
return { event in
743+
return Signal.Observer { event in
790744
switch event {
791745
case let .value(value):
792746
// Schedule only when there is no prior outstanding value.
@@ -828,7 +782,7 @@ extension Signal.Event {
828782
}
829783
}
830784

831-
return { event in
785+
return Signal.Observer { event in
832786
switch event {
833787
case .failed, .interrupted:
834788
scheduler.schedule {
@@ -859,7 +813,7 @@ extension Signal.Event {
859813
scheduler.schedule { action(.interrupted) }
860814
}
861815

862-
return { event in
816+
return Signal.Observer { event in
863817
guard let value = event.value else {
864818
schedulerDisposable.inner = scheduler.schedule {
865819
action(event)
@@ -901,7 +855,7 @@ extension Signal.Event {
901855
scheduler.schedule { action(.interrupted) }
902856
}
903857

904-
return { event in
858+
return Signal.Observer { event in
905859
switch event {
906860
case let .value(value):
907861
state.modify { state in
@@ -960,7 +914,7 @@ extension Signal.Event {
960914
scheduler.schedule { action(.interrupted) }
961915
}
962916

963-
return { event in
917+
return Signal.Observer { event in
964918
switch event {
965919
case let .value(value):
966920
state.modify { $0.values.append(value) }
@@ -1016,7 +970,7 @@ private struct ThrottleState<Value> {
1016970
extension Signal.Event where Error == Never {
1017971
internal static func promoteError<F>(_: F.Type) -> Transformation<Value, F> {
1018972
return { action, _ in
1019-
return { event in
973+
return Signal.Observer { event in
1020974
switch event {
1021975
case let .value(value):
1022976
action(.value(value))
@@ -1035,7 +989,7 @@ extension Signal.Event where Error == Never {
1035989
extension Signal.Event where Value == Never {
1036990
internal static func promoteValue<U>(_: U.Type) -> Transformation<U, Error> {
1037991
return { action, _ in
1038-
return { event in
992+
return Signal.Observer { event in
1039993
action(event.promoteValue())
1040994
}
1041995
}

Sources/Observers/CompactMap.swift

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
extension Operators {
2+
internal final class CompactMap<InputValue, OutputValue, Error: Swift.Error>: Observer<InputValue, Error> {
3+
let downstream: Observer<OutputValue, Error>
4+
let transform: (InputValue) -> OutputValue?
5+
6+
init(downstream: Observer<OutputValue, Error>, transform: @escaping (InputValue) -> OutputValue?) {
7+
self.downstream = downstream
8+
self.transform = transform
9+
}
10+
11+
override func receive(_ value: InputValue) {
12+
if let output = transform(value) {
13+
downstream.receive(output)
14+
}
15+
}
16+
17+
override func terminate(_ termination: Termination<Error>) {
18+
downstream.terminate(termination)
19+
}
20+
}
21+
}

Sources/Observers/Filter.swift

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
extension Operators {
2+
internal final class Filter<Value, Error: Swift.Error>: Observer<Value, Error> {
3+
let downstream: Observer<Value, Error>
4+
let predicate: (Value) -> Bool
5+
6+
init(downstream: Observer<Value, Error>, predicate: @escaping (Value) -> Bool) {
7+
self.downstream = downstream
8+
self.predicate = predicate
9+
}
10+
11+
override func receive(_ value: Value) {
12+
if predicate(value) {
13+
downstream.receive(value)
14+
}
15+
}
16+
17+
override func terminate(_ termination: Termination<Error>) {
18+
downstream.terminate(termination)
19+
}
20+
}
21+
}

Sources/Observers/Map.swift

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
extension Operators {
2+
internal final class Map<InputValue, OutputValue, Error: Swift.Error>: Observer<InputValue, Error> {
3+
let downstream: Observer<OutputValue, Error>
4+
let transform: (InputValue) -> OutputValue
5+
6+
init(downstream: Observer<OutputValue, Error>, transform: @escaping (InputValue) -> OutputValue) {
7+
self.downstream = downstream
8+
self.transform = transform
9+
}
10+
11+
override func receive(_ value: InputValue) {
12+
downstream.receive(transform(value))
13+
}
14+
15+
override func terminate(_ termination: Termination<Error>) {
16+
downstream.terminate(termination)
17+
}
18+
}
19+
}

0 commit comments

Comments
 (0)