Skip to content

Commit 59769ac

Browse files
committed
Add type erased holders for protocols.
1 parent 8c4d294 commit 59769ac

5 files changed

Lines changed: 329 additions & 2 deletions

File tree

Sources/AnyProcessor.swift

Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
/*
2+
* Copyright 2016 Robert Cottrell
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
import Foundation
18+
19+
/// A type-erased `Processor` type.
20+
///
21+
/// Forwards operations to an arbitrary underlying processor with the same
22+
/// `SubscribeTrype` and `PublishType` types, hiding the specifics of the
23+
/// underlying processor.
24+
public struct AnyProcessor<Subscribe, Publish>: Processor {
25+
/// The type of elements to be received.
26+
public typealias SubscribeType = Subscribe
27+
28+
/// The type of elements to be published.
29+
public typealias PublishType = Publish
30+
31+
/// The boxed processor which will receive forwarded calls.
32+
private let box: _AnyProcessorBoxBase<SubscribeType, PublishType>
33+
34+
/// Create a type erased wrapper around a processor.
35+
///
36+
/// - parameter box: The processor to receive operations.
37+
public init<P: Processor where P.SubscribeType == SubscribeType, P.PublishType == PublishType>(_ box: P) {
38+
self.box = _AnyProcessorBox(box)
39+
}
40+
41+
/// Forward `onSubscribe(subscription:)` to the boxed processor.
42+
public func onSubscribe(subscription: Subscription) {
43+
box.onSubscribe(subscription: subscription)
44+
}
45+
46+
/// Forward `onNext` to the boxed processor.
47+
public func onNext(element: SubscribeType) {
48+
box.onNext(element: element)
49+
}
50+
51+
/// Forward `onError(error:)` to the boxed processor.
52+
public func onError(error: ErrorProtocol) {
53+
box.onError(error: error)
54+
}
55+
56+
/// Forward `onComplete()` to the boxed processor.
57+
public func onComplete() {
58+
box.onComplete()
59+
}
60+
61+
/// Forward `subscribe(subscriber:)` to the boxed processor.
62+
public func subscribe<S: Subscriber where S.SubscribeType == PublishType>(subscriber: S) {
63+
box.subscribe(subscriber: subscriber)
64+
}
65+
66+
/// Erases type of the processor and returns the canonical processor.
67+
///
68+
/// - returns: type erased processor.
69+
public func asProcessor() -> AnyProcessor<SubscribeType, PublishType> {
70+
return self
71+
}
72+
}
73+
74+
public extension Processor {
75+
/// Erases type of the processor and returns the canonical processor.
76+
///
77+
/// - returns: type erased processor.
78+
public func asProcessor() -> AnyProcessor<SubscribeType, PublishType> {
79+
return AnyProcessor(self)
80+
}
81+
}
82+
83+
private class _AnyProcessorBox<P: Processor>: _AnyProcessorBoxBase<P.SubscribeType, P.PublishType> {
84+
let box: P
85+
86+
init(_ box: P) {
87+
self.box = box
88+
}
89+
90+
override func onSubscribe(subscription: Subscription) {
91+
box.onSubscribe(subscription: subscription)
92+
}
93+
94+
override func onNext(element: SubscribeType) {
95+
box.onNext(element: element)
96+
}
97+
98+
override func onError(error: ErrorProtocol) {
99+
box.onError(error: error)
100+
}
101+
102+
override func onComplete() {
103+
box.onComplete()
104+
}
105+
106+
override func subscribe<S: Subscriber where S.SubscribeType == PublishType>(subscriber: S) {
107+
box.subscribe(subscriber: subscriber)
108+
}
109+
}
110+
111+
private class _AnyProcessorBoxBase<Subscribe, Publish>: Processor {
112+
typealias SubscribeType = Subscribe
113+
typealias PublishType = Publish
114+
115+
func onSubscribe(subscription: Subscription) {
116+
fatalError()
117+
}
118+
119+
func onNext(element: SubscribeType) {
120+
fatalError()
121+
}
122+
123+
func onError(error: ErrorProtocol) {
124+
fatalError()
125+
}
126+
127+
func onComplete() {
128+
fatalError()
129+
}
130+
131+
func subscribe<S: Subscriber where S.SubscribeType == PublishType>(subscriber: S) {
132+
fatalError()
133+
}
134+
}

Sources/AnyPublisher.swift

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
/*
2+
* Copyright 2016 Robert Cottrell
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
import Foundation
18+
19+
/// A type-erased `Publisher` type.
20+
///
21+
/// Forwards operations to an arbitrary underlying publisher with the same
22+
/// `PublishType` type, hiding the specifics of the underlying publisher.
23+
public struct AnyPublisher<Publish>: Publisher {
24+
/// The type of elements to be published.
25+
public typealias PublishType = Publish
26+
27+
/// The boxed publisher which will receive forwarded calls.
28+
private let box: _AnyPublisherBoxBase<PublishType>
29+
30+
/// Create a type erased wrapper around a publisher.
31+
///
32+
/// - parameter box: The publisher to receive operations.
33+
public init<P: Publisher where P.PublishType == PublishType>(_ box: P) {
34+
self.box = _AnyPublisherBox(box)
35+
}
36+
37+
/// Forward `subscribe(subscriber:)` to the boxed publisher.
38+
public func subscribe<S: Subscriber where S.SubscribeType == PublishType>(subscriber: S) {
39+
box.subscribe(subscriber: subscriber)
40+
}
41+
42+
/// Erases type of the publisher and returns the canonical publisher.
43+
///
44+
/// - returns: type erased publisher.
45+
public func asPublisher() -> AnyPublisher<PublishType> {
46+
return self
47+
}
48+
}
49+
50+
public extension Publisher {
51+
/// Erases type of the publisher and returns the canonical publisher.
52+
///
53+
/// - returns: type erased publisher.
54+
public func asPublisher() -> AnyPublisher<PublishType> {
55+
return AnyPublisher(self)
56+
}
57+
}
58+
59+
private class _AnyPublisherBox<P: Publisher>: _AnyPublisherBoxBase<P.PublishType> {
60+
let box: P
61+
62+
init(_ box: P) {
63+
self.box = box
64+
}
65+
66+
override func subscribe<S: Subscriber where S.SubscribeType == PublishType>(subscriber: S) {
67+
box.subscribe(subscriber: subscriber)
68+
}
69+
}
70+
71+
private class _AnyPublisherBoxBase<Publish>: Publisher {
72+
typealias PublishType = Publish
73+
74+
func subscribe<S: Subscriber where S.SubscribeType == PublishType>(subscriber: S) {
75+
fatalError()
76+
}
77+
}

Sources/AnySubscriber.swift

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
/*
2+
* Copyright 2016 Robert Cottrell
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
import Foundation
18+
19+
/// A type-erased `Subscriber` type.
20+
///
21+
/// Forwards operations to an arbitrary underlying subscriber with the same
22+
/// `SubscribeTrype` type, hiding the specifics of the underlying subscriber.
23+
public struct AnySubscriber<Subscribe>: Subscriber {
24+
/// The type of elements to be received.
25+
public typealias SubscribeType = Subscribe
26+
27+
/// The boxed processor which will receive forwarded calls.
28+
private let box: _AnySubscriberBoxBase<SubscribeType>
29+
30+
/// Create a type erased wrapper around a subscriber.
31+
///
32+
/// - parameter box: The subscriber to receive operations.
33+
public init<S: Subscriber where S.SubscribeType == SubscribeType>(_ box: S) {
34+
self.box = _AnySubscriberBox(box)
35+
}
36+
37+
/// Forward `onSubscribe(subscription:)` to the boxed subscriber.
38+
public func onSubscribe(subscription: Subscription) {
39+
box.onSubscribe(subscription: subscription)
40+
}
41+
42+
/// Forward `onNext` to the boxed subscriber.
43+
public func onNext(element: SubscribeType) {
44+
box.onNext(element: element)
45+
}
46+
47+
/// Forward `onError(error:)` to the boxed subscriber.
48+
public func onError(error: ErrorProtocol) {
49+
box.onError(error: error)
50+
}
51+
52+
/// Forward `onComplete()` to the boxed subscriber.
53+
public func onComplete() {
54+
box.onComplete()
55+
}
56+
57+
/// Erases type of the subscriber and returns the canonical subscriber.
58+
///
59+
/// - returns: type erased subscriber.
60+
public func asSubscriber() -> AnySubscriber<SubscribeType> {
61+
return self
62+
}
63+
}
64+
65+
public extension Subscriber {
66+
/// Erases type of the subscriber and returns the canonical processor.
67+
///
68+
/// - returns: type erased subscriber.
69+
public func asSubscriber() -> AnySubscriber<SubscribeType> {
70+
return AnySubscriber(self)
71+
}
72+
}
73+
74+
private class _AnySubscriberBox<S: Subscriber>: _AnySubscriberBoxBase<S.SubscribeType> {
75+
let box: S
76+
77+
init(_ box: S) {
78+
self.box = box
79+
}
80+
81+
override func onSubscribe(subscription: Subscription) {
82+
box.onSubscribe(subscription: subscription)
83+
}
84+
85+
override func onNext(element: SubscribeType) {
86+
box.onNext(element: element)
87+
}
88+
89+
override func onError(error: ErrorProtocol) {
90+
box.onError(error: error)
91+
}
92+
93+
override func onComplete() {
94+
box.onComplete()
95+
}
96+
}
97+
98+
private class _AnySubscriberBoxBase<Subscribe>: Subscriber {
99+
typealias SubscribeType = Subscribe
100+
101+
func onSubscribe(subscription: Subscription) {
102+
fatalError()
103+
}
104+
105+
func onNext(element: SubscribeType) {
106+
fatalError()
107+
}
108+
109+
func onError(error: ErrorProtocol) {
110+
fatalError()
111+
}
112+
113+
func onComplete() {
114+
fatalError()
115+
}
116+
}

Sources/Publisher.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,5 +40,5 @@ public protocol Publisher {
4040
///
4141
/// - parameter subscriber: The `Subscriber` that will consume signals
4242
/// from this `Publisher`.
43-
func subscribe<T: Subscriber where T.SubscribeType == PublishType>(subscriber: T)
43+
func subscribe<S: Subscriber where S.SubscribeType == PublishType>(subscriber: S)
4444
}

Sources/Subscriber.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ import Foundation
3636
/// Demand can be signaled via `Subscription.request(count:)` whenever the
3737
/// `Subscriber` is capable of handling more.
3838
public protocol Subscriber {
39-
/// The type of element to be received.
39+
/// The type of elements to be received.
4040
associatedtype SubscribeType
4141

4242
/// Invoked after calling `Publisher.subscribe(subscriber:)`.

0 commit comments

Comments
 (0)