// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

// @dart = 2.5

part of dart.async;

// -------------------------------------------------------------------
// Core Stream types
// -------------------------------------------------------------------

typedef void _TimerCallback();

/**
 * A source of asynchronous data events.
 *
 * A Stream provides a way to receive a sequence of events.
 * Each event is either a data event, also called an *element* of the stream,
 * or an error event, which is a notification that something has failed.
 * When a stream has emitted all its event,
 * a single "done" event will notify the listener that the end has been reached.
 *
 * You [listen] on a stream to make it start generating events,
 * and to set up listeners that receive the events.
 * When you listen, you receive a [StreamSubscription] object
 * which is the active object providing the events,
 * and which can be used to stop listening again,
 * or to temporarily pause events from the subscription.
 *
 * There are two kinds of streams: "Single-subscription" streams and
 * "broadcast" streams.
 *
 * *A single-subscription stream* allows only a single listener during the whole
 * lifetime of the stream.
 * It doesn't start generating events until it has a listener,
 * and it stops sending events when the listener is unsubscribed,
 * even if the source of events could still provide more.
 *
 * Listening twice on a single-subscription stream is not allowed, even after
 * the first subscription has been canceled.
 *
 * Single-subscription streams are generally used for streaming chunks of
 * larger contiguous data like file I/O.
 *
 * *A broadcast stream* allows any number of listeners, and it fires
 * its events when they are ready, whether there are listeners or not.
 *
 * Broadcast streams are used for independent events/observers.
 *
 * If several listeners want to listen to a single subscription stream,
 * use [asBroadcastStream] to create a broadcast stream on top of the
 * non-broadcast stream.
 *
 * On either kind of stream, stream transformations, such as [where] and
 * [skip], return the same type of stream as the one the method was called on,
 * unless otherwise noted.
 *
 * When an event is fired, the listener(s) at that time will receive the event.
 * If a listener is added to a broadcast stream while an event is being fired,
 * that listener will not receive the event currently being fired.
 * If a listener is canceled, it immediately stops receiving events.
 * Listening on a broadcast stream can be treated as listening on a new stream
 * containing only the events that have not yet been emitted when the [listen]
 * call occurs.
 * For example, the [first] getter listens to the stream, then returns the first
 * event that listener receives.
 * This is not necessarily the first even emitted by the stream, but the first
 * of the *remaining* events of the broadcast stream.
 *
 * When the "done" event is fired, subscribers are unsubscribed before
 * receiving the event. After the event has been sent, the stream has no
 * subscribers. Adding new subscribers to a broadcast stream after this point
 * is allowed, but they will just receive a new "done" event as soon
 * as possible.
 *
 * Stream subscriptions always respect "pause" requests. If necessary they need
 * to buffer their input, but often, and preferably, they can simply request
 * their input to pause too.
 *
 * The default implementation of [isBroadcast] returns false.
 * A broadcast stream inheriting from [Stream] must override [isBroadcast]
 * to return `true`.
 */
abstract class Stream<T> {
  Stream();

  /**
   * Internal use only. We do not want to promise that Stream stays const.
   *
   * If mixins become compatible with const constructors, we may use a
   * stream mixin instead of extending Stream from a const class.
   */
  const Stream._internal();

  /**
   * Creates an empty broadcast stream.
   *
   * This is a stream which does nothing except sending a done event
   * when it's listened to.
   */
  const factory Stream.empty() = _EmptyStream<T>;

  /**
   * Creates a stream which emits a single data event before completing.
   *
   * This stream emits a single data event of [value]
   * and then completes with a done event.
   *
   * Example:
   * ```dart
   * Future<void> printThings(Stream<String> data) async {
   *   await for (var x in data) {
   *     print(x);
   *   }
   * }
   * printThings(Stream<String>.value("ok")); // prints "ok".
   * ```
   *
   * The returned stream is effectively equivalent to one created by
   * `(() async* { yield value; } ())` or `Future<T>.value(value).asStream()`.
   */
  @Since("2.5")
  factory Stream.value(T value) =>
      (_AsyncStreamController<T>(null, null, null, null)
            .._add(value)
            .._closeUnchecked())
          .stream;

  /**
   * Creates a stream which emits a single error event before completing.
   *
   * This stream emits a single error event of [error] and [stackTrace]
   * and then completes with a done event.
   *
   * Example:
   * ```dart
   * Future<void> tryThings(Stream<int> data) async {
   *   try {
   *     await for (var x in data) {
   *       print("Data: $x");
   *     }
   *   } catch (e) {
   *     print(e);
   *   }
   * }
   * tryThings(Stream<int>.error("Error")); // prints "Error".
   * ```
   * The returned stream is effectively equivalent to one created by
   * `Future<T>.error(error, stackTrace).asStream()`, by or
   * `(() async* { throw error; } ())`, except that you can control the
   * stack trace as well.
   */
  @Since("2.5")
  factory Stream.error(Object error, [StackTrace stackTrace]) =>
      (_AsyncStreamController<T>(null, null, null, null)
            .._addError(error, stackTrace)
            .._closeUnchecked())
          .stream;

  /**
   * Creates a new single-subscription stream from the future.
   *
   * When the future completes, the stream will fire one event, either
   * data or error, and then close with a done-event.
   */
  factory Stream.fromFuture(Future<T> future) {
    // Use the controller's buffering to fill in the value even before
    // the stream has a listener. For a single value, it's not worth it
    // to wait for a listener before doing the `then` on the future.
    _StreamController<T> controller =
        new _SyncStreamController<T>(null, null, null, null);
    future.then((value) {
      controller._add(value);
      controller._closeUnchecked();
    }, onError: (error, stackTrace) {
      controller._addError(error, stackTrace);
      controller._closeUnchecked();
    });
    return controller.stream;
  }

  /**
   * Create a stream from a group of futures.
   *
   * The stream reports the results of the futures on the stream in the order
   * in which the futures complete.
   * Each future provides either a data event or an error event,
   * depending on how the future completes.
   *
   * If some futures have already completed when `Stream.fromFutures` is called,
   * their results will be emitted in some unspecified order.
   *
   * When all futures have completed, the stream is closed.
   *
   * If [futures] is empty, the stream closes as soon as possible.
   */
  factory Stream.fromFutures(Iterable<Future<T>> futures) {
    _StreamController<T> controller =
        new _SyncStreamController<T>(null, null, null, null);
    int count = 0;
    // Declare these as variables holding closures instead of as
    // function declarations.
    // This avoids creating a new closure from the functions for each future.
    var onValue = (T value) {
      if (!controller.isClosed) {
        controller._add(value);
        if (--count == 0) controller._closeUnchecked();
      }
    };
    var onError = (error, StackTrace stack) {
      if (!controller.isClosed) {
        controller._addError(error, stack);
        if (--count == 0) controller._closeUnchecked();
      }
    };
    // The futures are already running, so start listening to them immediately
    // (instead of waiting for the stream to be listened on).
    // If we wait, we might not catch errors in the futures in time.
    for (var future in futures) {
      count++;
      future.then(onValue, onError: onError);
    }
    // Use schedule microtask since controller is sync.
    if (count == 0) scheduleMicrotask(controller.close);
    return controller.stream;
  }

  /**
   * Creates a single-subscription stream that gets its data from [elements].
   *
   * The iterable is iterated when the stream receives a listener, and stops
   * iterating if the listener cancels the subscription, or if the
   * [Iterator.moveNext] method returns `false` or throws.
   * Iteration is suspended while the stream subscription is paused.
   *
   * If calling [Iterator.moveNext] on `elements.iterator` throws,
   * the stream emits that error and then it closes.
   * If reading [Iterator.current] on `elements.iterator` throws,
   * the stream emits that error, but keeps iterating.
   */
  factory Stream.fromIterable(Iterable<T> elements) {
    return new _GeneratedStreamImpl<T>(
        () => new _IterablePendingEvents<T>(elements));
  }

  /**
   * Creates a stream that repeatedly emits events at [period] intervals.
   *
   * The event values are computed by invoking [computation]. The argument to
   * this callback is an integer that starts with 0 and is incremented for
   * every event.
   *
   * If [computation] is omitted the event values will all be `null`.
   */
  factory Stream.periodic(Duration period,
      [T computation(int computationCount)]) {
    Timer timer;
    int computationCount = 0;
    StreamController<T> controller;
    // Counts the time that the Stream was running (and not paused).
    Stopwatch watch = new Stopwatch();

    void sendEvent() {
      watch.reset();
      T data;
      if (computation != null) {
        try {
          data = computation(computationCount++);
        } catch (e, s) {
          controller.addError(e, s);
          return;
        }
      }
      controller.add(data);
    }

    void startPeriodicTimer() {
      assert(timer == null);
      timer = new Timer.periodic(period, (Timer timer) {
        sendEvent();
      });
    }

    controller = new StreamController<T>(
        sync: true,
        onListen: () {
          watch.start();
          startPeriodicTimer();
        },
        onPause: () {
          timer.cancel();
          timer = null;
          watch.stop();
        },
        onResume: () {
          assert(timer == null);
          Duration elapsed = watch.elapsed;
          watch.start();
          timer = new Timer(period - elapsed, () {
            timer = null;
            startPeriodicTimer();
            sendEvent();
          });
        },
        onCancel: () {
          if (timer != null) timer.cancel();
          timer = null;
          return Future._nullFuture;
        });
    return controller.stream;
  }

