Add type-coercion functions. These match (and are based on) the coercion functions in dart-lang/async. R=sigmund@google.com Review URL: https://codereview.chromium.org//1966853003 .
diff --git a/pkgs/stream_channel/.analysis_options b/pkgs/stream_channel/.analysis_options new file mode 100644 index 0000000..a10d4c5 --- /dev/null +++ b/pkgs/stream_channel/.analysis_options
@@ -0,0 +1,2 @@ +analyzer: + strong-mode: true
diff --git a/pkgs/stream_channel/CHANGELOG.md b/pkgs/stream_channel/CHANGELOG.md index a5a7e46..6d86e48 100644 --- a/pkgs/stream_channel/CHANGELOG.md +++ b/pkgs/stream_channel/CHANGELOG.md
@@ -1,3 +1,11 @@ +## 1.4.0 + +* Add `StreamChannel.cast()`, which soundly coerces the generic type of a + channel. + +* Add `StreamChannelTransformer.typed()`, which soundly coerces the generic type + of a transformer. + ## 1.3.2 * Fix all strong-mode errors and warnings.
diff --git a/pkgs/stream_channel/lib/src/stream_channel_transformer.dart b/pkgs/stream_channel/lib/src/stream_channel_transformer.dart index ac98085..ca09ea1 100644 --- a/pkgs/stream_channel/lib/src/stream_channel_transformer.dart +++ b/pkgs/stream_channel/lib/src/stream_channel_transformer.dart
@@ -8,6 +8,7 @@ import 'package:async/async.dart'; import '../stream_channel.dart'; +import 'transformer/typed.dart'; /// A [StreamChannelTransformer] transforms the events being passed to and /// emitted by a [StreamChannel]. @@ -24,6 +25,21 @@ /// The transformer to use on the channel's sink. final StreamSinkTransformer<S, T> _sinkTransformer; + /// Creates a wrapper that coerces the type of [transformer]. + /// + /// This soundly converts a [StreamChannelTransformer] to a + /// `StreamChannelTransformer<S, T>`, regardless of its original generic type, + /// by asserting that the events emitted by the transformed channel's stream + /// are instances of `T` whenever they're provided. If they're not, the stream + /// throws a [CastError]. This also means that calls to [StreamSink.add] on + /// the transformed channel's sink may throw a [CastError] if the argument + /// type doesn't match the reified type of the sink. + static StreamChannelTransformer/*<S, T>*/ typed/*<S, T>*/( + StreamChannelTransformer transformer) => + transformer is StreamChannelTransformer/*<S, T>*/ + ? transformer + : new TypeSafeStreamChannelTransformer(transformer); + /// Creates a [StreamChannelTransformer] from existing stream and sink /// transformers. const StreamChannelTransformer(
diff --git a/pkgs/stream_channel/lib/src/transformer/typed.dart b/pkgs/stream_channel/lib/src/transformer/typed.dart new file mode 100644 index 0000000..f35e01c --- /dev/null +++ b/pkgs/stream_channel/lib/src/transformer/typed.dart
@@ -0,0 +1,17 @@ +// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import '../../stream_channel.dart'; + +/// A wrapper that coerces the generic type of the channel returned by an inner +/// transformer to `S`. +class TypeSafeStreamChannelTransformer<S, T> + implements StreamChannelTransformer<S, T> { + final StreamChannelTransformer _inner; + + TypeSafeStreamChannelTransformer(this._inner); + + StreamChannel<S> bind(StreamChannel<T> channel) => + _inner.bind(channel).cast(); +}
diff --git a/pkgs/stream_channel/lib/stream_channel.dart b/pkgs/stream_channel/lib/stream_channel.dart index b89845d..3615d21 100644 --- a/pkgs/stream_channel/lib/stream_channel.dart +++ b/pkgs/stream_channel/lib/stream_channel.dart
@@ -109,6 +109,13 @@ /// Returns a copy of [this] with [sink] replaced by [change]'s return /// value. StreamChannel<T> changeSink(StreamSink<T> change(StreamSink<T> sink)); + + /// Returns a copy of [this] with the generic type coerced to [S]. + /// + /// If any events emitted by [stream] aren't of type [S], they're converted + /// into [CastError] events. Similarly, if any events are added to [sync] that + /// aren't of type [S], a [CastError] is thrown. + StreamChannel/*<S>*/ cast/*<S>*/(); } /// An implementation of [StreamChannel] that simply takes a stream and a sink @@ -145,4 +152,7 @@ StreamChannel<T> changeSink(StreamSink<T> change(StreamSink<T> sink)) => new StreamChannel(stream, change(sink)); + + StreamChannel/*<S>*/ cast/*<S>*/() => new StreamChannel( + DelegatingStream.typed(stream), DelegatingStreamSink.typed(sink)); }
diff --git a/pkgs/stream_channel/pubspec.yaml b/pkgs/stream_channel/pubspec.yaml index 3e87e2b..1c1df31 100644 --- a/pkgs/stream_channel/pubspec.yaml +++ b/pkgs/stream_channel/pubspec.yaml
@@ -1,5 +1,5 @@ name: stream_channel -version: 1.3.2 +version: 1.4.0 description: An abstraction for two-way communication channels. author: Dart Team <misc@dartlang.org> homepage: https://github.com/dart-lang/stream_channel