Add PromiseKit dependency
- Added PromiseKit dependency
This commit is contained in:
201
Carthage/Checkouts/PromiseKit/Sources/Guarantee.swift
vendored
Normal file
201
Carthage/Checkouts/PromiseKit/Sources/Guarantee.swift
vendored
Normal file
@@ -0,0 +1,201 @@
|
||||
import class Foundation.Thread
|
||||
import Dispatch
|
||||
|
||||
/**
|
||||
A `Guarantee` is a functional abstraction around an asynchronous operation that cannot error.
|
||||
- See: `Thenable`
|
||||
*/
|
||||
public class Guarantee<T>: Thenable {
|
||||
let box: Box<T>
|
||||
|
||||
fileprivate init(box: SealedBox<T>) {
|
||||
self.box = box
|
||||
}
|
||||
|
||||
/// Returns a `Guarantee` sealed with the provided value.
|
||||
public static func value(_ value: T) -> Guarantee<T> {
|
||||
return .init(box: SealedBox(value: value))
|
||||
}
|
||||
|
||||
/// Returns a pending `Guarantee` that can be resolved with the provided closure’s parameter.
|
||||
public init(resolver body: (@escaping(T) -> Void) -> Void) {
|
||||
box = EmptyBox()
|
||||
body(box.seal)
|
||||
}
|
||||
|
||||
/// - See: `Thenable.pipe`
|
||||
public func pipe(to: @escaping(Result<T>) -> Void) {
|
||||
pipe{ to(.fulfilled($0)) }
|
||||
}
|
||||
|
||||
func pipe(to: @escaping(T) -> Void) {
|
||||
switch box.inspect() {
|
||||
case .pending:
|
||||
box.inspect {
|
||||
switch $0 {
|
||||
case .pending(let handlers):
|
||||
handlers.append(to)
|
||||
case .resolved(let value):
|
||||
to(value)
|
||||
}
|
||||
}
|
||||
case .resolved(let value):
|
||||
to(value)
|
||||
}
|
||||
}
|
||||
|
||||
/// - See: `Thenable.result`
|
||||
public var result: Result<T>? {
|
||||
switch box.inspect() {
|
||||
case .pending:
|
||||
return nil
|
||||
case .resolved(let value):
|
||||
return .fulfilled(value)
|
||||
}
|
||||
}
|
||||
|
||||
init(_: PMKUnambiguousInitializer) {
|
||||
box = EmptyBox()
|
||||
}
|
||||
|
||||
/// Returns a tuple of a pending `Guarantee` and a function that resolves it.
|
||||
public class func pending() -> (guarantee: Guarantee<T>, resolve: (T) -> Void) {
|
||||
return { ($0, $0.box.seal) }(Guarantee<T>(.pending))
|
||||
}
|
||||
}
|
||||
|
||||
public extension Guarantee {
|
||||
@discardableResult
|
||||
func done(on: DispatchQueue? = conf.Q.return, flags: DispatchWorkItemFlags? = nil, _ body: @escaping(T) -> Void) -> Guarantee<Void> {
|
||||
let rg = Guarantee<Void>(.pending)
|
||||
pipe { (value: T) in
|
||||
on.async(flags: flags) {
|
||||
body(value)
|
||||
rg.box.seal(())
|
||||
}
|
||||
}
|
||||
return rg
|
||||
}
|
||||
|
||||
func get(on: DispatchQueue? = conf.Q.return, flags: DispatchWorkItemFlags? = nil, _ body: @escaping (T) -> Void) -> Guarantee<T> {
|
||||
return map(on: on, flags: flags) {
|
||||
body($0)
|
||||
return $0
|
||||
}
|
||||
}
|
||||
|
||||
func map<U>(on: DispatchQueue? = conf.Q.map, flags: DispatchWorkItemFlags? = nil, _ body: @escaping(T) -> U) -> Guarantee<U> {
|
||||
let rg = Guarantee<U>(.pending)
|
||||
pipe { value in
|
||||
on.async(flags: flags) {
|
||||
rg.box.seal(body(value))
|
||||
}
|
||||
}
|
||||
return rg
|
||||
}
|
||||
|
||||
@discardableResult
|
||||
func then<U>(on: DispatchQueue? = conf.Q.map, flags: DispatchWorkItemFlags? = nil, _ body: @escaping(T) -> Guarantee<U>) -> Guarantee<U> {
|
||||
let rg = Guarantee<U>(.pending)
|
||||
pipe { value in
|
||||
on.async(flags: flags) {
|
||||
body(value).pipe(to: rg.box.seal)
|
||||
}
|
||||
}
|
||||
return rg
|
||||
}
|
||||
|
||||
public func asVoid() -> Guarantee<Void> {
|
||||
return map(on: nil) { _ in }
|
||||
}
|
||||
|
||||
/**
|
||||
Blocks this thread, so you know, don’t call this on a serial thread that
|
||||
any part of your chain may use. Like the main thread for example.
|
||||
*/
|
||||
public func wait() -> T {
|
||||
|
||||
if Thread.isMainThread {
|
||||
print("PromiseKit: warning: `wait()` called on main thread!")
|
||||
}
|
||||
|
||||
var result = value
|
||||
|
||||
if result == nil {
|
||||
let group = DispatchGroup()
|
||||
group.enter()
|
||||
pipe { (foo: T) in result = foo; group.leave() }
|
||||
group.wait()
|
||||
}
|
||||
|
||||
return result!
|
||||
}
|
||||
}
|
||||
|
||||
public extension Guarantee where T: Sequence {
|
||||
|
||||
/**
|
||||
`Guarantee<[T]>` => `T` -> `Guarantee<U>` => `Guaranetee<[U]>`
|
||||
|
||||
firstly {
|
||||
.value([1,2,3])
|
||||
}.thenMap {
|
||||
.value($0 * 2)
|
||||
}.done {
|
||||
// $0 => [2,4,6]
|
||||
}
|
||||
*/
|
||||
func thenMap<U>(on: DispatchQueue? = conf.Q.map, flags: DispatchWorkItemFlags? = nil, _ transform: @escaping(T.Iterator.Element) -> Guarantee<U>) -> Guarantee<[U]> {
|
||||
return then(on: on, flags: flags) {
|
||||
when(fulfilled: $0.map(transform))
|
||||
}.recover {
|
||||
// if happens then is bug inside PromiseKit
|
||||
fatalError(String(describing: $0))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if swift(>=3.1)
|
||||
public extension Guarantee where T == Void {
|
||||
convenience init() {
|
||||
self.init(box: SealedBox(value: Void()))
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
public extension DispatchQueue {
|
||||
/**
|
||||
Asynchronously executes the provided closure on a dispatch queue.
|
||||
|
||||
DispatchQueue.global().async(.promise) {
|
||||
md5(input)
|
||||
}.done { md5 in
|
||||
//…
|
||||
}
|
||||
|
||||
- Parameter body: The closure that resolves this promise.
|
||||
- Returns: A new `Guarantee` resolved by the result of the provided closure.
|
||||
- Note: There is no Promise/Thenable version of this due to Swift compiler ambiguity issues.
|
||||
*/
|
||||
@available(macOS 10.10, iOS 2.0, tvOS 10.0, watchOS 2.0, *)
|
||||
final func async<T>(_: PMKNamespacer, group: DispatchGroup? = nil, qos: DispatchQoS = .default, flags: DispatchWorkItemFlags = [], execute body: @escaping () -> T) -> Guarantee<T> {
|
||||
let rg = Guarantee<T>(.pending)
|
||||
async(group: group, qos: qos, flags: flags) {
|
||||
rg.box.seal(body())
|
||||
}
|
||||
return rg
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#if os(Linux)
|
||||
import func CoreFoundation._CFIsMainThread
|
||||
|
||||
extension Thread {
|
||||
// `isMainThread` is not implemented yet in swift-corelibs-foundation.
|
||||
static var isMainThread: Bool {
|
||||
return _CFIsMainThread()
|
||||
}
|
||||
}
|
||||
#endif
|
Reference in New Issue
Block a user