OLD | NEW |
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 /// Capture asynchronous results into synchronous values. | 5 /// Import `async.dart` instead. |
6 /// | 6 @Deprecated("Will be removed in async 2.0.0.") |
7 /// Capturing a result (either a returned value or a thrown error) | |
8 /// means converting it into a [Result] - | |
9 /// either a [ValueResult] or an [ErrorResult]. | |
10 /// | |
11 /// This value can release itself by writing itself either to a | |
12 /// [EventSink] or a [Completer], or by becoming a [Future]. | |
13 library dart.pkg.async.results; | 7 library dart.pkg.async.results; |
14 | 8 |
15 import "dart:async"; | 9 export "src/result.dart"; |
16 | 10 export "src/result/capture_transformer.dart"; |
17 /// The result of a computation. | 11 export "src/result/error.dart"; |
18 abstract class Result<T> { | 12 export "src/result/release_transformer.dart"; |
19 /// Create a `Result` with the result of calling [computation]. | 13 export "src/result/value.dart"; |
20 /// | |
21 /// This generates either a [ValueResult] with the value returned by | |
22 /// calling `computation`, or an [ErrorResult] with an error thrown by | |
23 /// the call. | |
24 factory Result(T computation()) { | |
25 try { | |
26 return new ValueResult(computation()); | |
27 } catch (e, s) { | |
28 return new ErrorResult(e, s); | |
29 } | |
30 } | |
31 | |
32 /// Create a `Result` holding a value. | |
33 /// | |
34 /// Alias for [ValueResult.ValueResult]. | |
35 factory Result.value(T value) = ValueResult<T>; | |
36 | |
37 /// Create a `Result` holding an error. | |
38 /// | |
39 /// Alias for [ErrorResult.ErrorResult]. | |
40 factory Result.error(Object error, [StackTrace stackTrace]) => | |
41 new ErrorResult(error, stackTrace); | |
42 | |
43 // Helper functions. | |
44 static _captureValue(value) => new ValueResult(value); | |
45 static _captureError(error, stack) => new ErrorResult(error, stack); | |
46 static _release(Result v) { | |
47 if (v.isValue) return v.asValue.value; // Avoid wrapping in future. | |
48 return v.asFuture; | |
49 } | |
50 | |
51 /// Capture the result of a future into a `Result` future. | |
52 /// | |
53 /// The resulting future will never have an error. | |
54 /// Errors have been converted to an [ErrorResult] value. | |
55 static Future<Result> capture(Future future) { | |
56 return future.then(_captureValue, onError: _captureError); | |
57 } | |
58 | |
59 /// Release the result of a captured future. | |
60 /// | |
61 /// Converts the [Result] value of the given [future] to a value or error | |
62 /// completion of the returned future. | |
63 /// | |
64 /// If [future] completes with an error, the returned future completes with | |
65 /// the same error. | |
66 static Future release(Future<Result> future) { | |
67 return future.then(_release); | |
68 } | |
69 | |
70 /// Capture the results of a stream into a stream of [Result] values. | |
71 /// | |
72 /// The returned stream will not have any error events. | |
73 /// Errors from the source stream have been converted to [ErrorResult]s. | |
74 /// | |
75 /// Shorthand for transforming the stream using [CaptureStreamTransformer]. | |
76 static Stream<Result> captureStream(Stream source) { | |
77 return source.transform(const CaptureStreamTransformer()); | |
78 } | |
79 | |
80 /// Release a stream of [result] values into a stream of the results. | |
81 /// | |
82 /// `Result` values of the source stream become value or error events in | |
83 /// the returned stream as appropriate. | |
84 /// Errors from the source stream become errors in the returned stream. | |
85 /// | |
86 /// Shorthand for transforming the stream using [ReleaseStreamTransformer]. | |
87 static Stream releaseStream(Stream<Result> source) { | |
88 return source.transform(const ReleaseStreamTransformer()); | |
89 } | |
90 | |
91 /// Converts a result of a result to a single result. | |
92 /// | |
93 /// If the result is an error, or it is a `Result` value | |
94 /// which is then an error, then a result with that error is returned. | |
95 /// Otherwise both levels of results are value results, and a single | |
96 /// result with the value is returned. | |
97 static Result flatten(Result<Result> result) { | |
98 if (result.isError) return result; | |
99 return result.asValue.value; | |
100 } | |
101 | |
102 /// Whether this result is a value result. | |
103 /// | |
104 /// Always the opposite of [isError]. | |
105 bool get isValue; | |
106 | |
107 /// Whether this result is an error result. | |
108 /// | |
109 /// Always the opposite of [isValue]. | |
110 bool get isError; | |
111 | |
112 /// If this is a value result, return itself. | |
113 /// | |
114 /// Otherwise return `null`. | |
115 ValueResult<T> get asValue; | |
116 | |
117 /// If this is an error result, return itself. | |
118 /// | |
119 /// Otherwise return `null`. | |
120 ErrorResult get asError; | |
121 | |
122 /// Complete a completer with this result. | |
123 void complete(Completer<T> completer); | |
124 | |
125 /// Add this result to an [EventSink]. | |
126 /// | |
127 /// Calls the sink's `add` or `addError` method as appropriate. | |
128 void addTo(EventSink<T> sink); | |
129 | |
130 /// Creates a future completed with this result as a value or an error. | |
131 Future<T> get asFuture; | |
132 } | |
133 | |
134 /// A result representing a returned value. | |
135 class ValueResult<T> implements Result<T> { | |
136 final T value; | |
137 ValueResult(this.value); | |
138 bool get isValue => true; | |
139 bool get isError => false; | |
140 ValueResult<T> get asValue => this; | |
141 ErrorResult get asError => null; | |
142 void complete(Completer<T> completer) { | |
143 completer.complete(value); | |
144 } | |
145 void addTo(EventSink<T> sink) { | |
146 sink.add(value); | |
147 } | |
148 Future<T> get asFuture => new Future.value(value); | |
149 } | |
150 | |
151 /// A result representing a thrown error. | |
152 class ErrorResult implements Result { | |
153 final error; | |
154 final StackTrace stackTrace; | |
155 ErrorResult(this.error, this.stackTrace); | |
156 bool get isValue => false; | |
157 bool get isError => true; | |
158 ValueResult get asValue => null; | |
159 ErrorResult get asError => this; | |
160 void complete(Completer completer) { | |
161 completer.completeError(error, stackTrace); | |
162 } | |
163 void addTo(EventSink sink) { | |
164 sink.addError(error, stackTrace); | |
165 } | |
166 Future get asFuture => new Future.error(error, stackTrace); | |
167 | |
168 /// Calls an error handler with the error and stacktrace. | |
169 /// | |
170 /// An async error handler function is either a function expecting two | |
171 /// arguments, which will be called with the error and the stack trace, | |
172 /// or it has to be a function expecting only one argument, | |
173 /// which will be called with only the error. | |
174 void handle(Function errorHandler) { | |
175 if (errorHandler is ZoneBinaryCallback) { | |
176 errorHandler(error, stackTrace); | |
177 } else { | |
178 errorHandler(error); | |
179 } | |
180 } | |
181 } | |
182 | |
183 /// A stream transformer that captures a stream of events into [Result]s. | |
184 /// | |
185 /// The result of the transformation is a stream of [Result] values and | |
186 /// no error events. | |
187 class CaptureStreamTransformer<T> implements StreamTransformer<T, Result<T>> { | |
188 const CaptureStreamTransformer(); | |
189 | |
190 Stream<Result<T>> bind(Stream<T> source) { | |
191 return new Stream<Result<T>>.eventTransformed(source, _createSink); | |
192 } | |
193 | |
194 static EventSink _createSink(EventSink<Result> sink) { | |
195 return new CaptureSink(sink); | |
196 } | |
197 } | |
198 | |
199 /// A stream transformer that releases a stream of result events. | |
200 /// | |
201 /// The result of the transformation is a stream of values and | |
202 /// error events. | |
203 class ReleaseStreamTransformer<T> implements StreamTransformer<Result<T>, T> { | |
204 const ReleaseStreamTransformer(); | |
205 | |
206 Stream<T> bind(Stream<Result<T>> source) { | |
207 return new Stream<T>.eventTransformed(source, _createSink); | |
208 } | |
209 | |
210 static EventSink<Result> _createSink(EventSink sink) { | |
211 return new ReleaseSink(sink); | |
212 } | |
213 } | |
214 | |
215 /// An event sink wrapper that captures the incoming events. | |
216 /// | |
217 /// Wraps an [EventSink] that expects [Result] values. | |
218 /// Accepts any value and error result, | |
219 /// and passes them to the wrapped sink as [Result] values. | |
220 /// | |
221 /// The wrapped sink will never receive an error event. | |
222 class CaptureSink<T> implements EventSink<T> { | |
223 final EventSink _sink; | |
224 | |
225 CaptureSink(EventSink<Result<T>> sink) : _sink = sink; | |
226 void add(T value) { _sink.add(new ValueResult(value)); } | |
227 void addError(Object error, [StackTrace stackTrace]) { | |
228 _sink.add(new ErrorResult(error, stackTrace)); | |
229 } | |
230 void close() { _sink.close(); } | |
231 } | |
232 | |
233 /// An event sink wrapper that releases the incoming result events. | |
234 /// | |
235 /// Wraps an output [EventSink] that expects any result. | |
236 /// Accepts [Result] values, and puts the result value or error into the | |
237 /// corresponding output sink add method. | |
238 class ReleaseSink<T> implements EventSink<Result<T>> { | |
239 final EventSink _sink; | |
240 ReleaseSink(EventSink<T> sink) : _sink = sink; | |
241 void add(Result<T> result) { | |
242 if (result.isValue) { | |
243 _sink.add(result.asValue.value); | |
244 } else { | |
245 ErrorResult error = result.asError; | |
246 _sink.addError(error.error, error.stackTrace); | |
247 } | |
248 } | |
249 void addError(Object error, [StackTrace stackTrace]) { | |
250 // Errors may be added by intermediate processing, even if it is never | |
251 // added by CaptureSink. | |
252 _sink.addError(error, stackTrace); | |
253 } | |
254 | |
255 void close() { _sink.close(); } | |
256 } | |
OLD | NEW |