  /**
   * Creates a stream where all events of an existing stream are piped through
   * a sink-transformation.
   *
   * The given [mapSink] closure is invoked when the returned stream is
   * listened to. All events from the [source] are added into the event sink
   * that is returned from the invocation. The transformation puts all
   * transformed events into the sink the [mapSink] closure received during
   * its invocation. Conceptually the [mapSink] creates a transformation pipe
   * with the input sink being the returned [EventSink] and the output sink
   * being the sink it received.
   *
   * This constructor is frequently used to build transformers.
   *
   * Example use for a duplicating transformer:
   *
   *     class DuplicationSink implements EventSink<String> {
   *       final EventSink<String> _outputSink;
   *       DuplicationSink(this._outputSink);
   *
   *       void add(String data) {
   *         _outputSink.add(data);
   *         _outputSink.add(data);
   *       }
   *
   *       void addError(e, [st]) { _outputSink.addError(e, st); }
   *       void close() { _outputSink.close(); }
   *     }
   *
   *     class DuplicationTransformer extends StreamTransformerBase<String, String> {
   *       // Some generic types omitted for brevity.
   *       Stream bind(Stream stream) => new Stream<String>.eventTransformed(
   *           stream,
   *           (EventSink sink) => new DuplicationSink(sink));
   *     }
   *
   *     stringStream.transform(new DuplicationTransformer());
   *
   * The resulting stream is a broadcast stream if [source] is.
   */
  factory Stream.eventTransformed(
      Stream source, EventSink mapSink(EventSink<T> sink)) {
    return new _BoundSinkStream(source, mapSink);
  }

  /**
   * Adapts [source] to be a `Stream<T>`.
   *
   * This allows [source] to be used at the new type, but at run-time it
   * must satisfy the requirements of both the new type and its original type.
   *
   * Data events created by the source stream must also be instances of [T].
   */
  static Stream<T> castFrom<S, T>(Stream<S> source) =>
      new CastStream<S, T>(source);

  /**
   * Whether this stream is a broadcast stream.
   */
  bool get isBroadcast => false;

  /**
   * Returns a multi-subscription stream that produces the same events as this.
   *
   * The returned stream will subscribe to this stream when its first
   * subscriber is added, and will stay subscribed until this stream ends,
   * or a callback cancels the subscription.
   *
   * If [onListen] is provided, it is called with a subscription-like object
   * that represents the underlying subscription to this stream. It is
   * possible to pause, resume or cancel the subscription during the call
   * to [onListen]. It is not possible to change the event handlers, including
   * using [StreamSubscription.asFuture].
   *
   * If [onCancel] is provided, it is called in a similar way to [onListen]
   * when the returned stream stops having listener. If it later gets
   * a new listener, the [onListen] function is called again.
   *
   * Use the callbacks, for example, for pausing the underlying subscription
   * while having no subscribers to prevent losing events, or canceling the
   * subscription when there are no listeners.
   */
  Stream<T> asBroadcastStream(
      {void onListen(StreamSubscription<T> subscription),
      void onCancel(StreamSubscription<T> subscription)}) {
    return new _AsBroadcastStream<T>(this, onListen, onCancel);
  }

  /**
   * Adds a subscription to this stream.
   *
   * Returns a [StreamSubscription] which handles events from this stream using
   * the provided [onData], [onError] and [onDone] handlers.
   * The handlers can be changed on the subscription, but they start out
   * as the provided functions.
   *
   * On each data event from this stream, the subscriber's [onData] handler
   * is called. If [onData] is `null`, nothing happens.
   *
   * On errors from this stream, the [onError] handler is called with the
   * error object and possibly a stack trace.
   *
   * The [onError] callback must be of type `void onError(error)` or
   * `void onError(error, StackTrace stackTrace)`. If [onError] accepts
   * two arguments it is called with the error object and the stack trace
   * (which could be `null` if this stream itself received an error without
   * stack trace).
   * Otherwise it is called with just the error object.
   * If [onError] is omitted, any errors on this stream are considered unhandled,
   * and will be passed to the current [Zone]'s error handler.
   * By default unhandled async errors are treated
   * as if they were uncaught top-level errors.
   *
   * If this stream closes and sends a done event, the [onDone] handler is
   * called. If [onDone] is `null`, nothing happens.
   *
   * If [cancelOnError] is true, the subscription is automatically canceled
   * when the first error event is delivered. The default is `false`.
   *
   * While a subscription is paused, or when it has been canceled,
   * the subscription doesn't receive events and none of the
   * event handler functions are called.
   */
  StreamSubscription<T> listen(void onData(T event),
      {Function onError, void onDone(), bool cancelOnError});

  /**
   * Creates a new stream from this stream that discards some elements.
   *
   * The new stream sends the same error and done events as this stream,
   * but it only sends the data events that satisfy the [test].
   *
   * If the [test] function throws, the data event is dropped and the
   * error is emitted on the returned stream instead.
   *
   * The returned stream is a broadcast stream if this stream is.
   * If a broadcast stream is listened to more than once, each subscription
   * will individually perform the `test`.
   */
  Stream<T> where(bool test(T event)) {
    return new _WhereStream<T>(this, test);
  }

  /**
   * Transforms each element of this stream into a new stream event.
   *
   * Creates a new stream that converts each element of this stream
   * to a new value using the [convert] function, and emits the result.
   *
   * For each data event, `o`, in this stream, the returned stream
   * provides a data event with the value `convert(o)`.
   * If [convert] throws, the returned stream reports it as an error
   * event instead.
   *
   * Error and done events are passed through unchanged to the returned stream.
   *
   * The returned stream is a broadcast stream if this stream is.
   * The [convert] function is called once per data event per listener.
   * If a broadcast stream is listened to more than once, each subscription
   * will individually call [convert] on each data event.
   *
   * Unlike [transform], this method does not treat the stream as
   * chunks of a single value. Instead each event is converted independently
   * of the previous and following events, which may not always be correct.
   * For example, UTF-8 encoding, or decoding, will give wrong results
   * if a surrogate pair, or a multibyte UTF-8 encoding, is split into
   * separate events, and those events are attempted encoded or decoded
   * independently.
   */
  Stream<S> map<S>(S convert(T event)) {
    return new _MapStream<T, S>(this, convert);
  }

  /**
   * Creates a new stream with each data event of this stream asynchronously
   * mapped to a new event.
   *
   * This acts like [map], except that [convert] may return a [Future],
   * and in that case, this stream waits for that future to complete before
   * continuing with its result.
   *
   * The returned stream is a broadcast stream if this stream is.
   */
  Stream<E> asyncMap<E>(FutureOr<E> convert(T event)) {
    _StreamControllerBase<E> controller;
    StreamSubscription<T> subscription;

    void onListen() {
      final add = controller.add;
      assert(controller is _StreamController<E> ||
          controller is _BroadcastStreamController);
      final addError = controller._addError;
      subscription = this.listen((T event) {
        FutureOr<E> newValue;
        try {
          newValue = convert(event);
        } catch (e, s) {
          controller.addError(e, s);
          return;
        }
        if (newValue is Future<E>) {
          subscription.pause();
          newValue
              .then(add, onError: addError)
              .whenComplete(subscription.resume);
        } else {
          controller.add(newValue);
        }
      }, onError: addError, onDone: controller.close);
    }

    if (this.isBroadcast) {
      controller = new StreamController<E>.broadcast(
          onListen: onListen,
          onCancel: () {
            subscription.cancel();
          },
          sync: true);
    } else {
      controller = new StreamController<E>(
          onListen: onListen,
          onPause: () {
            subscription.pause();
          },
          onResume: () {
            subscription.resume();
          },
          onCancel: () => subscription.cancel(),
          sync: true);
    }
    return controller.stream;
  }

