Repository navigation
Expand file tree
/
Copy pathAsync.swift
More file actions
149 lines (118 loc) · 4.16 KB
/
Copy pathAsync.swift
File metadata and controls
149 lines (118 loc) · 4.16 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
//
// Async.swift
// SwiftSummit
//
// Created by Thomas Visser on 30/10/15.
// Copyright © 2015 Thomas Visser. All rights reserved.
//
import Foundation
protocol AsyncType {
typealias Res
var result: Res? { get }
init(@noescape scope: (Res -> Void) -> Void)
func onComplete(callback: Res -> Void) -> Self
}
class Async<Result>: AsyncType {
typealias Callback = Result -> Void
private(set) var result: Result?
private var callbacks = [Callback]()
required init(@noescape scope: (Result -> Void) -> Void) {
scope { res in
self.result = res
for callback in self.callbacks {
callback(res)
}
self.callbacks.removeAll()
}
}
func onComplete(callback: Result -> Void) -> Self {
let mainCallback: Callback = { res in
dispatch_async(dispatch_get_main_queue()) {
callback(res)
}
}
if let result = result {
mainCallback(result)
} else {
callbacks.append(mainCallback)
}
return self
}
}
import Result
class Future<Value, Error: ErrorType>: Async<Result<Value,Error>> {
required init(@noescape scope: (Result<Value, Error> -> Void) -> Void) {
super.init(scope: scope)
}
}
extension AsyncType where Res: ResultType {
func onSuccess(callback: Res.Value -> Void) -> Self {
return onComplete { res in
res.analysis(ifSuccess: { val -> Void in
callback(val)
}, ifFailure: { _ in })
}
}
func onFailure(callback: Res.Error -> Void) -> Self {
return onComplete { res in
res.analysis(ifSuccess: { _ in }, ifFailure: { error -> Void in
callback(error)
})
}
}
func map<U>(transform: Self.Res.Value -> U) -> Future<U, Self.Res.Error> {
return Future { completion in
onComplete { res in
res.analysis(ifSuccess: { val -> Void in
completion(Result(value: transform(val)))
}, ifFailure: { error -> Void in
completion(Result(error: error))
})
}
}
}
func flatMap<U>(transform: Self.Res.Value -> Result<U, Self.Res.Error>) -> Future<U, Self.Res.Error> {
return Future { completion in
self.onComplete { res in
res.analysis(ifSuccess: { val -> Void in
transform(val).analysis(ifSuccess: { val in
completion(Result(value: val))
}, ifFailure: { error in
completion(Result(error: error))
});
}, ifFailure: { error -> Void in
completion(Result(error: error))
})
}
}
}
func flatMap<U>(transform: Self.Res.Value -> Future<U, Self.Res.Error>) -> Future<U, Self.Res.Error> {
return Future { completion in
self.onSuccess { value in
transform(value).onSuccess { val in
completion(Result(value: val))
}.onFailure { err in
completion(Result(error: err))
}
}.onFailure { error in
completion(Result(error: error))
}
}
}
}
extension SequenceType where Generator.Element: AsyncType, Generator.Element.Res : ResultType {
func fold<R>(zero: R, f: (R, Generator.Element.Res.Value) -> R) -> Future<R, Generator.Element.Res.Error> {
return reduce(Future { $0(Result(value: zero)) }) { zero, elem in
return zero.flatMap { zeroVal in
elem.map { elemVal in
return f(zeroVal, elemVal)
}
}
}
}
func sequence() -> Future<[Generator.Element.Res.Value], Generator.Element.Res.Error> {
return fold(Array<Generator.Element.Res.Value>()) { (acc, elem) -> [Generator.Element.Res.Value] in
return acc + [elem]
}
}
}