Skip to content

Commit

Permalink
Refine and operators in Swift
Browse files Browse the repository at this point in the history
  • Loading branch information
shoumikhin committed Feb 18, 2018
1 parent a3345f0 commit b5d1631
Show file tree
Hide file tree
Showing 11 changed files with 889 additions and 96 deletions.
2 changes: 1 addition & 1 deletion PromisesObjC.podspec
@@ -1,6 +1,6 @@
Pod::Spec.new do |s|
s.name = 'PromisesObjC'
s.version = '1.0.2'
s.version = '1.0.3'
s.authors = 'Google Inc.'
s.license = { :type => 'Apache', :file => 'LICENSE' }
s.homepage = 'https://github.com/google/promises'
Expand Down
2 changes: 1 addition & 1 deletion PromisesSwift.podspec
@@ -1,6 +1,6 @@
Pod::Spec.new do |s|
s.name = 'PromisesSwift'
s.version = '1.0.2'
s.version = '1.0.3'
s.authors = 'Google Inc.'
s.license = { :type => 'Apache', :file => 'LICENSE' }
s.homepage = 'https://github.com/google/promises'
Expand Down
87 changes: 85 additions & 2 deletions Sources/Promises/Promise+All.swift
Expand Up @@ -41,12 +41,95 @@ public func all<Value, Container: Sequence>(
on queue: DispatchQueue = .main,
_ promises: Container
) -> Promise<[Value]> where Container.Iterator.Element == Promise<Value> {
let promises = promises.map { $0.objCPromise }
let promise = Promise<[Value]>(
Promise<[Value]>.ObjCPromise<AnyObject>.__onQueue(queue, all: promises.map { $0.objCPromise })
Promise<[Value]>.ObjCPromise<AnyObject>.__onQueue(queue, all: promises)
)
// Keep Swift wrapper alive for chained promises until `ObjCPromise` counterpart is resolved.
promises.forEach {
$0.objCPromise.__pendingObjects?.add(promise)
$0.__pendingObjects?.add(promise)
}
return promise
}

/// Waits until all of the promises have been fulfilled.
/// If one of the promises is rejected, then the returned promise is rejected with same error.
/// If any other arbitrary value or `Error` appears in the array instead of `Promise`,
/// it's implicitly considered a pre-fulfilled or pre-rejected `Promise` correspondingly.
/// - parameters:
/// - queue: A queue to dispatch on.
/// - promiseA: Promise of type `A`.
/// - promiseB: Promise of type `B`.
/// - returns: Promise of a tuple containing the values of input promises in the same order.
public func all<A, B>(
on queue: DispatchQueue = .main,
_ promiseA: Promise<A>,
_ promiseB: Promise<B>
) -> Promise<(A, B)> {
let promises = [
promiseA.objCPromise,
promiseB.objCPromise
]
let promise = Promise<(A, B)>(
Promise<(A, B)>.ObjCPromise<AnyObject>.__onQueue(
queue,
all: promises
).__onQueue(queue, then: { objCValues in
guard let values = objCValues as [AnyObject]?,
let valueA = Promise<A>.asValue(values[0]),
let valueB = Promise<B>.asValue(values[1])
else {
preconditionFailure("Cannot convert \(type(of: objCValues)) to \((A, B).self)")
}
return (valueA, valueB)
})
)
// Keep Swift wrapper alive for chained promises until `ObjCPromise` counterpart is resolved.
promises.forEach {
$0.__pendingObjects?.add(promise)
}
return promise
}

