import Foundation public func map<T, E, R>(_ f: @escaping(T) -> R) -> (Signal<T, E>) -> Signal<R, E> { return { signal in return Signal<R, E> { subscriber in return signal.start(next: { next in subscriber.putNext(f(next)) }, error: { error in subscriber.putError(error) }, completed: { subscriber.putCompletion() }) } } } public func filter<T, E>(_ f: @escaping(T) -> Bool) -> (Signal<T, E>) -> Signal<T, E> { return { signal in return Signal<T, E> { 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<T, E, R>(_ f: @escaping (T) -> R) -> (Signal<T?, E>) -> Signal<R?, E> { return { signal in return Signal<R?, E> { 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<T, E, R>(_ f: @escaping(E) -> R) -> (Signal<T, E>) -> Signal<T, R> { return { signal in return Signal<T, R> { subscriber in return signal.start(next: { next in subscriber.putNext(next) }, error: { error in subscriber.putError(f(error)) }, completed: { subscriber.putCompletion() }) } } } public func castError<T, E>(_ type: E.Type) -> (Signal<T, NoError>) -> Signal<T, E> { return { signal in return Signal<T, E> { subscriber in return signal.start(next: { next in subscriber.putNext(next) }, error: { _ in }, completed: { subscriber.putCompletion() }) } } } private class DistinctUntilChangedContext<T> { var value: T? } public func distinctUntilChanged<T: Equatable, E>(_ signal: Signal<T, E>) -> Signal<T, E> { return Signal { subscriber in let context = Atomic(value: DistinctUntilChangedContext<T>()) 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<T, E>(isEqual: @escaping (T, T) -> Bool) -> (_ signal: Signal<T, E>) -> Signal<T, E> { return { signal in return Signal { subscriber in let context = Atomic(value: DistinctUntilChangedContext<T>()) 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() }) } } }