OLD | NEW |
---|---|
1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2016, 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 import 'dart:async'; | 5 import 'dart:async'; |
6 | 6 |
7 import 'result/capture_transformer.dart'; | 7 import 'result/capture_transformer.dart'; |
8 import 'result/error.dart'; | 8 import 'result/error.dart'; |
9 import 'result/release_transformer.dart'; | 9 import 'result/release_transformer.dart'; |
10 import 'result/value.dart'; | 10 import 'result/value.dart'; |
11 import 'stream_sink_transformer.dart'; | 11 import 'stream_sink_transformer.dart'; |
12 | 12 |
13 /// The result of a computation. | 13 /// The result of a computation. |
14 /// | 14 /// |
15 /// Capturing a result (either a returned value or a thrown error) means | 15 /// Capturing a result (either a returned value or a thrown error) means |
16 /// converting it into a [Result] - either a [ValueResult] or an [ErrorResult]. | 16 /// converting it into a [Result] - either a [ValueResult] or an [ErrorResult]. |
17 /// | 17 /// |
18 /// This value can release itself by writing itself either to a [EventSink] or a | 18 /// This value can release itself by writing itself either to a [EventSink] or a |
19 /// [Completer], or by becoming a [Future]. | 19 /// [Completer], or by becoming a [Future]. |
20 /// | |
21 /// A [Future] represents a potential result, one that might not have been | |
22 /// computed yet, and a [Result] is always a completed and available result. | |
20 abstract class Result<T> { | 23 abstract class Result<T> { |
21 /// A stream transformer that captures a stream of events into [Result]s. | 24 /// A stream transformer that captures a stream of events into [Result]s. |
22 /// | 25 /// |
23 /// The result of the transformation is a stream of [Result] values and no | 26 /// The result of the transformation is a stream of [Result] values and no |
24 /// error events. This is the transformer used by [captureStream]. | 27 /// error events. This is the transformer used by [captureStream]. |
25 static const StreamTransformer<Object, Result> captureStreamTransformer = | 28 static const StreamTransformer<Object, Result> captureStreamTransformer = |
26 const CaptureStreamTransformer(); | 29 const CaptureStreamTransformer(); |
27 | 30 |
28 /// A stream transformer that releases a stream of result events. | 31 /// A stream transformer that releases a stream of result events. |
29 /// | 32 /// |
(...skipping 18 matching lines...) Expand all Loading... | |
48 const StreamSinkTransformer.fromStreamTransformer( | 51 const StreamSinkTransformer.fromStreamTransformer( |
49 const ReleaseStreamTransformer()); | 52 const ReleaseStreamTransformer()); |
50 | 53 |
51 /// Create a `Result` with the result of calling [computation]. | 54 /// Create a `Result` with the result of calling [computation]. |
52 /// | 55 /// |
53 /// This generates either a [ValueResult] with the value returned by | 56 /// This generates either a [ValueResult] with the value returned by |
54 /// calling `computation`, or an [ErrorResult] with an error thrown by | 57 /// calling `computation`, or an [ErrorResult] with an error thrown by |
55 /// the call. | 58 /// the call. |
56 factory Result(T computation()) { | 59 factory Result(T computation()) { |
57 try { | 60 try { |
58 return new ValueResult(computation()); | 61 return new ValueResult<T>(computation()); |
59 } catch (e, s) { | 62 } catch (e, s) { |
60 return new ErrorResult(e, s); | 63 return new ErrorResult(e, s); |
61 } | 64 } |
62 } | 65 } |
63 | 66 |
64 /// Create a `Result` holding a value. | 67 /// Create a `Result` holding a value. |
65 /// | 68 /// |
66 /// Alias for [ValueResult.ValueResult]. | 69 /// Alias for [ValueResult.ValueResult]. |
67 factory Result.value(T value) = ValueResult<T>; | 70 factory Result.value(T value) = ValueResult<T>; |
68 | 71 |
69 /// Create a `Result` holding an error. | 72 /// Create a `Result` holding an error. |
70 /// | 73 /// |
71 /// Alias for [ErrorResult.ErrorResult]. | 74 /// Alias for [ErrorResult.ErrorResult]. |
72 factory Result.error(Object error, [StackTrace stackTrace]) => | 75 factory Result.error(Object error, [StackTrace stackTrace]) => |
73 new ErrorResult(error, stackTrace); | 76 new ErrorResult(error, stackTrace); |
74 | 77 |
75 /// Capture the result of a future into a `Result` future. | 78 /// Capture the result of a future into a `Result` future. |
76 /// | 79 /// |
77 /// The resulting future will never have an error. | 80 /// The resulting future will never have an error. |
78 /// Errors have been converted to an [ErrorResult] value. | 81 /// Errors have been converted to an [ErrorResult] value. |
79 static Future<Result<T>> capture<T>(Future<T> future) { | 82 static Future<Result<T>> capture<T>(Future<T> future) { |
80 return future.then((value) => new ValueResult(value), | 83 return future.then((value) => new ValueResult(value), |
81 onError: (error, stackTrace) => new ErrorResult<T>(error, stackTrace)); | 84 onError: (error, stackTrace) => new ErrorResult<T>(error, stackTrace)); |
82 } | 85 } |
83 | 86 |
87 /// Capture each future in [elements], | |
floitsch
2017/08/17 15:29:22
Dartdoc wants third person. Here and for all other
| |
88 /// | |
89 /// Returns a (future of) a list of results for each element in [elements], | |
90 /// in iteration order. | |
91 /// Each future in [elements] is [capture]d and each non-future is | |
92 /// wrapped as a [Result.value]. | |
93 /// The returned future will never have an error. | |
94 static Future<List<Result<T>>> captureAll<T>(Iterable<FutureOr<T>> elements) { | |
95 var results = <T>[]; | |
96 int pending = 0; | |
97 var completer; | |
98 for (var element in elements) { | |
99 if (element is Future<T>) { | |
100 int i = results.length; | |
101 results.add(null); | |
102 pending++; | |
103 Result.capture<T>(element).then((result) { | |
104 results[i] = result; | |
105 if (--pending == 0) { | |
106 completer.complete(results); | |
107 } | |
108 }); | |
109 } else { | |
110 results.add(new Result<T>.value(element)); | |
111 } | |
112 } | |
113 if (pending == 0) { | |
114 return new Future<List<Result<T>>>.value(results); | |
115 } | |
116 completer = Completer<List<Result<T>>>(); | |
117 return completer.future; | |
118 } | |
119 | |
84 /// Release the result of a captured future. | 120 /// Release the result of a captured future. |
85 /// | 121 /// |
86 /// Converts the [Result] value of the given [future] to a value or error | 122 /// Converts the [Result] value of the given [future] to a value or error |
87 /// completion of the returned future. | 123 /// completion of the returned future. |
88 /// | 124 /// |
89 /// If [future] completes with an error, the returned future completes with | 125 /// If [future] completes with an error, the returned future completes with |
90 /// the same error. | 126 /// the same error. |
91 static Future<T> release<T>(Future<Result<T>> future) => | 127 static Future<T> release<T>(Future<Result<T>> future) => |
92 future.then<T>((result) => result.asFuture); | 128 future.then<T>((result) => result.asFuture); |
93 | 129 |
(...skipping 13 matching lines...) Expand all Loading... | |
107 source.transform(new ReleaseStreamTransformer<T>()); | 143 source.transform(new ReleaseStreamTransformer<T>()); |
108 | 144 |
109 /// Converts a result of a result to a single result. | 145 /// Converts a result of a result to a single result. |
110 /// | 146 /// |
111 /// If the result is an error, or it is a `Result` value | 147 /// If the result is an error, or it is a `Result` value |
112 /// which is then an error, then a result with that error is returned. | 148 /// which is then an error, then a result with that error is returned. |
113 /// Otherwise both levels of results are value results, and a single | 149 /// Otherwise both levels of results are value results, and a single |
114 /// result with the value is returned. | 150 /// result with the value is returned. |
115 static Result<T> flatten<T>(Result<Result<T>> result) { | 151 static Result<T> flatten<T>(Result<Result<T>> result) { |
116 if (result.isValue) return result.asValue.value; | 152 if (result.isValue) return result.asValue.value; |
117 return new ErrorResult<T>(result.asError.error, result.asError.stackTrace); | 153 return result.asError; |
154 } | |
155 | |
156 /// Converts a sequence of results to a result of a list. | |
157 /// | |
158 /// Returns either a list of values if [results] doesn't contain any errors, | |
159 /// or the first error result in [results]. | |
160 static Result<List<T>> flattenList(Iterable<Result<T>> results) { | |
161 var values = <T>[]; | |
162 for (var result in results) { | |
163 if (result.isValue) { | |
164 values.add(result.asValue.value); | |
165 } | |
166 return result.asError; | |
167 } | |
168 return new Result<List<T>>.value(values); | |
118 } | 169 } |
119 | 170 |
120 /// Whether this result is a value result. | 171 /// Whether this result is a value result. |
121 /// | 172 /// |
122 /// Always the opposite of [isError]. | 173 /// Always the opposite of [isError]. |
123 bool get isValue; | 174 bool get isValue; |
124 | 175 |
125 /// Whether this result is an error result. | 176 /// Whether this result is an error result. |
126 /// | 177 /// |
127 /// Always the opposite of [isValue]. | 178 /// Always the opposite of [isValue]. |
128 bool get isError; | 179 bool get isError; |
129 | 180 |
130 /// If this is a value result, return itself. | 181 /// If this is a value result, return itself. |
131 /// | 182 /// |
132 /// Otherwise return `null`. | 183 /// Otherwise return `null`. |
133 ValueResult<T> get asValue; | 184 ValueResult<T> get asValue; |
134 | 185 |
135 /// If this is an error result, return itself. | 186 /// If this is an error result, return itself. |
136 /// | 187 /// |
137 /// Otherwise return `null`. | 188 /// Otherwise return `null`. |
138 ErrorResult<T> get asError; | 189 ErrorResult get asError; |
139 | 190 |
140 /// Complete a completer with this result. | 191 /// Complete a completer with this result. |
141 void complete(Completer<T> completer); | 192 void complete(Completer<T> completer); |
142 | 193 |
143 /// Add this result to an [EventSink]. | 194 /// Add this result to an [EventSink]. |
144 /// | 195 /// |
145 /// Calls the sink's `add` or `addError` method as appropriate. | 196 /// Calls the sink's `add` or `addError` method as appropriate. |
146 void addTo(EventSink<T> sink); | 197 void addTo(EventSink<T> sink); |
147 | 198 |
148 /// Creates a future completed with this result as a value or an error. | 199 /// A future that has been completed with this result as a value or an error. |
149 Future<T> get asFuture; | 200 Future<T> get asFuture; |
150 } | 201 } |
OLD | NEW |