sdk icon indicating copy to clipboard operation
sdk copied to clipboard

Utilities: Sink.withCallback and Sink.nonClosing

Open jonasfj opened this issue 3 years ago • 1 comments

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?

jonasfj avatar Sep 16 '22 12:09 jonasfj

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.

lrhn avatar Sep 16 '22 13:09 lrhn