Skip to content

Instantly share code, notes, and snippets.

@DivineDominion
Last active September 7, 2023 06:06
Show Gist options
  • Select an option

  • Save DivineDominion/de85d2dc3d42f6ebfe29f1d35a3c7da3 to your computer and use it in GitHub Desktop.

Select an option

Save DivineDominion/de85d2dc3d42f6ebfe29f1d35a3c7da3 to your computer and use it in GitHub Desktop.
Combine.Publishers.Either implementation
import Combine
let selectSubject = PassthroughSubject<_EitherPublisher<String, Int, Never>.Select, Never>()
let leftSubject = PassthroughSubject<String, Never>()
let rightSubject = PassthroughSubject<Int, Never>()
var cancellables = Set<AnyCancellable>()
Combine.Publishers
.Either(
selectSubject.print("select"),
leftSubject.print("left"),
rightSubject.print("right")
)
.print("either")
.sink(receiveCompletion: {
print("completion", $0)
}, receiveValue: {
print("value", $0)
})
.store(in: &cancellables)
leftSubject.send("a")
rightSubject.send(1)
leftSubject.send("b")
rightSubject.send(2)
selectSubject.send(.left)
leftSubject.send("c")
rightSubject.send(3)
leftSubject.send("d")
leftSubject.send("e")
selectSubject.send(.right)
leftSubject.send("f")
rightSubject.send(5)
import Combine
enum Either<Left, Right> {
case left(Left)
case right(Right)
}
struct _EitherPublisher<Left, Right, _Failure: Error>: Publisher {
enum Select { case left, right }
typealias Output = Either<Left, Right>
typealias Failure = _Failure
private let stream: AnyPublisher<Either<Left, Right>, _Failure>
init<S, L, R>(_ select: S, _ left: L, _ right: R)
where S: Publisher, S.Output == Select, L: Publisher, L.Output == Left, R: Publisher, R.Output == Right, L.Failure == R.Failure, L.Failure == _Failure, S.Failure == _Failure {
self.stream = Publishers
.CombineLatest3(select, left, right)
.map { (select: Select, left: Left, right: Right) -> Either<Left, Right> in
switch select {
case .left: return .left(left)
case .right: return .right(right)
}
}
.eraseToAnyPublisher()
}
func receive<S>(subscriber: S)
where S: Subscriber, _Failure == S.Failure, Either<Left, Right> == S.Input {
stream.receive(subscriber: subscriber)
}
}
extension Combine.Publishers {
typealias Either = _EitherPublisher
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment