Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(399)

Side by Side Diff: pkg/async/lib/materialize.dart

Issue 255123002: Add capture/release for results in package:async (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Added captureStream/releaseStream too. Created 6 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« pkg/async/lib/async.dart ('K') | « pkg/async/lib/async.dart ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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
3 // BSD-style license that can be found in the LICENSE file.
4
5 /**
6 * Capture asynchronous results into synchronous values, and release them again.
7 *
8 * Capturing a result (either a returned value or a thrown error)
9 * means converting it into a [Result] -
10 * either a [ValueResult] or an [ErrorResult].
11 *
12 * This value can release itself by writing itself either to a
13 * [EventSink] or a [Completer], or by becoming a [Future].
14 */
15 library dart.pkg.async.captureResults;
16
17 /**
18 * The result of a computation.
19 */
20 abstract class Result<T> {
21 /**
22 * Create a `Result` with the result of calling [computation].
23 *
24 * This generates either a [ValueResult] with the value returned by
25 * calling `computation`, or an [ErrorResult] with an error thrown by
26 * the call.
27 */
28 Result(T computation()) {
29 try {
30 return new ValueResult(computation());
31 } catch (e, s) {
32 return new ErrorResult(e, s);
33 }
34 }
35
36 /**
37 * Create a `Result` holding a value.
38 */
39 factory Result.value(T value) = ValueResult<T>;
40
41 /**
42 * Create a `Result` holding an error.
43 */
44 factory Result.error(Object error, [StackTrace stackTrace]) = ErrorResult;
45
46 // Helper functions.
47 static _captureValue(value) => new ValueResult(value);
48 static _captureError(error, stack) => new ErrorResult(error, stack);
49 static _release(Result v) {
50 if (v.isValue) return v.asValue.value; // Avoid wrapping in future.
51 return v.asFuture;
52 }
53
54 /**
55 * Capture the result of a future into a `Result` future.
56 *
57 * The resulting future will never have an error.
58 * Errors have been converted to an [ErrorResult] value.
59 */
60 static Future<Result> capture(Future future) {
61 return future.then(_captureValue, onError: _captureError);
62 }
63
64 /**
65 * Release the result of a captured future.
66 *
67 * Converts the [Result] value of the given [future] to a result or error
floitsch 2014/05/22 12:15:21 to a value or error completion.
Lasse Reichstein Nielsen 2014/05/23 07:14:25 Done.
68 * completion of the returned future.
69 *
70 * If [future] completes with an error, the returned future completes with
71 * the same error.
72 */
73 static Future release(Future<Result> future) {
74 return future.then(_release);
75 }
76
77 /**
78 * Capture the results of a stream into a stream of [Result] values.
79 *
80 * The returned stream will not have any error events.
81 * Errors from the source stream have been converted to [ErrorResult]s.
82 *
83 * Transforms the stream using [CaptureStreamTransformer].
84 */
85 static Stream<Result> captureStream(Stream source) {
86 return source.transform(const CaptureStreamTransformer());
87 }
88
89 /**
90 * Release a stream of [result] values into a stream of the results.
91 *
92 * `Result` values of the source stream become value or error events in
93 * the retuned stream as appropriate.
94 * Errors from the source stream become errors in the returned stream.
95 *
96 * Transforms the stream using [ReleaseStreamTransformer].
97 */
98 static Stream releaseStream(Stream<Result> source) {
99 return source.transform(const ReleaseStreamTransformer());
100 }
101
102 /**
103 * Whether this result is a value result.
104 *
105 * Always the opposite of [isError].
106 */
107 bool get isValue;
108
109 /**
110 * Whether this result is an error result.
111 *
112 * Always the opposite of [isValue].
113 */
114 bool get isError;
115
116 /**
117 * If this is a value result, return itself.
118 *
119 * Otherwise return `null`.
120 */
121 ValueResult<T> get asValue;
122
123 /**
124 * If this is an error result, return itself.
125 *
126 * Otherwise return `null`.
127 */
128 ErrorResult get asError;
129
130 /**
131 * Complete a completer with this result.
132 */
133 void complete(Completer<T> completer);
134
135 /**
136 * Add this result to a [StreamSink].
137 */
138 void addTo(EventSink<T> sink);
139
140 /**
141 * Creates a future completed with this result as a value or an error.
142 */
143 Future<T> get asFuture;
144 }
145
146 /**
147 * A result representing a returned value.
148 */
149 class ValueResult<T> implements Result<T> {
150 /** The returned value that this result represents. */
151 final T value;
152 /** Create a value result with the given [value]. */
153 ValueResult(this.value);
154 bool get isValue => true;
155 bool get isError => false;
156 ValueResult<T> get asValue => this;
157 ErrorResult get asError => null;
158 void complete(Completer<T> completer) {
159 completer.complete(value);
160 }
161 void addTo(EventSink<T> sink) {
162 sink.add(value);
163 }
164 Future<T> get asFuture => new Future.value(value);
165 }
166
167 /**
168 * A result representing a thrown error.
169 */
170 class ErrorResult implements Result {
171 /** The thrown object that this result represents. */
172 final error;
173 /** The stack trace, if any, associated with the throw. */
174 final StackTrace stackTrace;
175 /** Create an error result with the given [error] and [stackTrace]. */
176 ErrorResult(this.error, this.stackTrace);
177 bool get isValue => false;
178 bool get isError => true;
179 ValueResult get asValue => null;
180 ErrorResult get asError => this;
181 void complete(Completer<T> completer) {
182 completer.completeError(error, stackTrace);
183 }
184 void addTo(EventSink<T> sink) {
185 sink.addError(error, stackTrace);
186 }
187 Future get asFuture => new Future.error(error, stackTrace);
188 }
189
190 /**
191 * A stream transformer that captures a stream of events into [Result]s.
192 *
193 * The result of the transformation is a stream of [Result] values and
194 * no error events.
195 */
196 class CaptureStreamTransformer<T> implements StreamTransformer<T, Result<T>> {
197 const CaptureStreamTransformer();
198
199 Stream<Result<T>> bind(Stream<T> source) {
200 return new Stream<Result<T>>.eventTransformed(source, _createSink);
201 }
202
203 static EventSink _createSink(EventSink<Result> sink) {
204 return new CaptureSink(sink);
205 }
206 }
207
208 /**
209 * A stream transformer that releases a stream of result events.
210 *
211 * The result of the transformation is a stream of values and
212 * error events.
213 */
214 class ReleaseStreamTransformer<T> implements StreamTransformer<Result<T>, T> {
215 const ReleaseStreamTransformer();
216
217 Stream<T> bind(Stream<Result<T>> source) {
218 return new Stream<T>.eventTransformed(source, _createSink);
219 }
220
221 static EventSink _createSink(EventSink<Result> sink) {
222 return new ReleaseSink(sink);
223 }
224 }
225
226 /**
227 * An event sink wrapper that captures the incoming events.
228 *
229 * Wraps an [EventSink] that expects [Result] values.
230 * Accepts any value and error result,
231 * and passes them to the wrapped sink as [Result] values.
232 *
233 * The wrapped sink will never receive an error event.
234 */
235 class CaptureSink<T> implements EventSink<T> {
236 final EventSink _sink;
237 CaptureSink();
238 CaptureSink(EventSink<Result<T>> sink) : _sink = sink;
239 void add(T value) { _sink.add(new ValueResult(value)); }
240 void addError(Object error, StackTrace stackTrace) {
241 _sink.add(new ErrorResult(error, stackTrace));
242 }
243 void addDone() { _sink.addDone(); };
244 }
245
246 /**
247 * An event sink wrapper that releases the incoming result events.
248 *
249 * Wraps an output [EventSink] that expects any result.
250 * Accepts [Result] values, and puts the result value or error into the
251 * corresponding output sink add method.
252 */
253 class ReleaseSink<T> implements EventSink<Result<T>> {
254 final EventSink _sink;
255 ReleaseSink(EventSink<T> sink) : _sink = sink;
256 void add(Result<T> result) {
257 if (result.isValue) {
258 _sink.add(result.asValue.value);
259 } else {
260 ErrorResult error = result.asError;
261 _sink.addError(error.error, error.stackTrace);
262 }
263 }
264 void addError(Object error, StackTrace stackTrace) {
265 // Errors may be added by intermediate processing, even if it is never
266 // added by CaptureSink.
267 _sink.addError(error, stackTrace);
268 }
269
270 void addDone() { _sink.addDone(); }
271 }
OLDNEW
« pkg/async/lib/async.dart ('K') | « pkg/async/lib/async.dart ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698