  /**
   * Transforms each element into a sequence of asynchronous events.
   *
   * Returns a new stream and for each event of this stream, do the following:
   *
   * * If the event is an error event or a done event, it is emitted directly
   * by the returned stream.
   * * Otherwise it is an element. Then the [convert] function is called
   * with the element as argument to produce a convert-stream for the element.
   * * If that call throws, the error is emitted on the returned stream.
   * * If the call returns `null`, no further action is taken for the elements.
   * * Otherwise, this stream is paused and convert-stream is listened to.
   * Every data and error event of the convert-stream is emitted on the returned
   * stream in the order it is produced.
   * When the convert-stream ends, this stream is resumed.
   *
   * The returned stream is a broadcast stream if this stream is.
   */
  Stream<E> asyncExpand<E>(Stream<E> convert(T event)) {
    _StreamControllerBase<E> controller;
    StreamSubscription<T> subscription;
    void onListen() {
      assert(controller is _StreamController ||
          controller is _BroadcastStreamController);
      subscription = this.listen((T event) {
        Stream<E> newStream;
        try {
          newStream = convert(event);
        } catch (e, s) {
          controller.addError(e, s);
          return;
        }
        if (newStream != null) {
          subscription.pause();
          controller.addStream(newStream).whenComplete(subscription.resume);
        }
      },
          onError: controller._addError, // Avoid Zone error replacement.
          onDone: controller.close);
    }

    if (this.isBroadcast) {
      controller = new StreamController<E>.broadcast(
          onListen: onListen,
          onCancel: () {
            subscription.cancel();
          },
          sync: true);
    } else {
      controller = new StreamController<E>(
          onListen: onListen,
          onPause: () {
            subscription.pause();
          },
          onResume: () {
            subscription.resume();
          },
          onCancel: () => subscription.cancel(),
          sync: true);
    }
    return controller.stream;
  }

  /**
   * Creates a wrapper Stream that intercepts some errors from this stream.
   *
   * If this stream sends an error that matches [test], then it is intercepted
   * by the [onError] function.
   *
   * The [onError] callback must be of type `void onError(error)` or
   * `void onError(error, StackTrace stackTrace)`.
   * The function type determines whether [onError] is invoked with a stack
   * trace argument.
   * The stack trace argument may be `null` if this stream received an error
   * without a stack trace.
   *
   * An asynchronous error `error` is matched by a test function if
   *`test(error)` returns true. If [test] is omitted, every error is considered
   * matching.
   *
   * If the error is intercepted, the [onError] function can decide what to do
   * with it. It can throw if it wants to raise a new (or the same) error,
   * or simply return to make this stream forget the error.
   * If the received `error` value is thrown again by the [onError] function,
   * it acts like a `rethrow` and it is emitted along with its original
   * stack trace, not the stack trace of the `throw` inside [onError].
   *
   * If you need to transform an error into a data event, use the more generic
   * [Stream.transform] to handle the event by writing a data event to
   * the output sink.
   *
   * The returned stream is a broadcast stream if this stream is.
   * If a broadcast stream is listened to more than once, each subscription
   * will individually perform the `test` and handle the error.
   */
  Stream<T> handleError(Function onError, {bool test(error)}) {
    return new _HandleErrorStream<T>(this, onError, test);
  }

  /**
   * Transforms each element of this stream into a sequence of elements.
   *
   * Returns a new stream where each element of this stream is replaced
   * by zero or more data events.
   * The event values are provided as an [Iterable] by a call to [convert]
   * with the element as argument, and the elements of that iterable is
   * emitted in iteration order.
   * If calling [convert] throws, or if the iteration of the returned values
   * throws, the error is emitted on the returned stream and iteration ends
   * for that element of this stream.
   *
   * Error events and the done event of this stream are forwarded directly
   * to the returned stream.
   *
   * The returned stream is a broadcast stream if this stream is.
   * If a broadcast stream is listened to more than once, each subscription
   * will individually call `convert` and expand the events.
   */
  Stream<S> expand<S>(Iterable<S> convert(T element)) {
    return new _ExpandStream<T, S>(this, convert);
  }

  /**
   * Pipes the events of this stream into [streamConsumer].
   *
   * All events of this stream are added to `streamConsumer` using
   * [StreamConsumer.addStream].
   * The `streamConsumer` is closed when this stream has been successfully added
   * to it - when the future returned by `addStream` completes without an error.
   *
   * Returns a future which completes when this stream has been consumed
   * and the consumer has been closed.
   *
   * The returned future completes with the same result as the future returned
   * by [StreamConsumer.close].
   * If the call to [StreamConsumer.addStream] fails in some way, this
   * method fails in the same way.
   */
  Future pipe(StreamConsumer<T> streamConsumer) {
    return streamConsumer.addStream(this).then((_) => streamConsumer.close());
  }

  /**
   * Applies  [streamTransformer] to this stream.
   *
   * Returns the transformed stream,
   * that is, the result of `streamTransformer.bind(this)`.
   * This method simply allows writing the call to `streamTransformer.bind`
   * in a chained fashion, like
   * ```
   * stream.map(mapping).transform(transformation).toList()
   * ```
   * which can be more convenient than calling `bind` directly.
   *
   * The [streamTransformer] can return any stream.
   * Whether the returned stream is a broadcast stream or not,
   * and which elements it will contain,
   * is entirely up to the transformation.
   *
   * This method should always be used for transformations which treat
   * the entire stream as representing a single value
   * which has perhaps been split into several parts for transport,
   * like a file being read from disk or being fetched over a network.
   * The transformation will then produce a new stream which
   * transforms the stream's value incrementally (perhaps using
   * [Converter.startChunkedConversion]). The resulting stream
   * may again be chunks of the result, but does not have to
   * correspond to specific events from the source string.
   */
  Stream<S> transform<S>(StreamTransformer<T, S> streamTransformer) {
    return streamTransformer.bind(this);
  }

  /**
   * Combines a sequence of values by repeatedly applying [combine].
   *
   * Similar to [Iterable.reduce], this function maintains a value,
   * starting with the first element of this stream
   * and updated for each further element of this stream.
   * For each element after the first,
   * the value is updated to the result of calling [combine]
   * with the previous value and the element.
   *
   * When this stream is done, the returned future is completed with
   * the value at that time.
   *
   * If this stream is empty, the returned future is completed with
   * an error.
   * If this stream emits an error, or the call to [combine] throws,
   * the returned future is completed with that error,
   * and processing is stopped.
   */
  Future<T> reduce(T combine(T previous, T element)) {
    _Future<T> result = new _Future<T>();
    bool seenFirst = false;
    T value;
    StreamSubscription subscription;
    subscription = this.listen(
        (T element) {
          if (seenFirst) {
            _runUserCode(() => combine(value, element), (T newValue) {
              value = newValue;
            }, _cancelAndErrorClosure(subscription, result));
          } else {
            value = element;
            seenFirst = true;
          }
        },
        onError: result._completeError,
        onDone: () {
          if (!seenFirst) {
            try {
              // Throw and recatch, instead of just doing
              //  _completeWithErrorCallback, e, theError, StackTrace.current),
              // to ensure that the stackTrace is set on the error.
              throw IterableElementError.noElement();
            } catch (e, s) {
              _completeWithErrorCallback(result, e, s);
            }
          } else {
            result._complete(value);
          }
        },
        cancelOnError: true);
    return result;
  }

  /**
   * Combines a sequence of values by repeatedly applying [combine].
   *
   * Similar to [Iterable.fold], this function maintains a value,
   * starting with [initialValue] and updated for each element of
   * this stream.
   * For each element, the value is updated to the result of calling
   * [combine] with the previous value and the element.
   *
   * When this stream is done, the returned future is completed with
   * the value at that time.
   * For an empty stream, the future is completed with [initialValue].
   *
   * If this stream emits an error, or the call to [combine] throws,
   * the returned future is completed with that error,
   * and processing is stopped.
   */
  Future<S> fold<S>(S initialValue, S combine(S previous, T element)) {
    _Future<S> result = new _Future<S>();
    S value = initialValue;
    StreamSubscription subscription;
    subscription = this.listen(
        (T element) {
          _runUserCode(() => combine(value, element), (S newValue) {
            value = newValue;
          }, _cancelAndErrorClosure(subscription, result));
        },
        onError: result._completeError,
        onDone: () {
          result._complete(value);
        },
        cancelOnError: true);
    return result;
  }

  /**
   * Combines the string representation of elements into a single string.
   *
   * Each element is converted to a string using its [Object.toString] method.
   * If [separator] is provided, it is inserted between element string
   * representations.
   *
   * The returned future is completed with the combined string when this stream
   * is done.
   *
   * If this stream emits an error, or the call to [Object.toString] throws,
   * the returned future is completed with that error,
   * and processing stops.
   */
  Future<String> join([String separator = ""]) {
    _Future<String> result = new _Future<String>();
    StringBuffer buffer = new StringBuffer();
    StreamSubscription subscription;
    bool first = true;
    subscription = this.listen(
        (T element) {
          if (!first) {
            buffer.write(separator);
          }
          first = false;
          try {
            buffer.write(element);
          } catch (e, s) {
            _cancelAndErrorWithReplacement(subscription, result, e, s);
          }
        },
        onError: result._completeError,
        onDone: () {
          result._complete(buffer.toString());
        },
        cancelOnError: true);
    return result;
  }

