LCOV - code coverage report
Current view: top level - async-2.5.0/lib/src - stream_zip.dart (source / functions) Hit Total Coverage
Test: lcov.info Lines: 0 41 0.0 %
Date: 2021-11-28 14:37:50 Functions: 0 0 -

          Line data    Source code
       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
       3             : // BSD-style license that can be found in the LICENSE file.
       4             : 
       5             : import 'dart:async';
       6             : 
       7             : /// A stream that combines the values of other streams.
       8             : ///
       9             : /// This emits lists of collected values from each input stream. The first list
      10             : /// contains the first value emitted by each stream, the second contains the
      11             : /// second value, and so on. The lists have the same ordering as the iterable
      12             : /// passed to [new StreamZip].
      13             : ///
      14             : /// Any errors from any of the streams are forwarded directly to this stream.
      15             : class StreamZip<T> extends Stream<List<T>> {
      16             :   final Iterable<Stream<T>> _streams;
      17             : 
      18           0 :   StreamZip(Iterable<Stream<T>> streams) : _streams = streams;
      19             : 
      20           0 :   @override
      21             :   StreamSubscription<List<T>> listen(void Function(List<T>)? onData,
      22             :       {Function? onError, void Function()? onDone, bool? cancelOnError}) {
      23             :     cancelOnError = identical(true, cancelOnError);
      24           0 :     var subscriptions = <StreamSubscription<T>>[];
      25             :     late StreamController<List<T>> controller;
      26             :     late List<T?> current;
      27             :     var dataCount = 0;
      28             : 
      29             :     /// Called for each data from a subscription in [subscriptions].
      30           0 :     void handleData(int index, T data) {
      31           0 :       current[index] = data;
      32           0 :       dataCount++;
      33           0 :       if (dataCount == subscriptions.length) {
      34           0 :         var data = List<T>.from(current);
      35           0 :         current = List<T?>.filled(subscriptions.length, null);
      36             :         dataCount = 0;
      37           0 :         for (var i = 0; i < subscriptions.length; i++) {
      38           0 :           if (i != index) subscriptions[i].resume();
      39             :         }
      40           0 :         controller.add(data);
      41             :       } else {
      42           0 :         subscriptions[index].pause();
      43             :       }
      44             :     }
      45             : 
      46             :     /// Called for each error from a subscription in [subscriptions].
      47             :     /// Except if [cancelOnError] is true, in which case the function below
      48             :     /// is used instead.
      49           0 :     void handleError(Object error, StackTrace stackTrace) {
      50           0 :       controller.addError(error, stackTrace);
      51             :     }
      52             : 
      53             :     /// Called when a subscription has an error and [cancelOnError] is true.
      54             :     ///
      55             :     /// Prematurely cancels all subscriptions since we know that we won't
      56             :     /// be needing any more values.
      57           0 :     void handleErrorCancel(Object error, StackTrace stackTrace) {
      58           0 :       for (var i = 0; i < subscriptions.length; i++) {
      59           0 :         subscriptions[i].cancel();
      60             :       }
      61           0 :       controller.addError(error, stackTrace);
      62             :     }
      63             : 
      64           0 :     void handleDone() {
      65           0 :       for (var i = 0; i < subscriptions.length; i++) {
      66           0 :         subscriptions[i].cancel();
      67             :       }
      68           0 :       controller.close();
      69             :     }
      70             : 
      71             :     try {
      72           0 :       for (var stream in _streams) {
      73           0 :         var index = subscriptions.length;
      74           0 :         subscriptions.add(stream.listen((data) {
      75             :           handleData(index, data);
      76             :         },
      77             :             onError: cancelOnError ? handleError : handleErrorCancel,
      78             :             onDone: handleDone,
      79             :             cancelOnError: cancelOnError));
      80             :       }
      81             :     } catch (e) {
      82           0 :       for (var i = subscriptions.length - 1; i >= 0; i--) {
      83           0 :         subscriptions[i].cancel();
      84             :       }
      85             :       rethrow;
      86             :     }
      87             : 
      88           0 :     current = List<T?>.filled(subscriptions.length, null);
      89             : 
      90           0 :     controller = StreamController<List<T>>(onPause: () {
      91           0 :       for (var i = 0; i < subscriptions.length; i++) {
      92             :         // This may pause some subscriptions more than once.
      93             :         // These will not be resumed by onResume below, but must wait for the
      94             :         // next round.
      95           0 :         subscriptions[i].pause();
      96             :       }
      97           0 :     }, onResume: () {
      98           0 :       for (var i = 0; i < subscriptions.length; i++) {
      99           0 :         subscriptions[i].resume();
     100             :       }
     101           0 :     }, onCancel: () {
     102           0 :       for (var i = 0; i < subscriptions.length; i++) {
     103             :         // Canceling more than once is safe.
     104           0 :         subscriptions[i].cancel();
     105             :       }
     106             :     });
     107             : 
     108           0 :     if (subscriptions.isEmpty) {
     109           0 :       controller.close();
     110             :     }
     111           0 :     return controller.stream.listen(onData,
     112             :         onError: onError, onDone: onDone, cancelOnError: cancelOnError);
     113             :   }
     114             : }

Generated by: LCOV version 1.14