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 'package:collection/collection.dart';
8 :
9 : import '../utils.dart';
10 : import 'stream_subscription.dart';
11 : import '../delegate/event_sink.dart';
12 :
13 : class TypeSafeStream<T> extends Stream<T> {
14 : final Stream _stream;
15 :
16 0 : Future<T> get first async => (await _stream.first) as T;
17 0 : Future<T> get last async => (await _stream.last) as T;
18 0 : Future<T> get single async => (await _stream.single) as T;
19 :
20 0 : bool get isBroadcast => _stream.isBroadcast;
21 0 : Future<bool> get isEmpty => _stream.isEmpty;
22 0 : Future<int> get length => _stream.length;
23 :
24 0 : TypeSafeStream(this._stream);
25 :
26 : Stream<T> asBroadcastStream(
27 : {void onListen(StreamSubscription<T> subscription),
28 : void onCancel(StreamSubscription<T> subscription)}) {
29 0 : return new TypeSafeStream<T>(_stream.asBroadcastStream(
30 : onListen: onListen == null
31 : ? null
32 : : (subscription) =>
33 0 : onListen(new TypeSafeStreamSubscription<T>(subscription)),
34 : onCancel: onCancel == null
35 : ? null
36 : : (subscription) =>
37 0 : onCancel(new TypeSafeStreamSubscription<T>(subscription))));
38 : }
39 :
40 : Stream<E> asyncExpand<E>(Stream<E> convert(T event)) =>
41 0 : _stream.asyncExpand(_validateType(convert));
42 :
43 : Stream<E> asyncMap<E>(convert(T event)) =>
44 0 : _stream.asyncMap(_validateType(convert));
45 :
46 : Stream<T> distinct([bool equals(T previous, T next)]) =>
47 0 : new TypeSafeStream<T>(_stream.distinct(equals == null
48 : ? null
49 0 : : (previous, next) => equals(previous as T, next as T)));
50 :
51 0 : Future<E> drain<E>([E futureValue]) => _stream.drain(futureValue);
52 :
53 : Stream<S> expand<S>(Iterable<S> convert(T value)) =>
54 0 : _stream.expand(_validateType(convert));
55 :
56 : Future firstWhere(bool test(T element), {Object defaultValue()}) =>
57 0 : _stream.firstWhere(_validateType(test), defaultValue: defaultValue);
58 :
59 : Future lastWhere(bool test(T element), {Object defaultValue()}) =>
60 0 : _stream.lastWhere(_validateType(test), defaultValue: defaultValue);
61 :
62 : Future<T> singleWhere(bool test(T element)) async =>
63 0 : (await _stream.singleWhere(_validateType(test))) as T;
64 :
65 : Future<S> fold<S>(S initialValue, S combine(S previous, T element)) =>
66 0 : _stream.fold(
67 0 : initialValue, (previous, element) => combine(previous, element as T));
68 :
69 : Future forEach(void action(T element)) =>
70 0 : _stream.forEach(_validateType(action));
71 :
72 : Stream<T> handleError(Function onError, {bool test(error)}) =>
73 0 : new TypeSafeStream<T>(_stream.handleError(onError, test: test));
74 :
75 : StreamSubscription<T> listen(void onData(T value),
76 : {Function onError, void onDone(), bool cancelOnError}) =>
77 0 : new TypeSafeStreamSubscription<T>(_stream.listen(_validateType(onData),
78 : onError: onError, onDone: onDone, cancelOnError: cancelOnError));
79 :
80 0 : Stream<S> map<S>(S convert(T event)) => _stream.map(_validateType(convert));
81 :
82 : // Don't forward to `_stream.pipe` because we want the consumer to see the
83 : // type-asserted stream.
84 : Future pipe(StreamConsumer<T> consumer) =>
85 0 : consumer.addStream(this).then((_) => consumer.close());
86 :
87 : Future<T> reduce(T combine(T previous, T element)) async {
88 0 : var result = await _stream
89 0 : .reduce((previous, element) => combine(previous as T, element as T));
90 0 : return result as T;
91 0 : }
92 :
93 : Stream<T> skipWhile(bool test(T element)) =>
94 0 : new TypeSafeStream<T>(_stream.skipWhile(_validateType(test)));
95 :
96 : Stream<T> takeWhile(bool test(T element)) =>
97 0 : new TypeSafeStream<T>(_stream.takeWhile(_validateType(test)));
98 :
99 : Stream<T> timeout(Duration timeLimit, {void onTimeout(EventSink<T> sink)}) =>
100 0 : new TypeSafeStream<T>(_stream.timeout(timeLimit,
101 0 : onTimeout: (sink) => onTimeout(DelegatingEventSink.typed(sink))));
102 :
103 : Future<List<T>> toList() async =>
104 0 : DelegatingList.typed<T>(await _stream.toList());
105 :
106 0 : Future<Set<T>> toSet() async => DelegatingSet.typed<T>(await _stream.toSet());
107 :
108 : // Don't forward to `_stream.transform` because we want the transformer to see
109 : // the type-asserted stream.
110 : Stream<S> transform<S>(StreamTransformer<T, S> transformer) =>
111 0 : transformer.bind(this);
112 :
113 : Stream<T> where(bool test(T element)) =>
114 0 : new TypeSafeStream<T>(_stream.where(_validateType(test)));
115 :
116 : Future<bool> every(bool test(T element)) =>
117 0 : _stream.every(_validateType(test));
118 :
119 0 : Future<bool> any(bool test(T element)) => _stream.any(_validateType(test));
120 0 : Stream<T> skip(int count) => new TypeSafeStream<T>(_stream.skip(count));
121 0 : Stream<T> take(int count) => new TypeSafeStream<T>(_stream.take(count));
122 0 : Future<T> elementAt(int index) async => (await _stream.elementAt(index)) as T;
123 0 : Future<bool> contains(Object needle) => _stream.contains(needle);
124 0 : Future<String> join([String separator = ""]) => _stream.join(separator);
125 0 : String toString() => _stream.toString();
126 :
127 : /// Returns a version of [function] that asserts that its argument is an
128 : /// instance of `T`.
129 : UnaryFunction<dynamic, S> _validateType<S>(S function(T value)) =>
130 0 : function == null ? null : (value) => function(value as T);
131 : }
|