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

Side by Side Diff: packages/barback/lib/src/utils.dart

Issue 3014633002: Roll to pickup pool changes (Closed)
Patch Set: Created 3 years, 2 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
OLDNEW
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 library barback.utils; 5 library barback.utils;
6 6
7 import 'dart:async'; 7 import 'dart:async';
8 import 'dart:typed_data'; 8 import 'dart:typed_data';
9 9
10 import 'package:async/async.dart'; 10 import 'package:async/async.dart';
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after
123 // TODO(nweiz): remove "as" when issue 11080 is fixed. 123 // TODO(nweiz): remove "as" when issue 11080 is fixed.
124 return new Uint8List.view((input as TypedData).buffer); 124 return new Uint8List.view((input as TypedData).buffer);
125 } 125 }
126 return new Uint8List.fromList(input); 126 return new Uint8List.fromList(input);
127 } 127 }
128 128
129 /// Group the elements in [iter] by the value returned by [fn]. 129 /// Group the elements in [iter] by the value returned by [fn].
130 /// 130 ///
131 /// This returns a map whose keys are the return values of [fn] and whose values 131 /// This returns a map whose keys are the return values of [fn] and whose values
132 /// are lists of each element in [iter] for which [fn] returned that key. 132 /// are lists of each element in [iter] for which [fn] returned that key.
133 Map<Object/*=T*/, List/*<S>*/> groupBy/*<S, T>*/(Iterable/*<S>*/ iter, 133 Map<Object, List<S>> groupBy<S, T>(Iterable<S> iter, T fn(S element)) {
134 /*=T*/ fn(/*=S*/ element)) { 134 var map = <T, List<S>>{};
135 var map = /*<T, List<S>>*/{};
136 for (var element in iter) { 135 for (var element in iter) {
137 var list = map.putIfAbsent(fn(element), () => []); 136 var list = map.putIfAbsent(fn(element), () => []);
138 list.add(element); 137 list.add(element);
139 } 138 }
140 return map; 139 return map;
141 } 140 }
142 141
143 /// Flattens nested lists inside an iterable into a single list containing only 142 /// Flattens nested lists inside an iterable into a single list containing only
144 /// non-list elements. 143 /// non-list elements.
145 List flatten(Iterable nested) { 144 List flatten(Iterable nested) {
146 var result = []; 145 var result = [];
147 helper(list) { 146 helper(list) {
148 for (var element in list) { 147 for (var element in list) {
149 if (element is List) { 148 if (element is List) {
150 helper(element); 149 helper(element);
151 } else { 150 } else {
152 result.add(element); 151 result.add(element);
153 } 152 }
154 } 153 }
155 } 154 }
155
156 helper(nested); 156 helper(nested);
157 return result; 157 return result;
158 } 158 }
159 159
160 /// Returns the union of all elements in each set in [sets]. 160 /// Returns the union of all elements in each set in [sets].
161 Set/*<T>*/ unionAll/*<T>*/(Iterable<Set/*<T>*/> sets) => 161 Set<T> unionAll<T>(Iterable<Set<T>> sets) =>
162 sets.fold(new Set(), (union, set) => union.union(set)); 162 sets.fold(new Set(), (union, set) => union.union(set));
163 163
164 /// Creates a new map from [map] with new keys and values. 164 /// Creates a new map from [map] with new keys and values.
165 /// 165 ///
166 /// The return values of [keyFn] are used as the keys and the return values of 166 /// The return values of [keyFn] are used as the keys and the return values of
167 /// [valueFn] are used as the values for the new map. 167 /// [valueFn] are used as the values for the new map.
168 Map/*<K2, V2>*/ mapMap/*<K1, V1, K2, V2>*/(Map/*<K1, V1>*/ map, 168 Map<K2, V2> mapMap<K1, V1, K2, V2>(Map<K1, V1> map, K2 keyFn(K1 key, V1 value),
169 /*=K2*/ keyFn(/*=K1*/ key, /*=V1*/ value), 169 V2 valueFn(K1 key, V1 value)) =>
170 /*=V2*/ valueFn(/*=K1*/ key, /*=V1*/ value)) => 170 new Map.fromIterable(map.keys,
171 new Map.fromIterable(map.keys, 171 key: (key) => keyFn(key as K1, map[key]),
172 key: (key) => keyFn(key as dynamic/*=K1*/, map[key]), 172 value: (key) => valueFn(key as K1, map[key]));
173 value: (key) => valueFn(key as dynamic/*=K1*/, map[key]));
174 173
175 /// Creates a new map from [map] with the same keys. 174 /// Creates a new map from [map] with the same keys.
176 /// 175 ///
177 /// The return values of [fn] are used as the values for the new map. 176 /// The return values of [fn] are used as the values for the new map.
178 Map/*<K, V2>*/ mapMapValues/*<K, V1, V2>*/(Map/*<K, V1>*/ map, 177 Map<K, V2> mapMapValues<K, V1, V2>(Map<K, V1> map, V2 fn(K key, V1 value)) =>
179 /*=V2*/ fn(/*=K*/ key, /*=V1*/ value)) => 178 // TODO(nweiz): Don't explicitly type [key] when sdk#25490 is fixed.
180 // TODO(nweiz): Don't explicitly type [key] when sdk#25490 is fixed. 179 mapMap(map, (K key, _) => key, fn);
181 mapMap(map, (/*=K*/ key, _) => key, fn);
182 180
183 /// Creates a new map from [map] with the same keys. 181 /// Creates a new map from [map] with the same keys.
184 /// 182 ///
185 /// The return values of [fn] are used as the keys for the new map. 183 /// The return values of [fn] are used as the keys for the new map.
186 Map/*<K2, V>*/ mapMapKeys/*<K1, V, K2>*/(Map/*<K1, V>*/ map, 184 Map<K2, V> mapMapKeys<K1, V, K2>(Map<K1, V> map, K2 fn(K1 key, V value)) =>
187 /*=K2*/ fn(/*=K1*/ key, /*=V*/ value)) => 185 // TODO(nweiz): Don't explicitly type [value] when sdk#25490 is fixed.
188 // TODO(nweiz): Don't explicitly type [value] when sdk#25490 is fixed. 186 mapMap(map, fn, (_, V value) => value);
189 mapMap(map, fn, (_, /*=V*/ value) => value);
190 187
191 /// Returns whether [set1] has exactly the same elements as [set2]. 188 /// Returns whether [set1] has exactly the same elements as [set2].
192 bool setEquals(Set set1, Set set2) => 189 bool setEquals(Set set1, Set set2) =>
193 set1.length == set2.length && set1.containsAll(set2); 190 set1.length == set2.length && set1.containsAll(set2);
194 191
195 /// Merges [streams] into a single stream that emits events from all sources. 192 /// Merges [streams] into a single stream that emits events from all sources.
196 /// 193 ///
197 /// If [broadcast] is true, this will return a broadcast stream; otherwise, it 194 /// If [broadcast] is true, this will return a broadcast stream; otherwise, it
198 /// will return a buffered stream. 195 /// will return a buffered stream.
199 Stream/*<T>*/ mergeStreams/*<T>*/(Iterable<Stream/*<T>*/> streams, 196 Stream<T> mergeStreams<T>(Iterable<Stream<T>> streams,
200 {bool broadcast: false}) { 197 {bool broadcast: false}) {
201 streams = streams.toList(); 198 streams = streams.toList();
202 var doneCount = 0; 199 var doneCount = 0;
203 // Use a sync stream to preserve the synchrony behavior of the input streams. 200 // Use a sync stream to preserve the synchrony behavior of the input streams.
204 // If the inputs are sync, then this will be sync as well; if the inputs are 201 // If the inputs are sync, then this will be sync as well; if the inputs are
205 // async, then the events we receive will also be async, and forwarding them 202 // async, then the events we receive will also be async, and forwarding them
206 // sync won't change that. 203 // sync won't change that.
207 var controller = broadcast 204 var controller = broadcast
208 ? new StreamController/*<T>*/.broadcast(sync: true) 205 ? new StreamController<T>.broadcast(sync: true)
209 : new StreamController/*<T>*/(sync: true); 206 : new StreamController<T>(sync: true);
210 207
211 for (var stream in streams) { 208 for (var stream in streams) {
212 stream.listen( 209 stream.listen(controller.add, onError: controller.addError, onDone: () {
213 controller.add,
214 onError: controller.addError,
215 onDone: () {
216 doneCount++; 210 doneCount++;
217 if (doneCount == streams.length) controller.close(); 211 if (doneCount == streams.length) controller.close();
218 }); 212 });
219 } 213 }
220 214
221 return controller.stream; 215 return controller.stream;
222 } 216 }
223 217
224 /// Prepends each line in [text] with [prefix]. If [firstPrefix] is passed, the 218 /// Prepends each line in [text] with [prefix]. If [firstPrefix] is passed, the
225 /// first line is prefixed with that instead. 219 /// first line is prefixed with that instead.
226 String prefixLines(String text, {String prefix: '| ', String firstPrefix}) { 220 String prefixLines(String text, {String prefix: '| ', String firstPrefix}) {
227 var lines = text.split('\n'); 221 var lines = text.split('\n');
228 if (firstPrefix == null) { 222 if (firstPrefix == null) {
229 return lines.map((line) => '$prefix$line').join('\n'); 223 return lines.map((line) => '$prefix$line').join('\n');
230 } 224 }
231 225
232 var firstLine = "$firstPrefix${lines.first}"; 226 var firstLine = "$firstPrefix${lines.first}";
233 lines = lines.skip(1).map((line) => '$prefix$line').toList(); 227 lines = lines.skip(1).map((line) => '$prefix$line').toList();
234 lines.insert(0, firstLine); 228 lines.insert(0, firstLine);
235 return lines.join('\n'); 229 return lines.join('\n');
236 } 230 }
237 231
238 /// Returns a [Future] that completes after pumping the event queue [times] 232 /// Returns a [Future] that completes after pumping the event queue [times]
239 /// times. By default, this should pump the event queue enough times to allow 233 /// times. By default, this should pump the event queue enough times to allow
240 /// any code to run, as long as it's not waiting on some external event. 234 /// any code to run, as long as it's not waiting on some external event.
241 Future pumpEventQueue([int times=20]) { 235 Future pumpEventQueue([int times = 20]) {
242 if (times == 0) return new Future.value(); 236 if (times == 0) return new Future.value();
243 // We use a delayed future to allow microtask events to finish. The 237 // We use a delayed future to allow microtask events to finish. The
244 // Future.value or Future() constructors use scheduleMicrotask themselves and 238 // Future.value or Future() constructors use scheduleMicrotask themselves and
245 // would therefore not wait for microtask callbacks that are scheduled after 239 // would therefore not wait for microtask callbacks that are scheduled after
246 // invoking this method. 240 // invoking this method.
247 return new Future.delayed(Duration.ZERO, () => pumpEventQueue(times - 1)); 241 return new Future.delayed(Duration.ZERO, () => pumpEventQueue(times - 1));
248 } 242 }
249 243
250 /// Like [new Future], but avoids dartbug.com/11911 by using async/await under 244 /// Like [new Future], but avoids dartbug.com/11911 by using async/await under
251 /// the covers. 245 /// the covers.
252 Future/*<T>*/ newFuture/*<T>*/(/*=T*/ callback()) async => await callback(); 246 Future<T> newFuture<T>(T callback()) async => await callback();
253 247
254 /// Returns a buffered stream that will emit the same values as the stream 248 /// Returns a buffered stream that will emit the same values as the stream
255 /// returned by [future] once [future] completes. 249 /// returned by [future] once [future] completes.
256 /// 250 ///
257 /// If [future] completes to an error, the return value will emit that error and 251 /// If [future] completes to an error, the return value will emit that error and
258 /// then close. 252 /// then close.
259 /// 253 ///
260 /// If [broadcast] is true, a broadcast stream is returned. This assumes that 254 /// If [broadcast] is true, a broadcast stream is returned. This assumes that
261 /// the stream returned by [future] will be a broadcast stream as well. 255 /// the stream returned by [future] will be a broadcast stream as well.
262 /// [broadcast] defaults to false. 256 /// [broadcast] defaults to false.
263 Stream/*<T>*/ futureStream/*<T>*/(Future<Stream/*<T>*/> future, 257 Stream<T> futureStream<T>(Future<Stream<T>> future, {bool broadcast: false}) {
264 {bool broadcast: false}) { 258 StreamSubscription<T> subscription;
265 StreamSubscription/*<T>*/ subscription; 259 StreamController<T> controller;
266 StreamController/*<T>*/ controller;
267 260
268 future = DelegatingFuture.typed(future.catchError((e, stackTrace) { 261 future = DelegatingFuture.typed(future.catchError((e, stackTrace) {
269 // Since [controller] is synchronous, it's likely that emitting an error 262 // Since [controller] is synchronous, it's likely that emitting an error
270 // will cause it to be cancelled before we call close. 263 // will cause it to be cancelled before we call close.
271 if (controller != null) controller.addError(e, stackTrace); 264 if (controller != null) controller.addError(e, stackTrace);
272 if (controller != null) controller.close(); 265 if (controller != null) controller.close();
273 controller = null; 266 controller = null;
274 })); 267 }));
275 268
276 onListen() { 269 onListen() {
277 future.then((stream) { 270 future.then((stream) {
278 if (controller == null) return; 271 if (controller == null) return;
279 subscription = stream.listen( 272 subscription = stream.listen(controller.add,
280 controller.add, 273 onError: controller.addError, onDone: controller.close);
281 onError: controller.addError,
282 onDone: controller.close);
283 }); 274 });
284 } 275 }
285 276
286 onCancel() { 277 onCancel() {
287 if (subscription != null) subscription.cancel(); 278 if (subscription != null) subscription.cancel();
288 subscription = null; 279 subscription = null;
289 controller = null; 280 controller = null;
290 } 281 }
291 282
292 if (broadcast) { 283 if (broadcast) {
293 controller = new StreamController/*<T>*/.broadcast( 284 controller = new StreamController<T>.broadcast(
294 sync: true, onListen: onListen, onCancel: onCancel); 285 sync: true, onListen: onListen, onCancel: onCancel);
295 } else { 286 } else {
296 controller = new StreamController/*<T>*/( 287 controller = new StreamController<T>(
297 sync: true, onListen: onListen, onCancel: onCancel); 288 sync: true, onListen: onListen, onCancel: onCancel);
298 } 289 }
299 return controller.stream; 290 return controller.stream;
300 } 291 }
301 292
302 /// Returns a [Stream] that will emit the same values as the stream returned by 293 /// Returns a [Stream] that will emit the same values as the stream returned by
303 /// [callback]. 294 /// [callback].
304 /// 295 ///
305 /// [callback] will only be called when the returned [Stream] gets a subscriber. 296 /// [callback] will only be called when the returned [Stream] gets a subscriber.
306 Stream/*<T>*/ callbackStream/*<T>*/(Stream/*<T>*/ callback()) { 297 Stream<T> callbackStream<T>(Stream<T> callback()) {
307 StreamSubscription/*<T>*/ subscription; 298 StreamSubscription<T> subscription;
308 StreamController/*<T>*/ controller; 299 StreamController<T> controller;
309 controller = new StreamController/*<T>*/(onListen: () { 300 controller = new StreamController<T>(
310 subscription = callback().listen(controller.add, 301 onListen: () {
311 onError: controller.addError, 302 subscription = callback().listen(controller.add,
312 onDone: controller.close); 303 onError: controller.addError, onDone: controller.close);
313 }, 304 },
314 onCancel: () => subscription.cancel(), 305 onCancel: () => subscription.cancel(),
315 onPause: () => subscription.pause(), 306 onPause: () => subscription.pause(),
316 onResume: () => subscription.resume(), 307 onResume: () => subscription.resume(),
317 sync: true); 308 sync: true);
318 return controller.stream; 309 return controller.stream;
319 } 310 }
320 311
321 /// Creates a single-subscription stream from a broadcast stream. 312 /// Creates a single-subscription stream from a broadcast stream.
322 /// 313 ///
323 /// The returned stream will enqueue events from [broadcast] until a listener is 314 /// The returned stream will enqueue events from [broadcast] until a listener is
324 /// attached, then pipe events to that listener. 315 /// attached, then pipe events to that listener.
325 Stream/*<T>*/ broadcastToSingleSubscription/*<T>*/(Stream/*<T>*/ broadcast) { 316 Stream<T> broadcastToSingleSubscription<T>(Stream<T> broadcast) {
326 if (!broadcast.isBroadcast) return broadcast; 317 if (!broadcast.isBroadcast) return broadcast;
327 318
328 // TODO(nweiz): Implement this using a transformer when issues 18588 and 18586 319 // TODO(nweiz): Implement this using a transformer when issues 18588 and 18586
329 // are fixed. 320 // are fixed.
330 var subscription; 321 var subscription;
331 var controller = new StreamController/*<T>*/( 322 var controller =
332 onCancel: () => subscription.cancel()); 323 new StreamController<T>(onCancel: () => subscription.cancel());
333 subscription = broadcast.listen(controller.add, 324 subscription = broadcast.listen(controller.add,
334 onError: controller.addError, 325 onError: controller.addError, onDone: controller.close);
335 onDone: controller.close);
336 return controller.stream; 326 return controller.stream;
337 } 327 }
338 328
339 /// A regular expression to match the exception prefix that some exceptions' 329 /// A regular expression to match the exception prefix that some exceptions'
340 /// [Object.toString] values contain. 330 /// [Object.toString] values contain.
341 final _exceptionPrefix = new RegExp(r'^([A-Z][a-zA-Z]*)?(Exception|Error): '); 331 final _exceptionPrefix = new RegExp(r'^([A-Z][a-zA-Z]*)?(Exception|Error): ');
342 332
343 /// Get a string description of an exception. 333 /// Get a string description of an exception.
344 /// 334 ///
345 /// Many exceptions include the exception class name at the beginning of their 335 /// Many exceptions include the exception class name at the beginning of their
346 /// [toString], so we remove that if it exists. 336 /// [toString], so we remove that if it exists.
347 String getErrorMessage(error) => 337 String getErrorMessage(error) =>
348 error.toString().replaceFirst(_exceptionPrefix, ''); 338 error.toString().replaceFirst(_exceptionPrefix, '');
349 339
350 /// Returns a human-friendly representation of [duration]. 340 /// Returns a human-friendly representation of [duration].
351 String niceDuration(Duration duration) { 341 String niceDuration(Duration duration) {
352 var result = duration.inMinutes > 0 ? "${duration.inMinutes}:" : ""; 342 var result = duration.inMinutes > 0 ? "${duration.inMinutes}:" : "";
353 343
354 var s = duration.inSeconds % 59; 344 var s = duration.inSeconds % 59;
355 var ms = (duration.inMilliseconds % 1000) ~/ 100; 345 var ms = (duration.inMilliseconds % 1000) ~/ 100;
356 return result + "$s.${ms}s"; 346 return result + "$s.${ms}s";
357 } 347 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698