Skip to content

Instantly share code, notes, and snippets.

@sidepelican
Last active April 14, 2021 09:36
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 sidepelican/a2045cb614c603cd2fcf6ada22cf509a to your computer and use it in GitHub Desktop.
Save sidepelican/a2045cb614c603cd2fcf6ada22cf509a to your computer and use it in GitHub Desktop.
import Combine
@_functionBuilder
struct FlatMapBuilder {
static func buildBlock<C: Publisher>(_ component: C) -> C
{
component
}
static func buildEither<F: Publisher, S: Publisher>(first component: F) -> EitherPublisher<F, S>
where
F.Output == S.Output,
F.Failure == S.Failure
{
.left(component)
}
static func buildEither<F: Publisher, S: Publisher>(first component: F) -> EitherPublisher<Publishers.SetFailureType<F, S.Failure>, S>
where
F.Output == S.Output,
F.Failure == Never
{
.left(component.setFailureType(to: S.Failure.self))
}
static func buildEither<F: Publisher, S: Publisher>(second component: S) -> EitherPublisher<F, S>
where
F.Output == S.Output,
F.Failure == S.Failure
{
.right(component)
}
static func buildEither<F: Publisher, S: Publisher>(first component: S) -> EitherPublisher<F, Publishers.SetFailureType<S, F.Failure>>
where
F.Output == S.Output,
S.Failure == Never
{
.right(component.setFailureType(to: F.Failure.self))
}
}
enum EitherPublisher<L: Publisher, R: Publisher>: Publisher
where
L.Output == R.Output, L.Failure == R.Failure
{
typealias Output = L.Output
typealias Failure = L.Failure
case left(L)
case right(R)
func receive<S>(subscriber: S) where S : Subscriber, Self.Failure == S.Failure, Self.Output == S.Input {
switch self {
case .left(let value):
value.receive(subscriber: subscriber)
case .right(let value):
value.receive(subscriber: subscriber)
}
}
}
extension Publisher {
func flatMapBuild<O, P>(
@FlatMapBuilder _ builder: @escaping (Self.Output) -> P
) -> Publishers.FlatMap<P, Self>
where O == P.Output, Failure == P.Failure, P: Publisher
{
flatMap(builder)
}
func flatMapBuild<O, P>(
@FlatMapBuilder _ builder: @escaping (Self.Output) -> P
) -> Publishers.FlatMap<Publishers.SetFailureType<P, Self.Failure>, Self>
where O == P.Output, P: Publisher, P.Failure == Never
{
flatMap(builder)
}
}
extension Publisher where Failure == Never {
func flatMapBuild<O, P>(
@FlatMapBuilder _ builder: @escaping (Self.Output) -> P
) -> Publishers.FlatMap<P, Publishers.SetFailureType<Self, P.Failure>>
where O == P.Output, P: Publisher
{
flatMap(builder)
}
func flatMapBuild<O, P>(
@FlatMapBuilder _ builder: @escaping (Self.Output) -> P
) -> Publishers.FlatMap<P, Self>
where O == P.Output, P: Publisher, P.Failure == Never
{
flatMap(builder)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment