Skip to content

Instantly share code, notes, and snippets.

@DivineDominion
Last active September 7, 2023 06:06
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save DivineDominion/de85d2dc3d42f6ebfe29f1d35a3c7da3 to your computer and use it in GitHub Desktop.
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)
enum Select { case left, right }
}
struct _EitherPublisher<Left, Right, Select, Failure>: Publisher
where Select: Publisher, Select.Output == Either<Left.Output, Right.Output>.Select, Select.Failure == Failure,
Left: Publisher, Right: Publisher, Left.Failure == Right.Failure, Left.Failure == Failure
{
typealias Output = Either<Left.Output, Right.Output>
private let stream: Publishers.Map<Publishers.CombineLatest3<Select, Left, Right>, _EitherPublisher<Left, Right, Select, Failure>.Output>
init(_ select: Select, _ left: Left, _ right: Right) {
stream = Publishers
.CombineLatest3(select, left, right)
.map { (select: Select.Output, left: Left.Output, right: Right.Output) -> Output in
switch select {
case .left: return .left(left)
case .right: return .right(right)
}
}
}
func receive<S>(subscriber: S)
where S: Subscriber, S.Failure == Failure, S.Input == Output {
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