  /**
   * Returns whether [needle] occurs in the elements provided by this stream.
   *
   * Compares each element of this stream to [needle] using [Object.==].
   * If an equal element is found, the returned future is completed with `true`.
   * If this stream ends without finding a match, the future is completed with
   * `false`.
   *
   * If this stream emits an error, or the call to [Object.==] throws,
   * the returned future is completed with that error,
   * and processing stops.
   */
  Future<bool> contains(Object needle) {
    _Future<bool> future = new _Future<bool>();
    StreamSubscription subscription;
    subscription = this.listen(
        (T element) {
          _runUserCode(() => (element == needle), (bool isMatch) {
            if (isMatch) {
              _cancelAndValue(subscription, future, true);
            }
          }, _cancelAndErrorClosure(subscription, future));
        },
        onError: future._completeError,
        onDone: () {
          future._complete(false);
        },
        cancelOnError: true);
    return future;
  }

  /**
   * Executes [action] on each element of this stream.
   *
   * Completes the returned [Future] when all elements of this stream
   * have been processed.
   *
   * If this stream emits an error, or if the call to [action] throws,
   * the returned future completes with that error,
   * and processing stops.
   */
  Future forEach(void action(T element)) {
    _Future future = new _Future();
    StreamSubscription subscription;
    subscription = this.listen(
        (T element) {
          // TODO(floitsch): the type should be 'void' and inferred.
          _runUserCode<dynamic>(() => action(element), (_) {},
              _cancelAndErrorClosure(subscription, future));
        },
        onError: future._completeError,
        onDone: () {
          future._complete(null);
        },
        cancelOnError: true);
    return future;
  }

  /**
   * Checks whether [test] accepts all elements provided by this stream.
   *
   * Calls [test] on each element of this stream.
   * If the call returns `false`, the returned future is completed with `false`
   * and processing stops.
   *
   * If this stream ends without finding an element that [test] rejects,
   * the returned future is completed with `true`.
   *
   * If this stream emits an error, or if the call to [test] throws,
   * the returned future is completed with that error,
   * and processing stops.
   */
  Future<bool> every(bool test(T element)) {
    _Future<bool> future = new _Future<bool>();
    StreamSubscription subscription;
    subscription = this.listen(
        (T element) {
          _runUserCode(() => test(element), (bool isMatch) {
            if (!isMatch) {
              _cancelAndValue(subscription, future, false);
            }
          }, _cancelAndErrorClosure(subscription, future));
        },
        onError: future._completeError,
        onDone: () {
          future._complete(true);
        },
        cancelOnError: true);
    return future;
  }

  /**
   * Checks whether [test] accepts any element provided by this stream.
   *
   * Calls [test] on each element of this stream.
   * If the call returns `true`, the returned future is completed with `true`
   * and processing stops.
   *
   * If this stream ends without finding an element that [test] accepts,
   * the returned future is completed with `false`.
   *
   * If this stream emits an error, or if the call to [test] throws,
   * the returned future is completed with that error,
   * and processing stops.
   */
  Future<bool> any(bool test(T element)) {
    _Future<bool> future = new _Future<bool>();
    StreamSubscription subscription;
    subscription = this.listen(
        (T element) {
          _runUserCode(() => test(element), (bool isMatch) {
            if (isMatch) {
              _cancelAndValue(subscription, future, true);
            }
          }, _cancelAndErrorClosure(subscription, future));
        },
        onError: future._completeError,
        onDone: () {
          future._complete(false);
        },
        cancelOnError: true);
    return future;
  }

  /**
   * The number of elements in this stream.
   *
   * Waits for all elements of this stream. When this stream ends,
   * the returned future is completed with the number of elements.
   *
   * If this stream emits an error,
   * the returned future is completed with that error,
   * and processing stops.
   *
   * This operation listens to this stream, and a non-broadcast stream cannot
   * be reused after finding its length.
   */
  Future<int> get length {
    _Future<int> future = new _Future<int>();
    int count = 0;
    this.listen(
        (_) {
          count++;
        },
        onError: future._completeError,
        onDone: () {
          future._complete(count);
        },
        cancelOnError: true);
    return future;
  }

  /**
   * Whether this stream contains any elements.
   *
   * Waits for the first element of this stream, then completes the returned
   * future with `true`.
   * If this stream ends without emitting any elements, the returned future is
   * completed with `false`.
   *
   * If the first event is an error, the returned future is completed with that
   * error.
   *
   * This operation listens to this stream, and a non-broadcast stream cannot
   * be reused after checking whether it is empty.
   */
  Future<bool> get isEmpty {
    _Future<bool> future = new _Future<bool>();
    StreamSubscription subscription;
    subscription = this.listen(
        (_) {
          _cancelAndValue(subscription, future, false);
        },
        onError: future._completeError,
        onDone: () {
          future._complete(true);
        },
        cancelOnError: true);
    return future;
  }

  /**
   * Adapt this stream to be a `Stream<R>`.
   *
   * This stream is wrapped as a `Stream<R>` which checks at run-time that
   * each data event emitted by this stream is also an instance of [R].
   */
  Stream<R> cast<R>() => Stream.castFrom<T, R>(this);
  /**
   * Collects all elements of this stream in a [List].
   *
   * Creates a `List<T>` and adds all elements of this stream to the list
   * in the order they arrive.
   * When this stream ends, the returned future is completed with that list.
   *
   * If this stream emits an error,
   * the returned future is completed with that error,
   * and processing stops.
   */
  Future<List<T>> toList() {
    List<T> result = <T>[];
    _Future<List<T>> future = new _Future<List<T>>();
    this.listen(
        (T data) {
          result.add(data);
        },
        onError: future._completeError,
        onDone: () {
          future._complete(result);
        },
        cancelOnError: true);
    return future;
  }

  /**
   * Collects the data of this stream in a [Set].
   *
   * Creates a `Set<T>` and adds all elements of this stream to the set.
   * in the order they arrive.
   * When this stream ends, the returned future is completed with that set.
   *
   * The returned set is the same type as returned by `new Set<T>()`.
   * If another type of set is needed, either use [forEach] to add each
   * element to the set, or use
   * `toList().then((list) => new SomeOtherSet.from(list))`
   * to create the set.
   *
   * If this stream emits an error,
   * the returned future is completed with that error,
   * and processing stops.
   */
  Future<Set<T>> toSet() {
    Set<T> result = new Set<T>();
    _Future<Set<T>> future = new _Future<Set<T>>();
    this.listen(
        (T data) {
          result.add(data);
        },
        onError: future._completeError,
        onDone: () {
          future._complete(result);
        },
        cancelOnError: true);
    return future;
  }

  /**
   * Discards all data on this stream, but signals when it is done or an error
   * occurred.
   *
   * When subscribing using [drain], cancelOnError will be true. This means
   * that the future will complete with the first error on this stream and then
   * cancel the subscription.
   * If this stream emits an error, or the call to [combine] throws,
   * the returned future is completed with that error,
   * and processing is stopped.
   *
   * In case of a `done` event the future completes with the given
   * [futureValue].
   */
  Future<E> drain<E>([E futureValue]) =>
      listen(null, cancelOnError: true).asFuture<E>(futureValue);

  /**
   * Provides at most the first [count] data events of this stream.
   *
   * Returns a stream that emits the same events that this stream would
   * if listened to at the same time,
   * until either this stream ends or it has emitted [count] data events,
   * at which point the returned stream is done.
   *
   * If this stream produces fewer than [count] data events before it's done,
   * so will the returned stream.
   *
   * Starts listening to this stream when the returned stream is listened to
   * and stops listening when the first [count] data events have been received.
   *
   * This means that if this is a single-subscription (non-broadcast) streams
   * it cannot be reused after the returned stream has been listened to.
   *
   * If this is a broadcast stream, the returned stream is a broadcast stream.
   * In that case, the events are only counted from the time
   * the returned stream is listened to.
   */
  Stream<T> take(int count) {
    return new _TakeStream<T>(this, count);
  }

