LCOV - code coverage report
Current view: top level - async-1.13.3/lib/src - stream_completer.dart (source / functions) Hit Total Coverage
Test: coverage.lcov Lines: 0 30 0.0 %
Date: 2017-10-10 20:17:03 Functions: 0 0 -

          Line data    Source code
       1             : // Copyright (c) 2015, 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 single-subscription [stream] where the contents are provided later.
       8             : ///
       9             : /// It is generally recommended that you never create a `Future<Stream>`
      10             : /// because you can just directly create a stream that doesn't do anything
      11             : /// until it's ready to do so.
      12             : /// This class can be used to create such a stream.
      13             : ///
      14             : /// The [stream] is a normal stream that you can listen to immediately,
      15             : /// but until either [setSourceStream] or [setEmpty] is called,
      16             : /// the stream won't produce any events.
      17             : ///
      18             : /// The same effect can be achieved by using a [StreamController]
      19             : /// and adding the stream using `addStream` when both
      20             : /// the controller's stream is listened to and the source stream is ready.
      21             : /// This class attempts to shortcut some of the overhead when possible.
      22             : /// For example, if the [stream] is only listened to
      23             : /// after the source stream has been set,
      24             : /// the listen is performed directly on the source stream.
      25             : class StreamCompleter<T> {
      26             :   /// The stream doing the actual work, is returned by [stream].
      27             :   final _stream = new _CompleterStream<T>();
      28             : 
      29             :   /// Convert a `Future<Stream>` to a `Stream`.
      30             :   ///
      31             :   /// This creates a stream using a stream completer,
      32             :   /// and sets the source stream to the result of the future when the
      33             :   /// future completes.
      34             :   ///
      35             :   /// If the future completes with an error, the returned stream will
      36             :   /// instead contain just that error.
      37             :   static Stream<T> fromFuture<T>(Future<Stream<T>> streamFuture) {
      38           0 :     var completer = new StreamCompleter<T>();
      39           0 :     streamFuture.then(completer.setSourceStream, onError: completer.setError);
      40           0 :     return completer.stream;
      41             :   }
      42             : 
      43             :   /// The stream of this completer.
      44             :   ///
      45             :   /// This stream is always a single-subscription stream.
      46             :   ///
      47             :   /// When a source stream is provided, its events will be forwarded to
      48             :   /// listeners on this stream.
      49             :   ///
      50             :   /// The stream can be listened either before or after a source stream
      51             :   /// is set.
      52           0 :   Stream<T> get stream => _stream;
      53             : 
      54             :   /// Set a stream as the source of events for the [StreamCompleter]'s
      55             :   /// [stream].
      56             :   ///
      57             :   /// The completer's `stream` will act exactly as [sourceStream].
      58             :   ///
      59             :   /// If the source stream is set before [stream] is listened to,
      60             :   /// the listen call on [stream] is forwarded directly to [sourceStream].
      61             :   ///
      62             :   /// If [stream] is listened to before setting the source stream,
      63             :   /// an intermediate subscription is created. It looks like a completely
      64             :   /// normal subscription, and can be paused or canceled, but it won't
      65             :   /// produce any events until a source stream is provided.
      66             :   ///
      67             :   /// If the `stream` subscription is canceled before a source stream is set,
      68             :   /// the source stream will be listened to and immediately canceled again.
      69             :   ///
      70             :   /// Otherwise, when the source stream is then set,
      71             :   /// it is immediately listened to, and its events are forwarded to the
      72             :   /// existing subscription.
      73             :   ///
      74             :   /// Any one of [setSourceStream], [setEmpty], and [setError] may be called at
      75             :   /// most once. Trying to call any of them again will fail.
      76             :   void setSourceStream(Stream<T> sourceStream) {
      77           0 :     if (_stream._isSourceStreamSet) {
      78           0 :       throw new StateError("Source stream already set");
      79             :     }
      80           0 :     _stream._setSourceStream(sourceStream);
      81             :   }
      82             : 
      83             :   /// Equivalent to setting an empty stream using [setSourceStream].
      84             :   ///
      85             :   /// Any one of [setSourceStream], [setEmpty], and [setError] may be called at
      86             :   /// most once. Trying to call any of them again will fail.
      87             :   void setEmpty() {
      88           0 :     if (_stream._isSourceStreamSet) {
      89           0 :       throw new StateError("Source stream already set");
      90             :     }
      91           0 :     _stream._setEmpty();
      92             :   }
      93             : 
      94             :   /// Completes this to a stream that emits [error] and then closes.
      95             :   ///
      96             :   /// This is useful when the process of creating the data for the stream fails.
      97             :   ///
      98             :   /// Any one of [setSourceStream], [setEmpty], and [setError] may be called at
      99             :   /// most once. Trying to call any of them again will fail.
     100             :   void setError(error, [StackTrace stackTrace]) {
     101           0 :     setSourceStream(new Stream.fromFuture(new Future.error(error, stackTrace)));
     102             :   }
     103             : }
     104             : 
     105             : /// Stream completed by [StreamCompleter].
     106             : class _CompleterStream<T> extends Stream<T> {
     107             :   /// Controller for an intermediate stream.
     108             :   ///
     109             :   /// Created if the user listens on this stream before the source stream
     110             :   /// is set, or if using [_setEmpty] so there is no source stream.
     111             :   StreamController<T> _controller;
     112             : 
     113             :   /// Source stream for the events provided by this stream.
     114             :   ///
     115             :   /// Set when the completer sets the source stream using [_setSourceStream]
     116             :   /// or [_setEmpty].
     117             :   Stream<T> _sourceStream;
     118             : 
     119             :   StreamSubscription<T> listen(onData(T data),
     120             :       {Function onError, void onDone(), bool cancelOnError}) {
     121           0 :     if (_controller == null) {
     122           0 :       if (_sourceStream != null && !_sourceStream.isBroadcast) {
     123             :         // If the source stream is itself single subscription,
     124             :         // just listen to it directly instead of creating a controller.
     125           0 :         return _sourceStream.listen(onData,
     126             :             onError: onError, onDone: onDone, cancelOnError: cancelOnError);
     127             :       }
     128           0 :       _createController();
     129           0 :       if (_sourceStream != null) {
     130           0 :         _linkStreamToController();
     131             :       }
     132             :     }
     133           0 :     return _controller.stream.listen(onData,
     134             :         onError: onError, onDone: onDone, cancelOnError: cancelOnError);
     135             :   }
     136             : 
     137             :   /// Whether a source stream has been set.
     138             :   ///
     139             :   /// Used to throw an error if trying to set a source stream twice.
     140           0 :   bool get _isSourceStreamSet => _sourceStream != null;
     141             : 
     142             :   /// Sets the source stream providing the events for this stream.
     143             :   ///
     144             :   /// If set before the user listens, listen calls will be directed directly
     145             :   /// to the source stream. If the user listenes earlier, and intermediate
     146             :   /// stream is created using a stream controller, and the source stream is
     147             :   /// linked into that stream later.
     148             :   void _setSourceStream(Stream<T> sourceStream) {
     149             :     assert(_sourceStream == null);
     150           0 :     _sourceStream = sourceStream;
     151           0 :     if (_controller != null) {
     152             :       // User has already listened, so provide the data through controller.
     153           0 :       _linkStreamToController();
     154             :     }
     155             :   }
     156             : 
     157             :   /// Links source stream to controller when both are available.
     158             :   void _linkStreamToController() {
     159             :     assert(_controller != null);
     160             :     assert(_sourceStream != null);
     161           0 :     _controller
     162           0 :         .addStream(_sourceStream, cancelOnError: false)
     163           0 :         .whenComplete(_controller.close);
     164             :   }
     165             : 
     166             :   /// Sets an empty source stream.
     167             :   ///
     168             :   /// Uses [_controller] for the stream, then closes the controller
     169             :   /// immediately.
     170             :   void _setEmpty() {
     171             :     assert(_sourceStream == null);
     172           0 :     if (_controller == null) {
     173           0 :       _createController();
     174             :     }
     175           0 :     _sourceStream = _controller.stream; // Mark stream as set.
     176           0 :     _controller.close();
     177             :   }
     178             : 
     179             :   // Creates the [_controller].
     180             :   void _createController() {
     181             :     assert(_controller == null);
     182           0 :     _controller = new StreamController<T>(sync: true);
     183             :   }
     184             : }

Generated by: LCOV version 1.13