Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1376)

Unified Diff: sdk/lib/async/stream_pipe.dart

Issue 11953103: Add public-facing method and class that allows intercepting stream events. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Address review comments Created 7 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « sdk/lib/async/stream_impl.dart ('k') | tests/lib/async/stream_controller_test.dart » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: sdk/lib/async/stream_pipe.dart
diff --git a/sdk/lib/async/stream_pipe.dart b/sdk/lib/async/stream_pipe.dart
index 59cf3829bec092c83081e649c71f4bb336805c63..895e3313b5189af2b2f7276b99d4ffc30e772d77 100644
--- a/sdk/lib/async/stream_pipe.dart
+++ b/sdk/lib/async/stream_pipe.dart
@@ -53,20 +53,23 @@ abstract class _ForwardingStream<S, T> extends Stream<T> {
bool get isBroadcast => _source.isBroadcast;
- bool asBroadcastStream() => _source.asBroadcastStream;
-
- StreamSubscription listen(void onData(T value),
- { void onError(AsyncError error),
- void onDone(),
- bool unsubscribeOnError }) {
+ StreamSubscription<T> listen(void onData(T value),
+ { void onError(AsyncError error),
+ void onDone(),
+ bool unsubscribeOnError }) {
if (onData == null) onData = _nullDataHandler;
if (onError == null) onError = _nullErrorHandler;
if (onDone == null) onDone = _nullDoneHandler;
unsubscribeOnError = identical(true, unsubscribeOnError);
- StreamSubscription subscription =
- new _ForwardingStreamSubscription<S, T>(
- this, onData, onError, onDone, unsubscribeOnError);
- return subscription;
+ return _createSubscription(onData, onError, onDone, unsubscribeOnError);
+ }
+
+ StreamSubscription<T> _createSubscription(void onData(T value),
+ void onError(AsyncError error),
+ void onDone(),
+ bool unsubscribeOnError) {
+ return new _ForwardingStreamSubscription<S, T>(
+ this, onData, onError, onDone, unsubscribeOnError);
}
// Override the following methods in subclasses to change the behavior.
@@ -86,33 +89,26 @@ abstract class _ForwardingStream<S, T> extends Stream<T> {
}
/**
- * Abstract superclass for subscriptions that forward to other subscriptions.
+ * Common behavior of [StreamSubscription] classes.
+ *
+ * Stores and allows updating of the event handlers of a [StreamSubscription].
*/
-class _ForwardingStreamSubscription<S, T>
- implements StreamSubscription<T>, _StreamOutputSink<T> {
- final _ForwardingStream<S, T> _stream;
+abstract class _BaseStreamSubscription<T> implements StreamSubscription<T> {
// TODO(ahe): Restore type when feature is implemented in dart2js
// checked mode. http://dartbug.com/7733
var /* _DataHandler<T> */ _onData;
_ErrorHandler _onError;
_DoneHandler _onDone;
- StreamSubscription<S> _subscription;
-
- _ForwardingStreamSubscription(this._stream,
- this._onData,
- this._onError,
- this._onDone,
- bool unsubscribeOnError) {
- _subscription =
- _stream._source.listen(_handleData,
- onError: _handleError,
- onDone: _handleDone,
- unsubscribeOnError: unsubscribeOnError);
+ _BaseStreamSubscription(this._onData,
+ this._onError,
+ this._onDone) {
+ if (_onData == null) _onData = _nullDataHandler;
+ if (_onError == null) _onError = _nullErrorHandler;
+ if (_onDone == null) _onDone = _nullDoneHandler;
}
// StreamSubscription interface.
-
void onData(void handleData(T event)) {
if (handleData == null) handleData = _nullDataHandler;
_onData = handleData;
@@ -128,6 +124,39 @@ class _ForwardingStreamSubscription<S, T>
_onDone = handleDone;
}
+ void pause([Future resumeSignal]);
+
+ void resume();
+
+ void cancel();
+}
+
+
+/**
+ * Abstract superclass for subscriptions that forward to other subscriptions.
+ */
+class _ForwardingStreamSubscription<S, T>
+ extends _BaseStreamSubscription<T> implements _StreamOutputSink<T> {
+ final _ForwardingStream<S, T> _stream;
+ final bool _unsubscribeOnError;
+
+ StreamSubscription<S> _subscription;
+
+ _ForwardingStreamSubscription(this._stream,
+ void onData(T data),
+ void onError(AsyncError error),
+ void onDone(),
+ this._unsubscribeOnError)
+ : super(onData, onError, onDone) {
+ // Don't unsubscribe on incoming error, only if we send an error forwards.
+ _subscription =
+ _stream._source.listen(_handleData,
+ onError: _handleError,
+ onDone: _handleDone);
+ }
+
+ // StreamSubscription interface.
+
void pause([Future resumeSignal]) {
if (_subscription == null) {
throw new StateError("Subscription has been unsubscribed");
@@ -158,6 +187,10 @@ class _ForwardingStreamSubscription<S, T>
void _sendError(AsyncError error) {
_onError(error);
+ if (_unsubscribeOnError) {
+ _subscription.cancel();
+ _subscription = null;
+ }
}
void _sendDone() {
@@ -428,11 +461,28 @@ class _DistinctStream<T> extends _ForwardingStream<T, T> {
}
}
+// Stream transformations and event transformations.
typedef void _TransformDataHandler<S, T>(S data, StreamSink<T> sink);
typedef void _TransformErrorHandler<T>(AsyncError data, StreamSink<T> sink);
typedef void _TransformDoneHandler<T>(StreamSink<T> sink);
+/** Default data handler forwards all data. */
+void _defaultHandleData(var data, StreamSink sink) {
+ sink.add(data);
+}
+
+/** Default error handler forwards all errors. */
+void _defaultHandleError(AsyncError error, StreamSink sink) {
+ sink.signalError(error);
+}
+
+/** Default done handler forwards done. */
+void _defaultHandleDone(StreamSink sink) {
+ sink.close();
+}
+
+
/**
* A stream transformer that intercepts all events and can generate any event as
* output.
@@ -467,7 +517,7 @@ class _StreamTransformerImpl<S, T> implements StreamTransformer<S, T> {
try {
_onData(data, _sink);
} catch (e, s) {
- _stream._signalError(_asyncError(e, s));
+ _sink.signalError(_asyncError(e, s));
}
}
@@ -475,7 +525,7 @@ class _StreamTransformerImpl<S, T> implements StreamTransformer<S, T> {
try {
_onError(error, _sink);
} catch (e, s) {
- _stream._signalError(_asyncError(e, s, error));
+ _sink.signalError(_asyncError(e, s, error));
}
}
@@ -483,22 +533,9 @@ class _StreamTransformerImpl<S, T> implements StreamTransformer<S, T> {
try {
_onDone(_sink);
} catch (e, s) {
- _stream._signalError(_asyncError(e, s));
+ _sink.signalError(_asyncError(e, s));
}
}
-
- /** Default data handler forwards all data. */
- static void _defaultHandleData(var data, StreamSink sink) {
- sink.add(data);
- }
- /** Default error handler forwards all errors. */
- static void _defaultHandleError(AsyncError error, StreamSink sink) {
- sink.signalError(error);
- }
- /** Default done handler forwards done. */
- static void _defaultHandleDone(StreamSink sink) {
- sink.close();
- }
}
/** Creates a [StreamSink] from a [_StreamImpl]'s input methods. */
@@ -509,3 +546,51 @@ class _StreamImplSink<T> implements StreamSink<T> {
void signalError(AsyncError error) { _target._signalError(error); }
void close() { _target._close(); }
}
+
+
+/**
+ * A stream transformer that intercepts all events and can generate any event as
+ * output.
+ *
+ * Each incoming event on the source stream is passed to the corresponding
+ * provided event handler, along with a [StreamSink] linked to the output
+ * Stream.
+ * The handler can then decide exactly which events to send to the output.
+ */
+class _StreamEventTransformerImpl<S, T>
+ implements StreamEventTransformer<S, T> {
+ final _TransformDataHandler<S, T> _handleData;
+ final _TransformErrorHandler<T> _handleError;
+ final _TransformDoneHandler<T> _handleDone;
+
+ _StreamEventTransformerImpl(void onData(S data, StreamSink<T> sink),
+ void onError(AsyncError data, StreamSink<T> sink),
+ void onDone(StreamSink<T> sink))
+ : this._handleData = (onData == null ? _defaultHandleData : onData),
+ this._handleError = (onError == null ? _defaultHandleError : onError),
+ this._handleDone = (onDone == null ? _defaultHandleDone : onDone);
+
+ void handleData(S data, StreamSink<T> sink) {
+ try {
+ _handleData(data, sink);
+ } catch (e, s) {
+ sink.signalError(_asyncError(e, s));
+ }
+ }
+
+ void handleError(AsyncError error, StreamSink<T> sink) {
+ try {
+ _handleError(error, sink);
+ } catch (e, s) {
+ sink.signalError(_asyncError(e, s, error));
+ }
+ }
+
+ void handleDone(StreamSink<T> sink) {
+ try {
+ _handleDone(sink);
+ } catch (e, s) {
+ sink.signalError(_asyncError(e, s));
+ }
+ }
+}
« no previous file with comments | « sdk/lib/async/stream_impl.dart ('k') | tests/lib/async/stream_controller_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698