Skip to content

Instantly share code, notes, and snippets.

@DivineDominion
Last active September 7, 2023 06:06
Show Gist options
  • Save DivineDominion/de85d2dc3d42f6ebfe29f1d35a3c7da3 to your computer and use it in GitHub Desktop.
Save DivineDominion/de85d2dc3d42f6ebfe29f1d35a3c7da3 to your computer and use it in GitHub Desktop.

Revisions

  1. DivineDominion revised this gist Sep 7, 2023. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion Combine.Publishers+Either.swift
    Original file line number Diff line number Diff line change
    @@ -9,7 +9,7 @@ enum Either<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
    Left: Publisher, Right: Publisher, Left.Failure == Right.Failure, Left.Failure == Failure
    {
    typealias Output = Either<Left.Output, Right.Output>

  2. DivineDominion revised this gist Sep 7, 2023. 1 changed file with 11 additions and 11 deletions.
    22 changes: 11 additions & 11 deletions Combine.Publishers+Either.swift
    Original file line number Diff line number Diff line change
    @@ -3,31 +3,31 @@ 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
    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: AnyPublisher<Either<Left, Right>, _Failure>
    private let stream: Publishers.Map<Publishers.CombineLatest3<Select, Left, Right>, _EitherPublisher<Left, Right, Select, Failure>.Output>

    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
    init(_ select: Select, _ left: Left, _ right: Right) {
    stream = Publishers
    .CombineLatest3(select, left, right)
    .map { (select: Select, left: Left, right: Right) -> Either<Left, Right> in
    .map { (select: Select.Output, left: Left.Output, right: Right.Output) -> Output 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 {
    where S: Subscriber, S.Failure == Failure, S.Input == Output {
    stream.receive(subscriber: subscriber)
    }
    }
  3. DivineDominion created this gist Sep 6, 2023.
    37 changes: 37 additions & 0 deletions Combine.Publishers+Either.swift
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,37 @@
    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
    }
    33 changes: 33 additions & 0 deletions _test.swift
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,33 @@
    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)