  /**
   * Forwards data events while [test] is successful.
   *
   * Returns a stream that provides the same events as this stream
   * until [test] fails for a data event.
   * The returned stream is done when either this stream is done,
   * or when this stream first emits a data event that fails [test].
   *
   * The `test` call is considered failing if it returns a non-`true` value
   * or if it throws. If the `test` call throws, the error is emitted as the
   * last event on the returned streams.
   *
   * Stops listening to this stream after the accepted elements.
   *
   * Internally the method cancels its subscription after these elements. This
   * means that single-subscription (non-broadcast) streams are closed and
   * cannot be reused after a call to this method.
   *
   * The returned stream is a broadcast stream if this stream is.
   * For a broadcast stream, the events are only tested from the time
   * the returned stream is listened to.
   */
  Stream<T> takeWhile(bool test(T element)) {
    return new _TakeWhileStream<T>(this, test);
  }

  /**
   * Skips the first [count] data events from this stream.
   *
   * Returns a stream that emits the same events as this stream would
   * if listened to at the same time, except that the first [count]
   * data events are not emitted.
   * The returned stream is done when this stream is.
   *
   * If this stream emits fewer than [count] data events
   * before being done, the returned stream emits no data events.
   *
   * The returned stream is a broadcast stream if this stream is.
   * For a broadcast stream, the events are only counted from the time
   * the returned stream is listened to.
   */
  Stream<T> skip(int count) {
    return new _SkipStream<T>(this, count);
  }

  /**
   * Skip data events from this stream while they are matched by [test].
   *
   * Returns a stream that emits the same events as this stream,
   * except that data events are not emitted until a data event fails `test`.
   * The test fails when called with a data event
   * if it returns a non-`true` value or if the call to `test` throws.
   * If the call throws, the error is emitted as an error event
   * on the returned stream instead of the data event,
   * otherwise the event that made `test` return non-true is emitted as the
   * first data event.
   *
   * Error and done events are provided by the returned stream unmodified.
   *
   * The returned stream is a broadcast stream if this stream is.
   * For a broadcast stream, the events are only tested from the time
   * the returned stream is listened to.
   */
  Stream<T> skipWhile(bool test(T element)) {
    return new _SkipWhileStream<T>(this, test);
  }

  /**
   * Skips data events if they are equal to the previous data event.
   *
   * The returned stream provides the same events as this stream, except
   * that it never provides two consecutive data events that are equal.
   * That is, errors are passed through to the returned stream, and
   * data events are passed through if they are distinct from the most
   * recently emitted data event.
   *
   * Equality is determined by the provided [equals] method. If that is
   * omitted, the '==' operator on the last provided data element is used.
   *
   * If [equals] throws, the data event is replaced by an error event
   * containing the thrown error. The behavior is equivalent to the
   * original stream emitting the error event, and it doesn't change
   * the what the most recently emitted data event is.
   *
   * The returned stream is a broadcast stream if this stream is.
   * If a broadcast stream is listened to more than once, each subscription
   * will individually perform the `equals` test.
   */
  Stream<T> distinct([bool equals(T previous, T next)]) {
    return new _DistinctStream<T>(this, equals);
  }

  /**
   * The first element of this stream.
   *
   * Stops listening to this stream after the first element has been received.
   *
   * Internally the method cancels its subscription after the first element.
   * This means that single-subscription (non-broadcast) streams are closed
   * and cannot be reused after a call to this getter.
   *
   * If an error event occurs before the first data event, the returned future
   * is completed with that error.
   *
   * If this stream is empty (a done event occurs before the first data event),
   * the returned future completes with an error.
   *
   * Except for the type of the error, this method is equivalent to
   * `this.elementAt(0)`.
   */
  Future<T> get first {
    _Future<T> future = new _Future<T>();
    StreamSubscription subscription;
    subscription = this.listen(
        (T value) {
          _cancelAndValue(subscription, future, value);
        },
        onError: future._completeError,
        onDone: () {
          try {
            throw IterableElementError.noElement();
          } catch (e, s) {
            _completeWithErrorCallback(future, e, s);
          }
        },
        cancelOnError: true);
    return future;
  }

  /**
   * The last element of this stream.
   *
   * If this stream emits an error event,
   * the returned future is completed with that error
   * and processing stops.
   *
   * If this stream is empty (the done event is the first event),
   * the returned future completes with an error.
   */
  Future<T> get last {
    _Future<T> future = new _Future<T>();
    T result;
    bool foundResult = false;
    listen(
        (T value) {
          foundResult = true;
          result = value;
        },
        onError: future._completeError,
        onDone: () {
          if (foundResult) {
            future._complete(result);
            return;
          }
          try {
            throw IterableElementError.noElement();
          } catch (e, s) {
            _completeWithErrorCallback(future, e, s);
          }
        },
        cancelOnError: true);
    return future;
  }

  /**
   * The single element of this stream.
   *
   * If this stream emits an error event,
   * the returned future is completed with that error
   * and processing stops.
   *
   * If [this] is empty or has more than one element,
   * the returned future completes with an error.
   */
  Future<T> get single {
    _Future<T> future = new _Future<T>();
    T result;
    bool foundResult = false;
    StreamSubscription subscription;
    subscription = this.listen(
        (T value) {
          if (foundResult) {
            // This is the second element we get.
            try {
              throw IterableElementError.tooMany();
            } catch (e, s) {
              _cancelAndErrorWithReplacement(subscription, future, e, s);
            }
            return;
          }
          foundResult = true;
          result = value;
        },
        onError: future._completeError,
        onDone: () {
          if (foundResult) {
            future._complete(result);
            return;
          }
          try {
            throw IterableElementError.noElement();
          } catch (e, s) {
            _completeWithErrorCallback(future, e, s);
          }
        },
        cancelOnError: true);
    return future;
  }

  /**
   * Finds the first element of this stream matching [test].
   *
   * Returns a future that is completed with the first element of this stream
   * that [test] returns `true` for.
   *
   * If no such element is found before this stream is done, and a
   * [orElse] function is provided, the result of calling [orElse]
   * becomes the value of the future. If [orElse] throws, the returned
   * future is completed with that error.
   *
   * If this stream emits an error before the first matching element,
   * the returned future is completed with that error, and processing stops.
   *
   * Stops listening to this stream after the first matching element or error
   * has been received.
   *
   * Internally the method cancels its subscription after the first element that
   * matches the predicate. This means that single-subscription (non-broadcast)
   * streams are closed and cannot be reused after a call to this method.
   *
   * If an error occurs, or if this stream ends without finding a match and
   * with no [orElse] function provided,
   * the returned future is completed with an error.
   */
  Future<T> firstWhere(bool test(T element), {T orElse()}) {
    _Future<T> future = new _Future();
    StreamSubscription subscription;
    subscription = this.listen(
        (T value) {
          _runUserCode(() => test(value), (bool isMatch) {
            if (isMatch) {
              _cancelAndValue(subscription, future, value);
            }
          }, _cancelAndErrorClosure(subscription, future));
        },
        onError: future._completeError,
        onDone: () {
          if (orElse != null) {
            _runUserCode(orElse, future._complete, future._completeError);
            return;
          }
          try {
            throw IterableElementError.noElement();
          } catch (e, s) {
            _completeWithErrorCallback(future, e, s);
          }
        },
        cancelOnError: true);
    return future;
  }

  /**
   * Finds the last element in this stream matching [test].
   *
   * If this stream emits an error, the returned future is completed with that
   * error, and processing stops.
   *
   * Otherwise as [firstWhere], except that the last matching element is found
   * instead of the first.
   * That means that a non-error result cannot be provided before this stream
   * is done.
   */
  Future<T> lastWhere(bool test(T element), {T orElse()}) {
    _Future<T> future = new _Future();
    T result;
    bool foundResult = false;
    StreamSubscription subscription;
    subscription = this.listen(
        (T value) {
          _runUserCode(() => true == test(value), (bool isMatch) {
            if (isMatch) {
              foundResult = true;
              result = value;
            }
          }, _cancelAndErrorClosure(subscription, future));
        },
        onError: future._completeError,
        onDone: () {
          if (foundResult) {
            future._complete(result);
            return;
          }
          if (orElse != null) {
            _runUserCode(orElse, future._complete, future._completeError);
            return;
          }
          try {
            throw IterableElementError.noElement();
          } catch (e, s) {
            _completeWithErrorCallback(future, e, s);
          }
        },
        cancelOnError: true);
    return future;
  }

  /**
   * Finds the single element in this stream matching [test].
   *
   * Like [lastWhere], except that it is an error if more than one
   * matching element occurs in this stream.
   */
  Future<T> singleWhere(bool test(T element), {T orElse()}) {
    _Future<T> future = new _Future<T>();
    T result;
    bool foundResult = false;
    StreamSubscription subscription;
    subscription = this.listen(
        (T value) {
          _runUserCode(() => true == test(value), (bool isMatch) {
            if (isMatch) {
              if (foundResult) {
                try {
                  throw IterableElementError.tooMany();
                } catch (e, s) {
                  _cancelAndErrorWithReplacement(subscription, future, e, s);
                }
                return;
              }
              foundResult = true;
              result = value;
            }
          }, _cancelAndErrorClosure(subscription, future));
        },
        onError: future._completeError,
        onDone: () {
          if (foundResult) {
            future._complete(result);
            return;
          }
          try {
            if (orElse != null) {
              _runUserCode(orElse, future._complete, future._completeError);
              return;
            }
            throw IterableElementError.noElement();
          } catch (e, s) {
            _completeWithErrorCallback(future, e, s);
          }
        },
        cancelOnError: true);
    return future;
  }

