| Index: lib/src/utils.dart
|
| diff --git a/lib/src/utils.dart b/lib/src/utils.dart
|
| index c499ac07195fb6bee78335a34996ac3f8683fb90..9e77a42fc6958b2821d492e93aad1c8b69916b9a 100644
|
| --- a/lib/src/utils.dart
|
| +++ b/lib/src/utils.dart
|
| @@ -5,6 +5,7 @@
|
| import 'dart:async';
|
| import 'dart:convert';
|
| import 'dart:math' as math;
|
| +import 'dart:typed_data';
|
|
|
| import 'package:async/async.dart' hide StreamQueue;
|
| import 'package:path/path.dart' as p;
|
| @@ -193,28 +194,26 @@ List flatten(Iterable nested) {
|
|
|
| /// Creates a new map from [map] with new keys and values.
|
| ///
|
| -/// The return values of [key] are used as the keys and the return values of
|
| -/// [value] are used as the values for the new map.
|
| -///
|
| -/// [key] defaults to returning the original key and [value] defaults to
|
| -/// returning the original value.
|
| -Map mapMap(Map map, {key(key, value), value(key, value)}) {
|
| - if (key == null) key = (key, _) => key;
|
| - if (value == null) value = (_, value) => value;
|
| -
|
| - var result = {};
|
| - map.forEach((mapKey, mapValue) {
|
| - result[key(mapKey, mapValue)] = value(mapKey, mapValue);
|
| - });
|
| - return result;
|
| +/// The return values of [keyFn] are used as the keys and the return values of
|
| +/// [valueFn] are used as the values for the new map.
|
| +Map/*<K2, V2>*/ mapMap/*<K1, V1, K2, V2>*/(Map/*<K1, V1>*/ map,
|
| + {/*=K2*/ key(/*=K1*/ key, /*=V1*/ value),
|
| + /*=V2*/ value(/*=K1*/ key, /*=V1*/ value)}) {
|
| + key ??= (key, _) => key as dynamic/*=K2*/;
|
| + value ??= (_, value) => value as dynamic/*=V2*/;
|
| +
|
| + return new Map.fromIterable(map.keys,
|
| + key: (mapKey) => key(mapKey as dynamic/*=K1*/, map[mapKey]),
|
| + value: (mapKey) => value(mapKey as dynamic/*=K1*/, map[mapKey]));
|
| }
|
|
|
| /// Returns a new map with all values in both [map1] and [map2].
|
| ///
|
| /// If there are conflicting keys, [value] is used to merge them. If it's
|
| /// not passed, [map2]'s value wins.
|
| -Map mergeMaps(Map map1, Map map2, {value(value1, value2)}) {
|
| - var result = new Map.from(map1);
|
| +Map/*<K, V>*/ mergeMaps/*<K, V>*/(Map/*<K, V>*/ map1, Map/*<K, V>*/ map2,
|
| + {/*=V*/ value(/*=V*/ value1, /*=V*/ value2)}) {
|
| + var result = new Map/*<K, V>*/.from(map1);
|
| map2.forEach((key, mapValue) {
|
| if (value == null || !result.containsKey(key)) {
|
| result[key] = mapValue;
|
| @@ -295,41 +294,6 @@ String niceDuration(Duration duration) {
|
| return buffer.toString();
|
| }
|
|
|
| -/// Merges [streams] into a single stream that emits events from all sources.
|
| -Stream mergeStreams(Iterable<Stream> streamIter) {
|
| - var streams = streamIter.toList();
|
| -
|
| - var subscriptions = new Set();
|
| - var controller;
|
| - controller = new StreamController(sync: true, onListen: () {
|
| - for (var stream in streams) {
|
| - var subscription;
|
| - subscription = stream.listen(
|
| - controller.add,
|
| - onError: controller.addError,
|
| - onDone: () {
|
| - subscriptions.remove(subscription);
|
| - if (subscriptions.isEmpty) controller.close();
|
| - });
|
| - subscriptions.add(subscription);
|
| - }
|
| - }, onPause: () {
|
| - for (var subscription in subscriptions) {
|
| - subscription.pause();
|
| - }
|
| - }, onResume: () {
|
| - for (var subscription in subscriptions) {
|
| - subscription.resume();
|
| - }
|
| - }, onCancel: () {
|
| - for (var subscription in subscriptions) {
|
| - subscription.cancel();
|
| - }
|
| - });
|
| -
|
| - return controller.stream;
|
| -}
|
| -
|
| /// Returns the first value [stream] emits, or `null` if [stream] closes before
|
| /// emitting a value.
|
| Future maybeFirst(Stream stream) {
|
| @@ -376,14 +340,16 @@ CancelableOperation cancelableNext(StreamQueue queue) {
|
| ///
|
| /// If the subscription is canceled, any pending operations are canceled as
|
| /// well.
|
| -Stream inCompletionOrder(Iterable<CancelableOperation> operations) {
|
| +Stream/*<T>*/ inCompletionOrder/*<T>*/(
|
| + Iterable<CancelableOperation/*<T>*/> operations) {
|
| var operationSet = operations.toSet();
|
| - var controller = new StreamController(sync: true, onCancel: () {
|
| + var controller = new StreamController/*<T>*/(sync: true, onCancel: () {
|
| return Future.wait(operationSet.map((operation) => operation.cancel()));
|
| });
|
|
|
| for (var operation in operationSet) {
|
| - operation.value.then(controller.add).catchError(controller.addError)
|
| + operation.value.then((value) => controller.add(value))
|
| + .catchError(controller.addError)
|
| .whenComplete(() {
|
| operationSet.remove(operation);
|
| if (operationSet.isEmpty) controller.close();
|
| @@ -417,9 +383,9 @@ void invoke(fn()) {
|
| /// passed to [CryptoUtils.bytesToBase64].
|
| String randomBase64(int bytes, {int seed}) {
|
| var random = new math.Random(seed);
|
| - var data = [];
|
| + var data = new Uint8List(bytes);
|
| for (var i = 0; i < bytes; i++) {
|
| - data.add(random.nextInt(256));
|
| + data[i] = random.nextInt(256);
|
| }
|
| return BASE64.encode(data);
|
| }
|
|
|