dart-lang / sdk

The Dart SDK, including the VM, JS and Wasm compilers, analysis, core libraries, and more.
https://dart.dev
BSD 3-Clause "New" or "Revised" License
10.28k stars 1.59k forks source link

Utilities: Sink.withCallback and Sink.nonClosing #49976

Open jonasfj opened 2 years ago

jonasfj commented 2 years ago

Working with Sink it would be nice to have utility factory constructors as follows:

abstract class Sink<T> {
  /// Create a [Sink] where data added invokes [accumulate].
  ///
  /// If [onClose] is given this callback will be invoked when the [Sink] is closed.
  factory Sink.withCallback(void Function(T value) accumulate, [void Function()? onClose]) = _CallbackSink;

  /// Create a [Sink] that forwards data add to [wrappedSink], but doesn't close [wrappedSink].
  ///
  /// If [onClose] is given this callback will be invoked when the [Sink] is closed.
  factory Sink.nonClosing(Sink<T> wrappedSink, [void Function()? onClose]) = _NonClosingSink;

  void add(T data);
  void close();
}

class _CallbackSink<T> implements Sink<T> {
  final void Function(T value) _accumulate;
  final void Function()? _onClose;
  _CallbackSink(this._accumulate, [this._onClose]);

  void add(T data) => _accumulate(data);
  void close() {
    final onClose = _onClose;
    if (onClose != null) {
      onClose();
    }
  }
}

class _CallbackSink<T> implements Sink<T> {
  final Sink<T> _wrappedSink;
  final void Function()? _onClose;
  _CallbackSink(this._wrappedSink, [this._onClose]);

  void add(T data) => _wrappedSink.add(data);
  void close() {
    final onClose = _onClose;
    if (onClose != null) {
      onClose();
    }
  }
}

The withCallback constructor already exists in ByteConversionSink.withCallback, but it's pretty hard to find. And less general as it only works for Sink<List<int>> (which is implemented by ByteConversionSink).

cc @lrhn thoughts?

lrhn commented 2 years ago

Makes sense.

We have a number of "sink-like" classes, including the ByteConversionSink. It makes sense that they could all use an easy way to create an instace.