  /**
   * Returns the value of the [index]th data event of this stream.
   *
   * Stops listening to this stream after the [index]th data event has been
   * received.
   *
   * Internally the method cancels its subscription after these elements. This
   * means that single-subscription (non-broadcast) streams are closed and
   * cannot be reused after a call to this method.
   *
   * If an error event occurs before the value is found, the future completes
   * with this error.
   *
   * If a done event occurs before the value is found, the future completes
   * with a [RangeError].
   */
  Future<T> elementAt(int index) {
    ArgumentError.checkNotNull(index, "index");
    RangeError.checkNotNegative(index, "index");
    _Future<T> future = new _Future<T>();
    StreamSubscription subscription;
    int elementIndex = 0;
    subscription = this.listen(
        (T value) {
          if (index == elementIndex) {
            _cancelAndValue(subscription, future, value);
            return;
          }
          elementIndex += 1;
        },
        onError: future._completeError,
        onDone: () {
          future._completeError(
              new RangeError.index(index, this, "index", null, elementIndex));
        },
        cancelOnError: true);
    return future;
  }

  /**
   * Creates a new stream with the same events as this stream.
   *
   * Whenever more than [timeLimit] passes between two events from this stream,
   * the [onTimeout] function is called, which can emit further events on
   * the returned stream.
   *
   * The countdown doesn't start until the returned stream is listened to.
   * The countdown is reset every time an event is forwarded from this stream,
   * or when this stream is paused and resumed.
   *
   * The [onTimeout] function is called with one argument: an
   * [EventSink] that allows putting events into the returned stream.
   * This `EventSink` is only valid during the call to [onTimeout].
   * Calling [EventSink.close] on the sink passed to [onTimeout] closes the
   * returned stream, and no further events are processed.
   *
   * If [onTimeout] is omitted, a timeout will just put a [TimeoutException]
   * into the error channel of the returned stream.
   * If the call to [onTimeout] throws, the error is emitted on the returned
   * stream.
   *
   * The returned stream is a broadcast stream if this stream is.
   * If a broadcast stream is listened to more than once, each subscription
   * will have its individually timer that starts counting on listen,
   * and the subscriptions' timers can be paused individually.
   */
  Stream<T> timeout(Duration timeLimit, {void onTimeout(EventSink<T> sink)}) {
    _StreamControllerBase<T> controller;
    // The following variables are set on listen.
    StreamSubscription<T> subscription;
    Timer timer;
    Zone zone;
    _TimerCallback timeout;

    void onData(T event) {
      timer.cancel();
      timer = zone.createTimer(timeLimit, timeout);
      // It might close the stream and cancel timer, so create recuring Timer
      // before calling into add();
      // issue: https://github.com/dart-lang/sdk/issues/37565
      controller.add(event);
    }

    void onError(error, StackTrace stackTrace) {
      timer.cancel();
      assert(controller is _StreamController ||
          controller is _BroadcastStreamController);
      controller._addError(error, stackTrace); // Avoid Zone error replacement.
      timer = zone.createTimer(timeLimit, timeout);
    }

    void onDone() {
      timer.cancel();
      controller.close();
    }

    void onListen() {
      // This is the onListen callback for of controller.
      // It runs in the same zone that the subscription was created in.
      // Use that zone for creating timers and running the onTimeout
      // callback.
      zone = Zone.current;
      if (onTimeout == null) {
        timeout = () {
          controller.addError(
              new TimeoutException("No stream event", timeLimit), null);
        };
      } else {
        // TODO(floitsch): the return type should be 'void', and the type
        // should be inferred.
        var registeredOnTimeout =
            zone.registerUnaryCallback<dynamic, EventSink<T>>(onTimeout);
        var wrapper = new _ControllerEventSinkWrapper<T>(null);
        timeout = () {
          wrapper._sink = controller; // Only valid during call.
          zone.runUnaryGuarded(registeredOnTimeout, wrapper);
          wrapper._sink = null;
        };
      }

      subscription = this.listen(onData, onError: onError, onDone: onDone);
      timer = zone.createTimer(timeLimit, timeout);
    }

    Future onCancel() {
      timer.cancel();
      Future result = subscription.cancel();
      subscription = null;
      return result;
    }

    controller = isBroadcast
        ? new _SyncBroadcastStreamController<T>(onListen, onCancel)
        : new _SyncStreamController<T>(onListen, () {
            // Don't null the timer, onCancel may call cancel again.
            timer.cancel();
            subscription.pause();
          }, () {
            subscription.resume();
            timer = zone.createTimer(timeLimit, timeout);
          }, onCancel);
    return controller.stream;
  }
}

/**
 * A subscription on events from a [Stream].
 *
 * When you listen on a [Stream] using [Stream.listen],
 * a [StreamSubscription] object is returned.
 *
 * The subscription provides events to the listener,
 * and holds the callbacks used to handle the events.
 * The subscription can also be used to unsubscribe from the events,
 * or to temporarily pause the events from the stream.
 */
abstract class StreamSubscription<T> {
  /**
   * Cancels this subscription.
   *
   * After this call, the subscription no longer receives events.
   *
   * The stream may need to shut down the source of events and clean up after
   * the subscription is canceled.
   *
   * Returns a future that is completed once the stream has finished
   * its cleanup.
   *
   * For historical reasons, may also return `null` if no cleanup was necessary.
   * Returning `null` is deprecated and should be avoided.
   *
   * Typically, futures are returned when the stream needs to release resources.
   * For example, a stream might need to close an open file (as an asynchronous
   * operation). If the listener wants to delete the file after having
   * canceled the subscription, it must wait for the cleanup future to complete.
   *
   * A returned future completes with a `null` value.
   * If the cleanup throws, which it really shouldn't, the returned future
   * completes with that error.
   */
  Future cancel();

  /**
   * Replaces the data event handler of this subscription.
   *
   * The [handleData] function is called for each element of the stream
   * after this function is called.
   * If [handleData] is `null`, further elements are ignored.
   *
   * This method replaces the current handler set by the invocation of
   * [Stream.listen] or by a previous call to [onData].
   */
  void onData(void handleData(T data));

  /**
   * Replaces the error event handler of this subscription.
   *
   * The [handleError] function must be able to be called with either
   * one positional argument, or with two positional arguments
   * where the seconds is always a [StackTrace].
   *
   * The [handleError] argument may be `null`, in which case further
   * error events are considered unhandled, and will be reported to
   * [Zone.handleUncaughtError].
   *
   * The provided function is called for all error events from the
   * stream subscription.
   *
   * This method replaces the current handler set by the invocation of
   * [Stream.listen], by calling [asFuture], or by a previous call to [onError].
   */
  void onError(Function handleError);

  /**
   * Replaces the done event handler of this subscription.
   *
   * The [handleDone] function is called when the stream closes.
   * The value may be `null`, in which case no function is called.
   *
   * This method replaces the current handler set by the invocation of
   * [Stream.listen], by calling [asFuture], or by a previous call to [onDone].
   */
  void onDone(void handleDone());

  /**
   * Request that the stream pauses events until further notice.
   *
   * While paused, the subscription will not fire any events.
   * If it receives events from its source, they will be buffered until
   * the subscription is resumed.
   * For non-broadcast streams, the underlying source is usually informed
   * about the pause,
   * so it can stop generating events until the subscription is resumed.
   *
   * To avoid buffering events on a broadcast stream, it is better to
   * cancel this subscription, and start to listen again when events
   * are needed, if the intermediate events are not important.
   *
   * If [resumeSignal] is provided, the stream subscription will undo the pause
   * when the future completes, as if by a call to [resume].
   * If the future completes with an error,
   * the stream will still resume, but the error will be considered unhandled
   * and is passed to [Zone.handleUncaughtError].
   *
   * A call to [resume] will also undo a pause.
   *
   * If the subscription is paused more than once, an equal number
   * of resumes must be performed to resume the stream.
   * Calls to [resume] and the completion of a [resumeSignal] are
   * interchangeable - the [pause] which was passed a [resumeSignal] may be
   * ended by a call to [resume], and completing the [resumeSignal] may end a
   * different [pause].
   *
   * It is safe to [resume] or complete a [resumeSignal] even when the
   * subscription is not paused, and the resume will have no effect.
   *
   * Currently DOM streams silently drop events when the stream is paused. This
   * is a bug and will be fixed.
   */
  void pause([Future resumeSignal]);

