Skip to content

Commit

Permalink
Add type-coercion functions.
Browse files Browse the repository at this point in the history
These match (and are based on) the coercion functions in
dart-lang/async.

R=sigmund@google.com

Review URL: https://codereview.chromium.org//1966853003 .
  • Loading branch information
nex3 committed May 10, 2016
1 parent 17f8d20 commit b74a376
Show file tree
Hide file tree
Showing 6 changed files with 54 additions and 1 deletion.
2 changes: 2 additions & 0 deletions .analysis_options
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
analyzer:
strong-mode: true
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -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.
Expand Down
16 changes: 16 additions & 0 deletions lib/src/stream_channel_transformer.dart
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import 'dart:convert';
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].
Expand All @@ -24,6 +25,21 @@ class StreamChannelTransformer<S, T> {
/// 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(
Expand Down
17 changes: 17 additions & 0 deletions lib/src/transformer/typed.dart
Original file line number Diff line number Diff line change
@@ -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();
}
10 changes: 10 additions & 0 deletions lib/stream_channel.dart
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,13 @@ abstract class StreamChannel<T> {
/// 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
Expand Down Expand Up @@ -145,4 +152,7 @@ abstract class StreamChannelMixin<T> implements StreamChannel<T> {

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));
}
2 changes: 1 addition & 1 deletion pubspec.yaml
Original file line number Diff line number Diff line change
@@ -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
Expand Down

0 comments on commit b74a376

Please sign in to comment.