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 'package:async/async.dart'; 6 : 7 : import '../stream_channel.dart'; 8 : 9 : /// A [channel] where the source and destination are provided later. 10 : /// 11 : /// The [channel] is a normal channel that can be listened to and that events 12 : /// can be added to immediately, but until [setChannel] is called it won't emit 13 : /// any events and all events added to it will be buffered. 14 : class StreamChannelCompleter<T> { 15 : /// The completer for this channel's stream. 16 : final _streamCompleter = StreamCompleter<T>(); 17 : 18 : /// The completer for this channel's sink. 19 : final _sinkCompleter = StreamSinkCompleter<T>(); 20 : 21 : /// The channel for this completer. 22 0 : StreamChannel<T> get channel => _channel; 23 : late final StreamChannel<T> _channel; 24 : 25 : /// Whether [setChannel] has been called. 26 : bool _set = false; 27 : 28 : /// Convert a `Future<StreamChannel>` to a `StreamChannel`. 29 : /// 30 : /// This creates a channel using a channel completer, and sets the source 31 : /// channel to the result of the future when the future completes. 32 : /// 33 : /// If the future completes with an error, the returned channel's stream will 34 : /// instead contain just that error. The sink will silently discard all 35 : /// events. 36 0 : static StreamChannel fromFuture(Future<StreamChannel> channelFuture) { 37 0 : var completer = StreamChannelCompleter(); 38 0 : channelFuture.then(completer.setChannel, onError: completer.setError); 39 0 : return completer.channel; 40 : } 41 : 42 0 : StreamChannelCompleter() { 43 0 : _channel = StreamChannel<T>(_streamCompleter.stream, _sinkCompleter.sink); 44 : } 45 : 46 : /// Set a channel as the source and destination for [channel]. 47 : /// 48 : /// A channel may be set at most once. 49 : /// 50 : /// Either [setChannel] or [setError] may be called at most once. Trying to 51 : /// call either of them again will fail. 52 0 : void setChannel(StreamChannel<T> channel) { 53 0 : if (_set) throw StateError('The channel has already been set.'); 54 0 : _set = true; 55 : 56 0 : _streamCompleter.setSourceStream(channel.stream); 57 0 : _sinkCompleter.setDestinationSink(channel.sink); 58 : } 59 : 60 : /// Indicates that there was an error connecting the channel. 61 : /// 62 : /// This makes the stream emit [error] and close. It makes the sink discard 63 : /// all its events. 64 : /// 65 : /// Either [setChannel] or [setError] may be called at most once. Trying to 66 : /// call either of them again will fail. 67 0 : void setError(Object error, [StackTrace? stackTrace]) { 68 0 : if (_set) throw StateError('The channel has already been set.'); 69 0 : _set = true; 70 : 71 0 : _streamCompleter.setError(error, stackTrace); 72 0 : _sinkCompleter.setDestinationSink(NullStreamSink()); 73 : } 74 : }