  /**
   * Resume after a pause.
   *
   * This undoes one previous call to [pause].
   * When all previously calls to [pause] have been matched by a calls to
   * [resume], possibly through a `resumeSignal` passed to [pause],
   * the stream subscription may emit events again.
   *
   * It is safe to [resume] even when the subscription is not paused, and the
   * resume will have no effect.
   */
  void resume();

  /**
   * Whether the [StreamSubscription] is currently paused.
   *
   * If there have been more calls to [pause] than to [resume] on this
   * stream subscription, the subscription is paused, and this getter
   * returns `true`.
   *
   * Returns `false` if the stream can currently emit events, or if
   * the subscription has completed or been cancelled.
   */
  bool get isPaused;

  /**
   * Returns a future that handles the [onDone] and [onError] callbacks.
   *
   * This method *overwrites* the existing [onDone] and [onError] callbacks
   * with new ones that complete the returned future.
   *
   * In case of an error the subscription will automatically cancel (even
   * when it was listening with `cancelOnError` set to `false`).
   *
   * In case of a `done` event the future completes with the given
   * [futureValue].
   */
  Future<E> asFuture<E>([E futureValue]);
}

/**
 * A [Sink] that supports adding errors.
 *
 * This makes it suitable for capturing the results of asynchronous
 * computations, which can complete with a value or an error.
 *
 * The [EventSink] has been designed to handle asynchronous events from
 * [Stream]s. See, for example, [Stream.eventTransformed] which uses
 * `EventSink`s to transform events.
 */
abstract class EventSink<T> implements Sink<T> {
  /**
   * Adds a data [event] to the sink.
   *
   * Must not be called on a closed sink.
   */
  void add(T event);

  /**
   * Adds an [error] to the sink.
   *
   * Must not be called on a closed sink.
   */
  void addError(Object error, [StackTrace stackTrace]);

  /**
   * Closes the sink.
   *
   * Calling this method more than once is allowed, but does nothing.
   *
   * Neither [add] nor [addError] must be called after this method.
   */
  void close();
}

/** [Stream] wrapper that only exposes the [Stream] interface. */
class StreamView<T> extends Stream<T> {
  final Stream<T> _stream;

  const StreamView(Stream<T> stream)
      : _stream = stream,
        super._internal();

  bool get isBroadcast => _stream.isBroadcast;

  Stream<T> asBroadcastStream(
          {void onListen(StreamSubscription<T> subscription),
          void onCancel(StreamSubscription<T> subscription)}) =>
      _stream.asBroadcastStream(onListen: onListen, onCancel: onCancel);

  StreamSubscription<T> listen(void onData(T value),
      {Function onError, void onDone(), bool cancelOnError}) {
    return _stream.listen(onData,
        onError: onError, onDone: onDone, cancelOnError: cancelOnError);
  }
}

/**
 * Abstract interface for a "sink" accepting multiple entire streams.
 *
 * A consumer can accept a number of consecutive streams using [addStream],
 * and when no further data need to be added, the [close] method tells the
 * consumer to complete its work and shut down.
 *
 * The [Stream.pipe] accepts a `StreamConsumer` and will pass the stream
 * to the consumer's [addStream] method. When that completes, it will
 * call [close] and then complete its own returned future.
 */
abstract class StreamConsumer<S> {
  /**
   * Consumes the elements of [stream].
   *
   * Listens on [stream] and does something for each event.
   *
   * Returns a future which is completed when the stream is done being added,
   * and the consumer is ready to accept a new stream.
   * No further calls to [addStream] or [close] should happen before the
   * returned future has completed.
   *
   * The consumer may stop listening to the stream after an error,
   * it may consume all the errors and only stop at a done event,
   * or it may be canceled early if the receiver don't want any further events.
   *
   * If the consumer stops listening because of some error preventing it
   * from continuing, it may report this error in the returned future,
   * otherwise it will just complete the future with `null`.
   */
  Future addStream(Stream<S> stream);

  /**
   * Tells the consumer that no further streams will be added.
   *
   * This allows the consumer to complete any remaining work and release
   * resources that are no longer needed
   *
   * Returns a future which is completed when the consumer has shut down.
   * If cleaning up can fail, the error may be reported in the returned future,
   * otherwise it completes with `null`.
   */
  Future close();
}

/**
 * A object that accepts stream events both synchronously and asynchronously.
 *
 * A [StreamSink] combines the methods from [StreamConsumer] and [EventSink].
 *
 * The [EventSink] methods can't be used while the [addStream] is called.
 * As soon as the [addStream]'s [Future] completes with a value, the
 * [EventSink] methods can be used again.
 *
 * If [addStream] is called after any of the [EventSink] methods, it'll
 * be delayed until the underlying system has consumed the data added by the
 * [EventSink] methods.
 *
 * When [EventSink] methods are used, the [done] [Future] can be used to
 * catch any errors.
 *
 * When [close] is called, it will return the [done] [Future].
 */
abstract class StreamSink<S> implements EventSink<S>, StreamConsumer<S> {
  /**
   * Tells the stream sink that no further streams will be added.
   *
   * This allows the stream sink to complete any remaining work and release
   * resources that are no longer needed
   *
   * Returns a future which is completed when the stream sink has shut down.
   * If cleaning up can fail, the error may be reported in the returned future,
   * otherwise it completes with `null`.
   *
   * Returns the same future as [done].
   *
   * The stream sink may close before the [close] method is called, either due
   * to an error or because it is itself providing events to someone who has
   * stopped listening. In that case, the [done] future is completed first,
   * and the `close` method will return the `done` future when called.
   *
   * Unifies [StreamConsumer.close] and [EventSink.close] which both mark their
   * object as not expecting any further events.
   */
  Future close();

  /**
   * Return a future which is completed when the [StreamSink] is finished.
   *
   * If the `StreamSink` fails with an error,
   * perhaps in response to adding events using [add], [addError] or [close],
   * the [done] future will complete with that error.
   *
   * Otherwise, the returned future will complete when either:
   *
   * * all events have been processed and the sink has been closed, or
   * * the sink has otherwise been stopped from handling more events
   *   (for example by canceling a stream subscription).
   */
  Future get done;
}

/**
 * Transforms a Stream.
 *
 * When a stream's [Stream.transform] method is invoked with a
 * [StreamTransformer], the stream calls the [bind] method on the provided
 * transformer. The resulting stream is then returned from the
 * [Stream.transform] method.
 *
 * Conceptually, a transformer is simply a function from [Stream] to [Stream]
 * that is encapsulated into a class.
 *
 * It is good practice to write transformers that can be used multiple times.
 *
 * All other transforming methods on [Stream], such as [Stream.map],
 * [Stream.where] or [Stream.expand] can be implemented using
 * [Stream.transform]. A [StreamTransformer] is thus very powerful but often
 * also a bit more complicated to use.
 */
abstract class StreamTransformer<S, T> {
  /**
   * Creates a [StreamTransformer] based on the given [onListen] callback.
   *
   * The returned stream transformer uses the provided [onListen] callback
   * when a transformed stream is listened to. At that time, the callback
   * receives the input stream (the one passed to [bind]) and a
   * boolean flag `cancelOnError` to create a [StreamSubscription].
   *
   * If the transformed stream is a broadcast stream, so is the stream
   * returned by the [StreamTransformer.bind] method by this transformer.
   *
   * If the transformed stream is listened to multiple times, the [onListen]
   * callback is called again for each new [Stream.listen] call.
   * This happens whether the stream is a broadcast stream or not,
   * but the call will usually fail for non-broadcast streams.
   *
   * The [onListen] callback does *not* receive the handlers that were passed
   * to [Stream.listen]. These are automatically set after the call to the
   * [onListen] callback (using [StreamSubscription.onData],
   * [StreamSubscription.onError] and [StreamSubscription.onDone]).
   *
   * Most commonly, an [onListen] callback will first call [Stream.listen] on
   * the provided stream (with the corresponding `cancelOnError` flag), and then
   * return a new [StreamSubscription].
   *
   * There are two common ways to create a StreamSubscription:
   *
   * 1. by allocating a [StreamController] and to return the result of
   *    listening to its stream. It's important to forward pause, resume and
   *    cancel events (unless the transformer intentionally wants to change
   *    this behavior).
   * 2. by creating a new class that implements [StreamSubscription].
   *    Note that the subscription should run callbacks in the [Zone] the
   *    stream was listened to (see [Zone] and [Zone.bindCallback]).
   *
   * Example:
   *
   * ```
   * /// Starts listening to [input] and duplicates all non-error events.
   * StreamSubscription<int> _onListen(Stream<int> input, bool cancelOnError) {
   *   StreamSubscription<String> subscription;
   *   // Create controller that forwards pause, resume and cancel events.
   *   var controller = new StreamController<String>(
   *       onPause: () {
   *         subscription.pause();
   *       },
   *       onResume: () {
   *         subscription.resume();
   *       },
   *       onCancel: () => subscription.cancel(),
   *       sync: true); // "sync" is correct here, since events are forwarded.
   *
   *   // Listen to the provided stream using `cancelOnError`.
   *   subscription = input.listen((data) {
   *     // Duplicate the data.
   *     controller.add(data);
   *     controller.add(data);
   *   },
   *       onError: controller.addError,
   *       onDone: controller.close,
   *       cancelOnError: cancelOnError);
   *
   *   // Return a new [StreamSubscription] by listening to the controller's
   *   // stream.
   *   return controller.stream.listen(null);
   * }
   *
   * // Instantiate a transformer:
   * var duplicator = const StreamTransformer<int, int>(_onListen);
   *
   * // Use as follows:
   * intStream.transform(duplicator);
   * ```
   */
  const factory StreamTransformer(
          StreamSubscription<T> onListen(
              Stream<S> stream, bool cancelOnError)) =
      _StreamSubscriptionTransformer<S, T>;