/// Waits until all of the promises have been fulfilled.
/// If one of the promises is rejected, then the returned promise is rejected with same error.
/// If any other arbitrary value or `Error` appears in the array instead of `Promise`,
/// it's implicitly considered a pre-fulfilled or pre-rejected `Promise` correspondingly.
/// - parameters:
/// - queue: A queue to dispatch on.
/// - promiseA: Promise of type `A`.
/// - promiseB: Promise of type `B`.
/// - promiseC: Promise of type `C`.
/// - returns: Promise of a tuple containing the values of input promises in the same order.
public func all<A, B, C>(
on queue: DispatchQueue = .main,
_ promiseA: Promise<A>,
_ promiseB: Promise<B>,
_ promiseC: Promise<C>
) -> Promise<(A, B, C)> {
let promises = [
promiseA.objCPromise,
promiseB.objCPromise,
promiseC.objCPromise
]
let promise = Promise<(A, B, C)>(
Promise<(A, B, C)>.ObjCPromise<AnyObject>.__onQueue(
queue,
all: promises
).__onQueue(queue, then: { objCValues in
guard let values = objCValues as [AnyObject]?,
let valueA = Promise<A>.asValue(values[0]),
let valueB = Promise<B>.asValue(values[1]),
let valueC = Promise<C>.asValue(values[2])
else {
preconditionFailure("Cannot convert \(type(of: objCValues)) to \((A, B, C).self)")
}
return (valueA, valueB, valueC)
})
)
// Keep Swift wrapper alive for chained promises until `ObjCPromise` counterpart is resolved.
promises.forEach {
$0.__pendingObjects?.add(promise)
}
return promise
}
5 changes: 3 additions & 2 deletions Sources/Promises/Promise+Any.swift
Expand Up @@ -41,12 +41,13 @@ public func any<Value>(
on queue: DispatchQueue = .main,
_ promises: [Promise<Value>]
) -> Promise<Value> {
let promises = promises.map { $0.objCPromise }
let promise = Promise<Value>(
Promise<Value>.ObjCPromise<AnyObject>.__onQueue(queue, any: promises.map { $0.objCPromise })
Promise<Value>.ObjCPromise<AnyObject>.__onQueue(queue, any: promises)
)
// Keep Swift wrapper alive for chained promises until `ObjCPromise` counterpart is resolved.
promises.forEach {
$0.objCPromise.__pendingObjects?.add(promise)
$0.__pendingObjects?.add(promise)
}
return promise
}
18 changes: 12 additions & 6 deletions Sources/Promises/Promise+Then.swift
Expand Up @@ -29,8 +29,10 @@ public extension Promise {
@discardableResult
public func then<Result>(on queue: DispatchQueue = .main,
_ work: @escaping Then<Promise<Result>>) -> Promise<Result> {
let promise = Promise<Result>(objCPromise.__onQueue(queue, then: { value in
guard let value = Promise<Value>.asValue(value) else { preconditionFailure() }
let promise = Promise<Result>(objCPromise.__onQueue(queue, then: { objCValue in
guard let value = Promise<Value>.asValue(objCValue) else {
preconditionFailure("Cannot cast \(type(of: objCValue)) to \(Value.self)")
}
do {
return try work(value).objCPromise
} catch let error {
Expand All @@ -52,8 +54,10 @@ public extension Promise {
@discardableResult
public func then<Result>(on queue: DispatchQueue = .main,
_ work: @escaping Then<Result>) -> Promise<Result> {
let promise = Promise<Result>(objCPromise.__onQueue(queue, then: { value in
guard let value = Promise<Value>.asValue(value) else { preconditionFailure() }
let promise = Promise<Result>(objCPromise.__onQueue(queue, then: { objCValue in
guard let value = Promise<Value>.asValue(objCValue) else {
preconditionFailure("Cannot cast \(type(of: objCValue)) to \(Value.self)")
}
do {
let value = try work(value)
return value as? NSError ?? Promise<Result>.asAnyObject(value)
Expand All @@ -75,8 +79,10 @@ public extension Promise {
/// - returns: A new pending promise to be resolved with the value passed into the `work` block.
@discardableResult
public func then(on queue: DispatchQueue = .main, _ work: @escaping Then<Void>) -> Promise {
let promise = Promise(objCPromise.__onQueue(queue, then: { value in
guard let value = Promise<Value>.asValue(value) else { preconditionFailure() }
let promise = Promise(objCPromise.__onQueue(queue, then: { objCValue in
guard let value = Promise<Value>.asValue(objCValue) else {
preconditionFailure("Cannot cast \(type(of: objCValue)) to \(Value.self)")
}
do {
try work(value)
return Promise<Value>.asAnyObject(value)
Expand Down

0 comments on commit b5d1631

Please sign in to comment.