Add map and tryMap operator specializations for Map and TryMap
This commit is contained in:
committed by
Sergej Jaskiewicz
parent
94fe896784
commit
2c38417545
@@ -3687,20 +3687,6 @@ extension Publishers.Last : Equatable where Upstream : Equatable {
|
||||
public static func == (lhs: Publishers.Last<Upstream>, rhs: Publishers.Last<Upstream>) -> Bool
|
||||
}
|
||||
|
||||
extension Publishers.Map {
|
||||
|
||||
public func map<T>(_ transform: @escaping (Output) -> T) -> Publishers.Map<Upstream, T>
|
||||
|
||||
public func tryMap<T>(_ transform: @escaping (Output) throws -> T) -> Publishers.TryMap<Upstream, T>
|
||||
}
|
||||
|
||||
extension Publishers.TryMap {
|
||||
|
||||
public func map<T>(_ transform: @escaping (Output) -> T) -> Publishers.TryMap<Upstream, T>
|
||||
|
||||
public func tryMap<T>(_ transform: @escaping (Output) throws -> T) -> Publishers.TryMap<Upstream, T>
|
||||
}
|
||||
|
||||
extension Publishers.Sequence {
|
||||
|
||||
public func allSatisfy(_ predicate: (Publishers.Sequence<Elements, Failure>.Output) -> Bool) -> Publishers.Once<Bool, Failure>
|
||||
|
||||
@@ -66,22 +66,46 @@ extension Publishers {
|
||||
}
|
||||
|
||||
extension Publishers.Map {
|
||||
public func receive<SubscriberType: Subscriber>(subscriber: SubscriberType)
|
||||
where Output == SubscriberType.Input, SubscriberType.Failure == Upstream.Failure
|
||||
public func receive<Downstream: Subscriber>(subscriber: Downstream)
|
||||
where Output == Downstream.Input, Downstream.Failure == Upstream.Failure
|
||||
{
|
||||
let inner = Inner(downstream: subscriber, transform: catching(transform))
|
||||
upstream.receive(subscriber: inner)
|
||||
}
|
||||
|
||||
public func map<Result>(
|
||||
_ transform: @escaping (Output) -> Result
|
||||
) -> Publishers.Map<Upstream, Result> {
|
||||
return .init(upstream: upstream) { transform(self.transform($0)) }
|
||||
}
|
||||
|
||||
public func tryMap<Result>(
|
||||
_ transform: @escaping (Output) throws -> Result
|
||||
) -> Publishers.TryMap<Upstream, Result> {
|
||||
return .init(upstream: upstream) { try transform(self.transform($0)) }
|
||||
}
|
||||
}
|
||||
|
||||
extension Publishers.TryMap {
|
||||
|
||||
public func receive<SubscriberType: Subscriber>(subscriber: SubscriberType)
|
||||
where Output == SubscriberType.Input, SubscriberType.Failure == Error
|
||||
public func receive<Downstream: Subscriber>(subscriber: Downstream)
|
||||
where Output == Downstream.Input, Downstream.Failure == Error
|
||||
{
|
||||
let inner = Inner(downstream: subscriber, transform: catching(transform))
|
||||
upstream.receive(subscriber: inner)
|
||||
}
|
||||
|
||||
public func map<Result>(
|
||||
_ transform: @escaping (Output) -> Result
|
||||
) -> Publishers.TryMap<Upstream, Result> {
|
||||
return .init(upstream: upstream) { try transform(self.transform($0)) }
|
||||
}
|
||||
|
||||
public func tryMap<Result>(
|
||||
_ transform: @escaping (Output) throws -> Result
|
||||
) -> Publishers.TryMap<Upstream, Result> {
|
||||
return .init(upstream: upstream) { try transform(self.transform($0)) }
|
||||
}
|
||||
}
|
||||
|
||||
private class _Map<Upstream: Publisher, Downstream: Subscriber>
|
||||
|
||||
@@ -28,6 +28,13 @@ final class MapTests: XCTestCase {
|
||||
("testCancel", testCancel),
|
||||
("testCancelAlreadyCancelled", testCancelAlreadyCancelled),
|
||||
("testLifecycle", testLifecycle),
|
||||
("testMapOperatorSpecializationForMap", testMapOperatorSpecializationForMap),
|
||||
("testTryMapOperatorSpecializationForMap",
|
||||
testTryMapOperatorSpecializationForMap),
|
||||
("testMapOperatorSpecializationForTryMap",
|
||||
testMapOperatorSpecializationForTryMap),
|
||||
("testTryMapOperatorSpecializationForTryMap",
|
||||
testTryMapOperatorSpecializationForTryMap)
|
||||
]
|
||||
|
||||
func testEmpty() {
|
||||
@@ -281,4 +288,125 @@ final class MapTests: XCTestCase {
|
||||
try XCTUnwrap(subscription).cancel()
|
||||
XCTAssertEqual(deinitCounter, 0)
|
||||
}
|
||||
|
||||
func testMapOperatorSpecializationForMap() {
|
||||
|
||||
let tracking = TrackingSubscriberBase<Int, Never>(
|
||||
receiveSubscription: { $0.request(.unlimited) }
|
||||
)
|
||||
let publisher = PassthroughSubject<Int, Never>()
|
||||
|
||||
let map1 = publisher.map { $0 * 2 }
|
||||
let map2 = map1.map { $0 + 1 }
|
||||
|
||||
map2.subscribe(tracking)
|
||||
publisher.send(2)
|
||||
publisher.send(3)
|
||||
publisher.send(5)
|
||||
|
||||
XCTAssert(map1.upstream === map2.upstream)
|
||||
XCTAssertEqual(tracking.history, [.subscription(Subscriptions.empty),
|
||||
.value(5),
|
||||
.value(7),
|
||||
.value(11)])
|
||||
}
|
||||
|
||||
func testTryMapOperatorSpecializationForMap() {
|
||||
let tracking = TrackingSubscriberBase<Int, Error>(
|
||||
receiveSubscription: { $0.request(.unlimited) }
|
||||
)
|
||||
let publisher = PassthroughSubject<Int, Never>()
|
||||
|
||||
let map1 = publisher.map { $0 * 2 }
|
||||
|
||||
let tryMap2 = map1.tryMap { input -> Int in
|
||||
if input == 12 { throw TestingError.oops }
|
||||
return input + 1
|
||||
}
|
||||
|
||||
tryMap2.subscribe(tracking)
|
||||
publisher.send(2)
|
||||
publisher.send(3)
|
||||
publisher.send(5)
|
||||
|
||||
XCTAssert(map1.upstream === tryMap2.upstream)
|
||||
XCTAssertEqual(tracking.history, [.subscription(Subscriptions.empty),
|
||||
.value(5),
|
||||
.value(7),
|
||||
.value(11)])
|
||||
|
||||
publisher.send(6)
|
||||
|
||||
XCTAssertEqual(tracking.history, [.subscription(Subscriptions.empty),
|
||||
.value(5),
|
||||
.value(7),
|
||||
.value(11),
|
||||
.completion(.failure(TestingError.oops))])
|
||||
}
|
||||
|
||||
func testMapOperatorSpecializationForTryMap() {
|
||||
let tracking = TrackingSubscriberBase<Int, Error>(
|
||||
receiveSubscription: { $0.request(.unlimited) }
|
||||
)
|
||||
let publisher = PassthroughSubject<Int, Never>()
|
||||
|
||||
let tryMap1 = publisher.tryMap { input -> Int in
|
||||
if input == 6 { throw TestingError.oops }
|
||||
return input * 2
|
||||
}
|
||||
|
||||
let tryMap2 = tryMap1.map { $0 + 1 }
|
||||
|
||||
tryMap2.subscribe(tracking)
|
||||
publisher.send(2)
|
||||
publisher.send(3)
|
||||
publisher.send(5)
|
||||
|
||||
XCTAssert(tryMap1.upstream === tryMap2.upstream)
|
||||
XCTAssertEqual(tracking.history, [.subscription(Subscriptions.empty),
|
||||
.value(5),
|
||||
.value(7),
|
||||
.value(11)])
|
||||
|
||||
publisher.send(6)
|
||||
|
||||
XCTAssertEqual(tracking.history, [.subscription(Subscriptions.empty),
|
||||
.value(5),
|
||||
.value(7),
|
||||
.value(11),
|
||||
.completion(.failure(TestingError.oops))])
|
||||
}
|
||||
|
||||
func testTryMapOperatorSpecializationForTryMap() {
|
||||
let tracking = TrackingSubscriberBase<Int, Error>(
|
||||
receiveSubscription: { $0.request(.unlimited) }
|
||||
)
|
||||
let publisher = PassthroughSubject<Int, Never>()
|
||||
|
||||
let tryMap1 = publisher.tryMap { input -> Int in
|
||||
if input == 6 { throw TestingError.oops }
|
||||
return input * 2
|
||||
}
|
||||
|
||||
let tryMap2 = tryMap1.tryMap { $0 + 1 }
|
||||
|
||||
tryMap2.subscribe(tracking)
|
||||
publisher.send(2)
|
||||
publisher.send(3)
|
||||
publisher.send(5)
|
||||
|
||||
XCTAssert(tryMap1.upstream === tryMap2.upstream)
|
||||
XCTAssertEqual(tracking.history, [.subscription(Subscriptions.empty),
|
||||
.value(5),
|
||||
.value(7),
|
||||
.value(11)])
|
||||
|
||||
publisher.send(6)
|
||||
|
||||
XCTAssertEqual(tracking.history, [.subscription(Subscriptions.empty),
|
||||
.value(5),
|
||||
.value(7),
|
||||
.value(11),
|
||||
.completion(.failure(TestingError.oops))])
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user