Line data Source code
1 : // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file 2 : // for details. All rights reserved. Use of this source code is governed by a 3 : // BSD-style license that can be found in the LICENSE file. 4 : 5 : import 'dart:async'; 6 : 7 : import '../stream_sink_transformer.dart'; 8 : import '../delegate/stream_sink.dart'; 9 : 10 : /// The type of the callback for handling data events. 11 : typedef HandleData<S, T> = void Function(S data, EventSink<T> sink); 12 : 13 : /// The type of the callback for handling error events. 14 : typedef HandleError<T> = void Function(Object error, StackTrace, EventSink<T>); 15 : 16 : /// The type of the callback for handling done events. 17 : typedef HandleDone<T> = void Function(EventSink<T> sink); 18 : 19 : /// A [StreamSinkTransformer] that delegates events to the given handlers. 20 : class HandlerTransformer<S, T> implements StreamSinkTransformer<S, T> { 21 : /// The handler for data events. 22 : final HandleData<S, T>? _handleData; 23 : 24 : /// The handler for error events. 25 : final HandleError<T>? _handleError; 26 : 27 : /// The handler for done events. 28 : final HandleDone<T>? _handleDone; 29 : 30 0 : HandlerTransformer(this._handleData, this._handleError, this._handleDone); 31 : 32 0 : @override 33 0 : StreamSink<S> bind(StreamSink<T> sink) => _HandlerSink<S, T>(this, sink); 34 : } 35 : 36 : /// A sink created by [HandlerTransformer]. 37 : class _HandlerSink<S, T> implements StreamSink<S> { 38 : /// The transformer that created this sink. 39 : final HandlerTransformer<S, T> _transformer; 40 : 41 : /// The original sink that's being transformed. 42 : final StreamSink<T> _inner; 43 : 44 : /// The wrapper for [_inner] whose [StreamSink.close] method can't emit 45 : /// errors. 46 : final StreamSink<T> _safeCloseInner; 47 : 48 0 : @override 49 0 : Future get done => _inner.done; 50 : 51 0 : _HandlerSink(this._transformer, StreamSink<T> inner) 52 : : _inner = inner, 53 0 : _safeCloseInner = _SafeCloseSink<T>(inner); 54 : 55 0 : @override 56 : void add(S event) { 57 0 : var handleData = _transformer._handleData; 58 : if (handleData == null) { 59 0 : _inner.add(event as T); 60 : } else { 61 0 : handleData(event, _safeCloseInner); 62 : } 63 : } 64 : 65 0 : @override 66 : void addError(error, [StackTrace? stackTrace]) { 67 0 : var handleError = _transformer._handleError; 68 : if (handleError == null) { 69 0 : _inner.addError(error, stackTrace); 70 : } else { 71 0 : handleError(error, stackTrace ?? AsyncError.defaultStackTrace(error), 72 0 : _safeCloseInner); 73 : } 74 : } 75 : 76 0 : @override 77 : Future addStream(Stream<S> stream) { 78 0 : return _inner.addStream(stream.transform( 79 0 : StreamTransformer<S, T>.fromHandlers( 80 0 : handleData: _transformer._handleData, 81 0 : handleError: _transformer._handleError, 82 : handleDone: _closeSink))); 83 : } 84 : 85 0 : @override 86 : Future close() { 87 0 : var handleDone = _transformer._handleDone; 88 0 : if (handleDone == null) return _inner.close(); 89 : 90 0 : handleDone(_safeCloseInner); 91 0 : return _inner.done; 92 : } 93 : } 94 : 95 : /// A wrapper for [StreamSink]s that swallows any errors returned by [close]. 96 : /// 97 : /// [HandlerTransformer] passes this to its handlers to ensure that when they 98 : /// call [close], they don't leave any dangling [Future]s behind that might emit 99 : /// unhandleable errors. 100 : class _SafeCloseSink<T> extends DelegatingStreamSink<T> { 101 0 : _SafeCloseSink(StreamSink<T> inner) : super(inner); 102 : 103 0 : @override 104 0 : Future close() => super.close().catchError((_) {}); 105 : } 106 : 107 : /// A function to pass as a [StreamTransformer]'s `handleDone` callback. 108 0 : void _closeSink(EventSink sink) { 109 0 : sink.close(); 110 : }