import Foundation public func map(_ f: @escaping(T) -> R) -> (Signal) -> Signal { return { signal in return Signal { subscriber in return signal.start(next: { next in subscriber.putNext(f(next)) }, error: { error in subscriber.putError(error) }, completed: { subscriber.putCompletion() }) } } } public func filter(_ f: @escaping(T) -> Bool) -> (Signal) -> Signal { return { signal in return Signal { subscriber in return signal.start(next: { next in if f(next) { subscriber.putNext(next) } }, error: { error in subscriber.putError(error) }, completed: { subscriber.putCompletion() }) } } } public func flatMap(_ f: @escaping (T) -> R) -> (Signal) -> Signal { return { signal in return Signal { subscriber in return signal.start(next: { next in if let next = next { subscriber.putNext(f(next)) } else { subscriber.putNext(nil) } }, error: { error in subscriber.putError(error) }, completed: { subscriber.putCompletion() }) } } } public func mapError(_ f: @escaping(E) -> R) -> (Signal) -> Signal { return { signal in return Signal { subscriber in return signal.start(next: { next in subscriber.putNext(next) }, error: { error in subscriber.putError(f(error)) }, completed: { subscriber.putCompletion() }) } } } public func castError(_ type: E.Type) -> (Signal) -> Signal { return { signal in return Signal { subscriber in return signal.start(next: { next in subscriber.putNext(next) }, error: { _ in }, completed: { subscriber.putCompletion() }) } } } private class DistinctUntilChangedContext { var value: T? } public func distinctUntilChanged(_ signal: Signal) -> Signal { return Signal { subscriber in let context = Atomic(value: DistinctUntilChangedContext()) return signal.start(next: { next in let pass = context.with { context -> Bool in if let value = context.value, value == next { return false } else { context.value = next return true } } if pass { subscriber.putNext(next) } }, error: { error in subscriber.putError(error) }, completed: { subscriber.putCompletion() }) } } public func distinctUntilChanged(isEqual: @escaping (T, T) -> Bool) -> (_ signal: Signal) -> Signal { return { signal in return Signal { subscriber in let context = Atomic(value: DistinctUntilChangedContext()) return signal.start(next: { next in let pass = context.with { context -> Bool in if let value = context.value, isEqual(value, next) { return false } else { context.value = next return true } } if pass { subscriber.putNext(next) } }, error: { error in subscriber.putError(error) }, completed: { subscriber.putCompletion() }) } } }