// 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.

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]) {
    // TODO(40614): Remove once non-nullability is sound.
    checkNotNullable(error, "error");
    return (_AsyncStreamController<T>(null, null, null, null)
          .._addError(error, stackTrace ?? AsyncError.defaultStackTrace(error))
          .._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 single-subscription 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.
    void onValue(T value) {
      if (!controller.isClosed) {
        controller._add(value);
        if (--count == 0) controller._closeUnchecked();
      }
    }

    void onError(Object 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 multi-subscription stream.
  ///
  /// Each time the created stream is listened to,
  /// the [onListen] callback is invoked with a new [MultiStreamController]
  /// which forwards events to the [StreamSubscription]
  /// returned by that [listen] call.
  ///
  /// This allows each listener to be treated as an individual stream.
  ///
  /// The [MultiStreamController] does not support reading its
  /// [StreamController.stream]. Setting its [StreamController.onListen]
  /// has no effect since the [onListen] callback is called instead,
  /// and the [StreamController.onListen] won't be called later.
  /// The controller acts like an asynchronous controller,
  /// but provides extra methods for delivering events synchronously.
  ///
  /// If [isBroadcast] is set to `true`, the returned stream's
  /// [Stream.isBroadcast] will be `true`.
  /// This has no effect on the stream behavior,
  /// it is up to the [onListen] function
  /// to act like a broadcast stream if it claims to be one.
  ///
  /// A multi-subscription stream can behave like any other stream.
  /// If the [onListen] callback throws on every call after the first,
  /// the stream behaves like a single-subscription stream.
  /// If the stream emits the same events to all current listeners,
  /// it behaves like a broadcast stream.
  ///
  /// It can also choose to emit different events to different listeners.
  /// For example, a stream which repeats the most recent
  /// non-`null` event to new listeners, could be implemented as this example:
  /// ```dart
  /// extension StreamRepeatLatestExtension<T extends Object> on Stream<T> {
  ///   Stream<T> repeatLatest() {
  ///     var done = false;
  ///     T? latest = null;
  ///     var currentListeners = <MultiStreamController<T>>{};
  ///     this.listen((event) {
  ///       latest = event;
  ///       for (var listener in [...currentListeners]) listener.addSync(event);
  ///     }, onError: (Object error, StackTrace stack) {
  ///       for (var listener in [...currentListeners]) listener.addErrorSync(error, stack);
  ///     }, onDone: () {
  ///       done = true;
  ///       latest = null;
  ///       for (var listener in currentListeners) listener.closeSync();
  ///       currentListeners.clear();
  ///     });
  ///     return Stream.multi((controller) {
  ///       if (done) {
  ///         controller.close();
  ///         return;
  ///       }
  ///       currentListeners.add(controller);
  ///       var latestValue = latest;
  ///       if (latestValue != null) controller.add(latestValue);
  ///       controller.onCancel = () {
  ///         currentListeners.remove(controller);
  ///       };
  ///     });
  ///   }
  /// }
  /// ```
  @Since("2.9")
  factory Stream.multi(void Function(MultiStreamController<T>) onListen,
      {bool isBroadcast = false}) {
    return _MultiStream<T>(onListen, isBroadcast);
  }

  /// 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.
  ///
  /// The [period] must a non-negative [Duration].
  ///
  /// If [computation] is omitted the event values will all be `null`.
  ///
  /// The [computation] must not be omitted if the event type [T] does not
  /// allow `null` as a value.
  factory Stream.periodic(Duration period,
      [T computation(int computationCount)?]) {
    if (computation == null && !typeAcceptsNull<T>()) {
      throw ArgumentError.value(null, "computation",
          "Must not be omitted when the event type is non-nullable");
    }
    var controller = _SyncStreamController<T>(null, null, null, null);
    // Counts the time that the Stream was running (and not paused).
    Stopwatch watch = new Stopwatch();
    controller.onListen = () {
      int computationCount = 0;
      void sendEvent(_) {
        watch.reset();
        if (computation != null) {
          T event;
          try {
            event = computation(computationCount++);
          } catch (e, s) {
            controller.addError(e, s);
            return;
          }
          controller.add(event);
        } else {
          controller.add(null as T); // We have checked that null is T.
        }
      }

      Timer timer = Timer.periodic(period, sendEvent);
      controller
        ..onCancel = () {
          timer.cancel();
          return Future._nullFuture;
        }
        ..onPause = () {
          watch.stop();
          timer.cancel();
        }
        ..onResume = () {
          Duration elapsed = watch.elapsed;
          watch.start();
          timer = new Timer(period - elapsed, () {
            timer = Timer.periodic(period, sendEvent);
            sendEvent(null);
          });
        };
    };
    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:
  /// ```dart
  /// 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) => Stream<String>.eventTransformed(
  ///       stream,
  ///       (EventSink sink) => DuplicationSink(sink));
  /// }
  ///
  /// stringStream.transform(DuplicationTransformer());
  /// ```
  /// The resulting stream is a broadcast stream if [source] is.
  factory Stream.eventTransformed(
      Stream<dynamic> source, EventSink<dynamic> 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.
  ///
  /// Cancelling is intended to be used when there are no current subscribers.
  /// If the subscription passed to `onListen` or `onCancel` is cancelled,
  /// then no further events are ever emitted by current subscriptions on
  /// the returned broadcast stream, not even a done event.
  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 Function(Object error)` or
  /// `void Function(Object error, StackTrace)`.
  /// The function type determines whether [onError] is invoked with a stack
  /// trace argument.
  /// The stack trace argument may be [StackTrace.empty] if this stream received
  /// an error without a 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;
    if (isBroadcast) {
      controller = _SyncBroadcastStreamController<E>(null, null);
    } else {
      controller = _SyncStreamController<E>(null, null, null, null);
    }

    controller.onListen = () {
      StreamSubscription<T> subscription = this.listen(null,
          onError: controller._addError, // Avoid Zone error replacement.
          onDone: controller.close);
      FutureOr<Null> add(E value) {
        controller.add(value);
      }

      final addError = controller._addError;
      final resume = subscription.resume;
      subscription.onData((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(resume);
        } else {
          // TODO(40014): Remove cast when type promotion works.
          controller.add(newValue as dynamic);
        }
      });
      controller.onCancel = subscription.cancel;
      if (!isBroadcast) {
        controller
          ..onPause = subscription.pause
          ..onResume = resume;
      }
    };
    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;
    if (isBroadcast) {
      controller = _SyncBroadcastStreamController<E>(null, null);
    } else {
      controller = _SyncStreamController<E>(null, null, null, null);
    }

    controller.onListen = () {
      StreamSubscription<T> subscription = this.listen(null,
          onError: controller._addError, // Avoid Zone error replacement.
          onDone: controller.close);
      subscription.onData((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);
        }
      });
      controller.onCancel = subscription.cancel;
      if (!isBroadcast) {
        controller
          ..onPause = subscription.pause
          ..onResume = subscription.resume;
      }
    };
    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 Function(Object error)` or
  /// `void Function(Object error, StackTrace)`.
  /// The function type determines whether [onError] is invoked with a stack
  /// trace argument.
  /// The stack trace argument may be [StackTrace.empty] 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)?}) {
    if (onError is! void Function(Object, StackTrace) &&
        onError is! void Function(Object)) {
      throw ArgumentError.value(
          onError,
          "onError",
          "Error handler must accept one Object or one Object and a StackTrace"
              " as arguments.");
    }
    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
  /// ```dart
  /// 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;
    late T value;
    StreamSubscription<T> subscription =
        this.listen(null, 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);
    subscription.onData((T element) {
      if (seenFirst) {
        _runUserCode(() => combine(value, element), (T newValue) {
          value = newValue;
        }, _cancelAndErrorClosure(subscription, result));
      } else {
        value = element;
        seenFirst = 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<T> subscription =
        this.listen(null, onError: result._completeError, onDone: () {
      result._complete(value);
    }, cancelOnError: true);
    subscription.onData((T element) {
      _runUserCode(() => combine(value, element), (S newValue) {
        value = newValue;
      }, _cancelAndErrorClosure(subscription, result));
    });
    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();
    bool first = true;
    StreamSubscription<T> subscription =
        this.listen(null, onError: result._completeError, onDone: () {
      result._complete(buffer.toString());
    }, cancelOnError: true);
    subscription.onData(separator.isEmpty
        ? (T element) {
            try {
              buffer.write(element);
            } catch (e, s) {
              _cancelAndErrorWithReplacement(subscription, result, e, s);
            }
          }
        : (T element) {
            if (!first) {
              buffer.write(separator);
            }
            first = false;
            try {
              buffer.write(element);
            } catch (e, s) {
              _cancelAndErrorWithReplacement(subscription, result, e, s);
            }
          });
    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<T> subscription =
        this.listen(null, onError: future._completeError, onDone: () {
      future._complete(false);
    }, cancelOnError: true);
    subscription.onData((T element) {
      _runUserCode(() => (element == needle), (bool isMatch) {
        if (isMatch) {
          _cancelAndValue(subscription, future, true);
        }
      }, _cancelAndErrorClosure(subscription, future));
    });
    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<T> subscription =
        this.listen(null, onError: future._completeError, onDone: () {
      future._complete(null);
    }, cancelOnError: true);
    subscription.onData((T element) {
      _runUserCode<void>(() => action(element), (_) {},
          _cancelAndErrorClosure(subscription, future));
    });
    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<T> subscription =
        this.listen(null, onError: future._completeError, onDone: () {
      future._complete(true);
    }, cancelOnError: true);
    subscription.onData((T element) {
      _runUserCode(() => test(element), (bool isMatch) {
        if (!isMatch) {
          _cancelAndValue(subscription, future, false);
        }
      }, _cancelAndErrorClosure(subscription, future));
    });
    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<T> subscription =
        this.listen(null, onError: future._completeError, onDone: () {
      future._complete(false);
    }, cancelOnError: true);
    subscription.onData((T element) {
      _runUserCode(() => test(element), (bool isMatch) {
        if (isMatch) {
          _cancelAndValue(subscription, future, true);
        }
      }, _cancelAndErrorClosure(subscription, future));
    });
    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 `false`.
  /// If this stream ends without emitting any elements, the returned future is
  /// completed with `true`.
  ///
  /// 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<T> subscription =
        this.listen(null, onError: future._completeError, onDone: () {
      future._complete(true);
    }, cancelOnError: true);
    subscription.onData((_) {
      _cancelAndValue(subscription, future, false);
    });
    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 created by `<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, 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].
  ///
  /// The [futureValue] must not be omitted if `null` is not assignable to [E].
  Future<E> drain<E>([E? futureValue]) {
    if (futureValue == null) {
      futureValue = futureValue as E;
    }
    return 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<T> subscription =
        this.listen(null, onError: future._completeError, onDone: () {
      try {
        throw IterableElementError.noElement();
      } catch (e, s) {
        _completeWithErrorCallback(future, e, s);
      }
    }, cancelOnError: true);
    subscription.onData((T value) {
      _cancelAndValue(subscription, future, value);
    });
    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>();
    late 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>();
    late T result;
    bool foundResult = false;
    StreamSubscription<T> subscription =
        this.listen(null, onError: future._completeError, onDone: () {
      if (foundResult) {
        future._complete(result);
        return;
      }
      try {
        throw IterableElementError.noElement();
      } catch (e, s) {
        _completeWithErrorCallback(future, e, s);
      }
    }, cancelOnError: true);
    subscription.onData((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;
    });
    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<T> subscription =
        this.listen(null, onError: future._completeError, onDone: () {
      if (orElse != null) {
        _runUserCode(orElse, future._complete, future._completeError);
        return;
      }
      try {
        // Sets stackTrace on error.
        throw IterableElementError.noElement();
      } catch (e, s) {
        _completeWithErrorCallback(future, e, s);
      }
    }, cancelOnError: true);

    subscription.onData((T value) {
      _runUserCode(() => test(value), (bool isMatch) {
        if (isMatch) {
          _cancelAndValue(subscription, future, value);
        }
      }, _cancelAndErrorClosure(subscription, future));
    });
    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();
    late T result;
    bool foundResult = false;
    StreamSubscription<T> subscription =
        this.listen(null, 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);

    subscription.onData((T value) {
      _runUserCode(() => test(value), (bool isMatch) {
        if (isMatch) {
          foundResult = true;
          result = value;
        }
      }, _cancelAndErrorClosure(subscription, future));
    });
    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>();
    late T result;
    bool foundResult = false;
    StreamSubscription<T> subscription =
        this.listen(null, 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);

    subscription.onData((T value) {
      _runUserCode(() => 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));
    });
    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) {
    RangeError.checkNotNegative(index, "index");
    _Future<T> result = new _Future<T>();
    int elementIndex = 0;
    StreamSubscription<T> subscription;
    subscription =
        this.listen(null, onError: result._completeError, onDone: () {
      result._completeError(
          new RangeError.index(index, this, "index", null, elementIndex),
          StackTrace.empty);
    }, cancelOnError: true);
    subscription.onData((T value) {
      if (index == elementIndex) {
        _cancelAndValue(subscription, result, value);
        return;
      }
      elementIndex += 1;
    });

    return result;
  }

  /// 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;
    if (isBroadcast) {
      controller = new _SyncBroadcastStreamController<T>(null, null);
    } else {
      controller = new _SyncStreamController<T>(null, null, null, null);
    }

    Zone zone = Zone.current;
    // Register callback immediately.
    _TimerCallback timeoutCallback;
    if (onTimeout == null) {
      timeoutCallback = () {
        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<void, EventSink<T>>(onTimeout);
      var wrapper = new _ControllerEventSinkWrapper<T>(null);
      timeoutCallback = () {
        wrapper._sink = controller; // Only valid during call.
        zone.runUnaryGuarded(registeredOnTimeout, wrapper);
        wrapper._sink = null;
      };
    }

    // All further setup happens inside `onListen`.
    controller.onListen = () {
      Timer timer = zone.createTimer(timeLimit, timeoutCallback);
      var subscription = this.listen(null);
      // Set up event forwarding. Each data or error event resets the timer
      subscription
        ..onData((T event) {
          timer.cancel();
          timer = zone.createTimer(timeLimit, timeoutCallback);
          // Controller is synchronous, and the call might close the stream
          // and cancel the timer,
          // so create the Timer before calling into add();
          // issue: https://github.com/dart-lang/sdk/issues/37565
          controller.add(event);
        })
        ..onError((Object error, StackTrace stackTrace) {
          timer.cancel();
          timer = zone.createTimer(timeLimit, timeoutCallback);
          controller._addError(
              error, stackTrace); // Avoid Zone error replacement.
        })
        ..onDone(() {
          timer.cancel();
          controller.close();
        });
      // Set up further controller callbacks.
      controller.onCancel = () {
        timer.cancel();
        return subscription.cancel();
      };
      if (!isBroadcast) {
        controller
          ..onPause = () {
            timer.cancel();
            subscription.pause();
          }
          ..onResume = () {
            subscription.resume();
            timer = zone.createTimer(timeLimit, timeoutCallback);
          };
      }
    };

    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.
  ///
  /// Typically, cleanup happens 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.
  ///
  /// If the cleanup throws, which it really shouldn't, the returned future
  /// completes with that error.
  Future<void> cancel();

  /// Replaces the data event handler of this subscription.
  ///
  /// The [handleData] function is called for each data event of the stream
  /// after this function is called.
  /// If [handleData] is `null`, data events 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()?);

  /// Requests 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.
  void pause([Future<void>? resumeSignal]);

  /// Resumes 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].
  ///
  /// If [futureValue] is omitted, the value `null as E` is used as a default.
  /// If `E` is not nullable, this will throw immediately when [asFuture]
  /// is called.
  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:
  ///
  /// ```dart
  /// /// Starts listening to [input] and duplicates all non-error events.
  /// StreamSubscription<int> _onListen(Stream<int> input, bool cancelOnError) {
  ///   late 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.
  ///   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:
  ///
  /// ```dart
  /// stringStream.transform(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.
  ///
  /// ```dart
  /// StreamController<String> controller = StreamController.broadcast()
  /// controller.onListen = () {
  ///   scheduleMicrotask(() {
  ///     controller.addError("Bad");
  ///     controller.addError("Worse");
  ///     controller.addError("Worst");
  ///   });
  /// };
  /// var sharedState = 0;
  /// var transformedStream = controller.stream.transform(
  ///     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].
///
/// The [current] value must only be used after a future returned by [moveNext]
/// has completed with `true`, and only until [moveNext] is called again.
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.
  ///
  /// 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]. This value must only be read after a call to [moveNext]
  /// has completed with `true`, and only until the [moveNext] is called again.
  ///
  /// If the StreamIterator has not yet been moved to the first element
  /// ([moveNext] has not been called and completed yet), or if the
  /// StreamIterator has been moved past the last element ([moveNext] has
  /// returned `false`), then [current] is unspecified. A [StreamIterator] may
  /// either throw or return an iterator-specific default value in that case.
  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 which completes when the cancellation is complete.
  /// This can be an already completed future if the cancellation happens
  /// synchronously.
  Future cancel();
}

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

  EventSink _ensureSink() {
    var sink = _sink;
    if (sink == null) throw StateError("Sink not available");
    return sink;
  }

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

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

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

/// An enhanced stream controller provided by [Stream.multi].
///
/// Acts like a normal asynchronous controller, but also allows
/// adding events synchronously.
/// As with any synchronous event delivery, the sender should be very careful
/// to not deliver events at times when a new listener might not
/// be ready to receive them.
/// That generally means only delivering events synchronously in response to other
/// asynchronous events, because that is a time when an asynchronous event could
/// happen.
@Since("2.9")
abstract class MultiStreamController<T> implements StreamController<T> {
  /// Adds and delivers an event.
  ///
  /// Adds an event like [add] and attempts to deliver it immediately.
  /// Delivery can be delayed if other previously added events are
  /// still pending delivery, if the subscription is paused,
  /// or if the subscription isn't listening yet.
  void addSync(T value);

  /// Adds and delivers an error event.
  ///
  /// Adds an error like [addError] and attempts to deliver it immediately.
  /// Delivery can be delayed if other previously added events are
  /// still pending delivery, if the subscription is paused,
  /// or if the subscription isn't listening yet.
  void addErrorSync(Object error, [StackTrace? stackTrace]);

  /// Closes the controller and delivers a done event.
  ///
  /// Closes the controller like [close] and attempts to deliver a "done"
  /// event immediately.
  /// Delivery can be delayed if other previously added events are
  /// still pending delivery, if the subscription is paused,
  /// or if the subscription isn't listening yet.
  /// If it's necessary to know whether the "done" event has been delivered,
  /// [done] future will complete when that has happened.
  void closeSync();
}