  /**
   * Creates a [StreamTransformer] that delegates events to the given functions.
   *
   * Example use of a duplicating transformer:
   *
   * ```
   * stringStream.transform(new StreamTransformer<String, String>.fromHandlers(
   *     handleData: (String value, EventSink<String> sink) {
   *       sink.add(value);
   *       sink.add(value);  // Duplicate the incoming events.
   *     }));
   * ```
   *
   * Transformers that are constructed this way cannot use captured state if
   * they are used in streams that can be listened to multiple times.
   * ```
   * StreamController<String> controller;
   * controller = new StreamController.broadcast(onListen: () {
   *   scheduleMicrotask(() {
   *     controller.addError("Bad");
   *     controller.addError("Worse");
   *     controller.addError("Worst");
   *   });
   * });
   * var sharedState = 0;
   * var transformedStream = controller.stream.transform(
   *     new StreamTransformer<String>.fromHandlers(
   *         handleError: (error, stackTrace, sink) {
   *   sharedState++; // Increment shared error-counter.
   *   sink.add("Error $sharedState: $error");
   * }));
   *
   * transformedStream.listen(print);
   * transformedStream.listen(print); // Listen twice.
   * // Listening twice to the same stream makes the transformer share the same
   * // state. Instead of having "Error 1: Bad", "Error 2: Worse",
   * // "Error 3: Worst" as output (each twice for the separate subscriptions),
   * // this program emits:
   * // Error 1: Bad
   * // Error 2: Bad
   * // Error 3: Worse
   * // Error 4: Worse
   * // Error 5: Worst
   * // Error 6: Worst
   * ```
   */
  factory StreamTransformer.fromHandlers(
      {void handleData(S data, EventSink<T> sink),
      void handleError(Object error, StackTrace stackTrace, EventSink<T> sink),
      void handleDone(EventSink<T> sink)}) = _StreamHandlerTransformer<S, T>;

  /**
   * Creates a [StreamTransformer] based on a [bind] callback.
   *
   * The returned stream transformer uses the [bind] argument to implement the
   * [StreamTransformer.bind] API and can be used when the transformation is
   * available as a stream-to-stream function.
   *
   * ```dart
   * final splitDecoded = StreamTransformer<List<int>, String>.fromBind(
   *     (stream) => stream.transform(utf8.decoder).transform(LineSplitter()));
   * ```
   */
  @Since("2.1")
  factory StreamTransformer.fromBind(Stream<T> Function(Stream<S>) bind) =
      _StreamBindTransformer<S, T>;

  /**
   * Adapts [source] to be a `StreamTransformer<TS, TT>`.
   *
   * This allows [source] to be used at the new type, but at run-time it
   * must satisfy the requirements of both the new type and its original type.
   *
   * Data events passed into the returned transformer must also be instances
   * of [SS], and data events produced by [source] for those events must
   * also be instances of [TT].
   */
  static StreamTransformer<TS, TT> castFrom<SS, ST, TS, TT>(
      StreamTransformer<SS, ST> source) {
    return new CastStreamTransformer<SS, ST, TS, TT>(source);
  }

  /**
   * Transforms the provided [stream].
   *
   * Returns a new stream with events that are computed from events of the
   * provided [stream].
   *
   * The [StreamTransformer] interface is completely generic,
   * so it cannot say what subclasses do.
   * Each [StreamTransformer] should document clearly how it transforms the
   * stream (on the class or variable used to access the transformer),
   * as well as any differences from the following typical behavior:
   *
   * * When the returned stream is listened to, it starts listening to the
   *   input [stream].
   * * Subscriptions of the returned stream forward (in a reasonable time)
   *   a [StreamSubscription.pause] call to the subscription of the input
   *   [stream].
   * * Similarly, canceling a subscription of the returned stream eventually
   *   (in reasonable time) cancels the subscription of the input [stream].
   *
   * "Reasonable time" depends on the transformer and stream. Some transformers,
   * like a "timeout" transformer, might make these operations depend on a
   * duration. Others might not delay them at all, or just by a microtask.
   *
   * Transformers are free to handle errors in any way.
   * A transformer implementation may choose to propagate errors,
   * or convert them to other events, or ignore them completely,
   * but if errors are ignored, it should be documented explicitly.
   */
  Stream<T> bind(Stream<S> stream);

  /**
   * Provides a `StreamTransformer<RS, RT>` view of this stream transformer.
   *
   * The resulting transformer will check at run-time that all data events
   * of the stream it transforms are actually instances of [S],
   * and it will check that all data events produced by this transformer
   * are actually instances of [RT].
   */
  StreamTransformer<RS, RT> cast<RS, RT>();
}

/**
 * Base class for implementing [StreamTransformer].
 *
 * Contains default implementations of every method except [bind].
 */
abstract class StreamTransformerBase<S, T> implements StreamTransformer<S, T> {
  const StreamTransformerBase();

  StreamTransformer<RS, RT> cast<RS, RT>() =>
      StreamTransformer.castFrom<S, T, RS, RT>(this);
}

/**
 * An [Iterator] like interface for the values of a [Stream].
 *
 * This wraps a [Stream] and a subscription on the stream. It listens
 * on the stream, and completes the future returned by [moveNext] when the
 * next value becomes available.
 *
 * The stream may be paused between calls to [moveNext].
 */
abstract class StreamIterator<T> {
  /** Create a [StreamIterator] on [stream]. */
  factory StreamIterator(Stream<T> stream)
      // TODO(lrn): use redirecting factory constructor when type
      // arguments are supported.
      =>
      new _StreamIterator<T>(stream);

  /**
   * Wait for the next stream value to be available.
   *
   * Returns a future which will complete with either `true` or `false`.
   * Completing with `true` means that another event has been received and
   * can be read as [current].
   * Completing with `false` means that the stream iteration is done and
   * no further events will ever be available.
   * The future may complete with an error, if the stream produces an error,
   * which also ends iteration.
   *
   * The function must not be called again until the future returned by a
   * previous call is completed.
   */
  Future<bool> moveNext();

  /**
   * The current value of the stream.
   *
   * Is `null` before the first call to [moveNext] and after a call to
   * `moveNext` completes with a `false` result or an error.
   *
   * When a `moveNext` call completes with `true`, the `current` field holds
   * the most recent event of the stream, and it stays like that until the next
   * call to `moveNext`.
   * Between a call to `moveNext` and when its returned future completes,
   * the value is unspecified.
   */
  T get current;

  /**
   * Cancels the stream iterator (and the underlying stream subscription) early.
   *
   * The stream iterator is automatically canceled if the [moveNext] future
   * completes with either `false` or an error.
   *
   * If you need to stop listening for values before the stream iterator is
   * automatically closed, you must call [cancel] to ensure that the stream
   * is properly closed.
   *
   * If [moveNext] has been called when the iterator is canceled,
   * its returned future will complete with `false` as value,
   * as will all further calls to [moveNext].
   *
   * Returns a future if the cancel-operation is not completed synchronously.
   * Otherwise returns `null`.
   */
  Future cancel();
}

/**
 * Wraps an [_EventSink] so it exposes only the [EventSink] interface.
 */
class _ControllerEventSinkWrapper<T> implements EventSink<T> {
  EventSink _sink;
  _ControllerEventSinkWrapper(this._sink);

  void add(T data) {
    _sink.add(data);
  }

  void addError(error, [StackTrace stackTrace]) {
    _sink.addError(error, stackTrace);
  }

  void close() {
    _sink.close();
  }
}
