Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(29)

Side by Side Diff: test/generated_sdk/lib/async/stream.dart

Issue 1162723007: remove generated_sdk from checked in code (Closed) Base URL: git@github.com:dart-lang/dev_compiler.git@master
Patch Set: Created 5 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright (c) 2013, 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 part of dart.async;
6
7 // -------------------------------------------------------------------
8 // Core Stream types
9 // -------------------------------------------------------------------
10
11 /**
12 * A source of asynchronous data events.
13 *
14 * A Stream provides a way to receive a sequence of events.
15 * Each event is either a data event or an error event,
16 * representing the result of a single computation.
17 * When the events provided by a Stream have all been sent,
18 * a single "done" event will mark the end.
19 *
20 * You can [listen] on a stream to make it start generating events,
21 * and to set up listeners that receive the events.
22 * When you listen, you receive a [StreamSubscription] object
23 * which is the active object providing the events,
24 * and which can be used to stop listening again,
25 * or to temporarily pause events from the subscription.
26 *
27 * There are two kinds of streams: "Single-subscription" streams and
28 * "broadcast" streams.
29 *
30 * *A single-subscription stream* allows only a single listener during the whole
31 * lifetime of the stream.
32 * It doesn't start generating events until it has a listener,
33 * and it stops sending events when the listener is unsubscribed,
34 * even if the source of events could still provide more.
35 *
36 * Listening twice on a single-subscription stream is not allowed, even after
37 * the first subscription has been canceled.
38 *
39 * Single-subscription streams are generally used for streaming chunks of
40 * larger contiguous data like file I/O.
41 *
42 * *A broadcast stream* allows any number of listeners, and it fires
43 * its events when they are ready, whether there are listeners or not.
44 *
45 * Broadcast streams are used for independent events/observers.
46 *
47 * If several listeners want to listen to a single subscription stream,
48 * use [asBroadcastStream] to create a broadcast stream on top of the
49 * non-broadcast stream.
50 *
51 * On either kind of stream, stream transformationss, such as [where] and
52 * [skip], return the same type of stream as the one the method was called on,
53 * unless otherwise noted.
54 *
55 * When an event is fired, the listener(s) at that time will receive the event.
56 * If a listener is added to a broadcast stream while an event is being fired,
57 * that listener will not receive the event currently being fired.
58 * If a listener is canceled, it immediately stops receiving events.
59 *
60 * When the "done" event is fired, subscribers are unsubscribed before
61 * receiving the event. After the event has been sent, the stream has no
62 * subscribers. Adding new subscribers to a broadcast stream after this point
63 * is allowed, but they will just receive a new "done" event as soon
64 * as possible.
65 *
66 * Stream subscriptions always respect "pause" requests. If necessary they need
67 * to buffer their input, but often, and preferably, they can simply request
68 * their input to pause too.
69 *
70 * The default implementation of [isBroadcast] returns false.
71 * A broadcast stream inheriting from [Stream] must override [isBroadcast]
72 * to return `true`.
73 */
74 abstract class Stream<T> {
75 Stream();
76
77 /**
78 * Creates a new single-subscription stream from the future.
79 *
80 * When the future completes, the stream will fire one event, either
81 * data or error, and then close with a done-event.
82 */
83 factory Stream.fromFuture(Future<T> future) {
84 // Use the controller's buffering to fill in the value even before
85 // the stream has a listener. For a single value, it's not worth it
86 // to wait for a listener before doing the `then` on the future.
87 _StreamController<T> controller =
88 new StreamController<T>(sync: true) as _StreamController<T>;
89 future.then((value) {
90 controller._add(value);
91 controller._closeUnchecked();
92 },
93 onError: (error, stackTrace) {
94 controller._addError(error, stackTrace);
95 controller._closeUnchecked();
96 });
97 return controller.stream;
98 }
99
100 /**
101 * Creates a single-subscription stream that gets its data from [data].
102 *
103 * The iterable is iterated when the stream receives a listener, and stops
104 * iterating if the listener cancels the subscription.
105 *
106 * If iterating [data] throws an error, the stream ends immediately with
107 * that error. No done event will be sent (iteration is not complete), but no
108 * further data events will be generated either, since iteration cannot
109 * continue.
110 */
111 factory Stream.fromIterable(Iterable<T> data) {
112 return new _GeneratedStreamImpl<T>(
113 () => new _IterablePendingEvents<T>(data));
114 }
115
116 /**
117 * Creates a stream that repeatedly emits events at [period] intervals.
118 *
119 * The event values are computed by invoking [computation]. The argument to
120 * this callback is an integer that starts with 0 and is incremented for
121 * every event.
122 *
123 * If [computation] is omitted the event values will all be `null`.
124 */
125 factory Stream.periodic(Duration period,
126 [T computation(int computationCount)]) {
127 if (computation == null) computation = ((i) => null);
128
129 Timer timer;
130 int computationCount = 0;
131 StreamController<T> controller;
132 // Counts the time that the Stream was running (and not paused).
133 Stopwatch watch = new Stopwatch();
134
135 void sendEvent() {
136 watch.reset();
137 T data = computation(computationCount++);
138 controller.add(data);
139 }
140
141 void startPeriodicTimer() {
142 assert(timer == null);
143 timer = new Timer.periodic(period, (Timer timer) {
144 sendEvent();
145 });
146 }
147
148 controller = new StreamController<T>(sync: true,
149 onListen: () {
150 watch.start();
151 startPeriodicTimer();
152 },
153 onPause: () {
154 timer.cancel();
155 timer = null;
156 watch.stop();
157 },
158 onResume: () {
159 assert(timer == null);
160 Duration elapsed = watch.elapsed;
161 watch.start();
162 timer = new Timer(period - elapsed, () {
163 timer = null;
164 startPeriodicTimer();
165 sendEvent();
166 });
167 },
168 onCancel: () {
169 if (timer != null) timer.cancel();
170 timer = null;
171 });
172 return controller.stream;
173 }
174
175 /**
176 * Creates a stream where all events of an existing stream are piped through
177 * a sink-transformation.
178 *
179 * The given [mapSink] closure is invoked when the returned stream is
180 * listened to. All events from the [source] are added into the event sink
181 * that is returned from the invocation. The transformation puts all
182 * transformed events into the sink the [mapSink] closure received during
183 * its invocation. Conceptually the [mapSink] creates a transformation pipe
184 * with the input sink being the returned [EventSink] and the output sink
185 * being the sink it received.
186 *
187 * This constructor is frequently used to build transformers.
188 *
189 * Example use for a duplicating transformer:
190 *
191 * class DuplicationSink implements EventSink<String> {
192 * final EventSink<String> _outputSink;
193 * DuplicationSink(this._outputSink);
194 *
195 * void add(String data) {
196 * _outputSink.add(data);
197 * _outputSink.add(data);
198 * }
199 *
200 * void addError(e, [st]) => _outputSink(e, st);
201 * void close() => _outputSink.close();
202 * }
203 *
204 * class DuplicationTransformer implements StreamTransformer<String, Strin g> {
205 * // Some generic types ommitted for brevety.
206 * Stream bind(Stream stream) => new Stream<String>.eventTransform(
207 * stream,
208 * (EventSink sink) => new DuplicationSink(sink));
209 * }
210 *
211 * stringStream.transform(new DuplicationTransformer());
212 *
213 * The resulting stream is a broadcast stream if [source] is.
214 */
215 factory Stream.eventTransformed(Stream source,
216 EventSink mapSink(EventSink<T> sink)) {
217 return new _BoundSinkStream(source, mapSink);
218 }
219
220 /**
221 * Reports whether this stream is a broadcast stream.
222 */
223 bool get isBroadcast => false;
224
225 /**
226 * Returns a multi-subscription stream that produces the same events as this.
227 *
228 * The returned stream will subscribe to this stream when its first
229 * subscriber is added, and will stay subscribed until this stream ends,
230 * or a callback cancels the subscription.
231 *
232 * If [onListen] is provided, it is called with a subscription-like object
233 * that represents the underlying subscription to this stream. It is
234 * possible to pause, resume or cancel the subscription during the call
235 * to [onListen]. It is not possible to change the event handlers, including
236 * using [StreamSubscription.asFuture].
237 *
238 * If [onCancel] is provided, it is called in a similar way to [onListen]
239 * when the returned stream stops having listener. If it later gets
240 * a new listener, the [onListen] function is called again.
241 *
242 * Use the callbacks, for example, for pausing the underlying subscription
243 * while having no subscribers to prevent losing events, or canceling the
244 * subscription when there are no listeners.
245 */
246 Stream<T> asBroadcastStream({
247 void onListen(StreamSubscription<T> subscription),
248 void onCancel(StreamSubscription<T> subscription) }) {
249 return new _AsBroadcastStream<T>(this, onListen, onCancel);
250 }
251
252 /**
253 * Adds a subscription to this stream.
254 *
255 * On each data event from this stream, the subscriber's [onData] handler
256 * is called. If [onData] is null, nothing happens.
257 *
258 * On errors from this stream, the [onError] handler is given a
259 * object describing the error.
260 *
261 * The [onError] callback must be of type `void onError(error)` or
262 * `void onError(error, StackTrace stackTrace)`. If [onError] accepts
263 * two arguments it is called with the stack trace (which could be `null` if
264 * the stream itself received an error without stack trace).
265 * Otherwise it is called with just the error object.
266 *
267 * If this stream closes, the [onDone] handler is called.
268 *
269 * If [cancelOnError] is true, the subscription is ended when
270 * the first error is reported. The default is false.
271 */
272 StreamSubscription<T> listen(void onData(T event),
273 { Function onError,
274 void onDone(),
275 bool cancelOnError});
276
277 /**
278 * Creates a new stream from this stream that discards some data events.
279 *
280 * The new stream sends the same error and done events as this stream,
281 * but it only sends the data events that satisfy the [test].
282 *
283 * The returned stream is a broadcast stream if this stream is.
284 * If a broadcast stream is listened to more than once, each subscription
285 * will individually perform the `test`.
286 */
287 Stream<T> where(bool test(T event)) {
288 return new _WhereStream<T>(this, test);
289 }
290
291 /**
292 * Creates a new stream that converts each element of this stream
293 * to a new value using the [convert] function.
294 *
295 * The returned stream is a broadcast stream if this stream is.
296 * If a broadcast stream is listened to more than once, each subscription
297 * will individually execute `map` for each event.
298 */
299 Stream map(convert(T event)) {
300 return new _MapStream<T, dynamic>(this, convert);
301 }
302
303 /**
304 * Creates a new stream with each data event of this stream asynchronously
305 * mapped to a new event.
306 *
307 * This acts like [map], except that [convert] may return a [Future],
308 * and in that case, the stream waits for that future to complete before
309 * continuing with its result.
310 *
311 * The returned stream is a broadcast stream if this stream is.
312 */
313 Stream asyncMap(convert(T event)) {
314 StreamController controller;
315 StreamSubscription subscription;
316 void onListen () {
317 final add = controller.add;
318 assert(controller is _StreamController ||
319 controller is _BroadcastStreamController);
320 final eventSink = controller;
321 final addError = eventSink._addError;
322 subscription = this.listen(
323 (T event) {
324 var newValue;
325 try {
326 newValue = convert(event);
327 } catch (e, s) {
328 controller.addError(e, s);
329 return;
330 }
331 if (newValue is Future) {
332 subscription.pause();
333 newValue.then(add, onError: addError)
334 .whenComplete(subscription.resume);
335 } else {
336 controller.add(newValue);
337 }
338 },
339 onError: addError,
340 onDone: controller.close
341 );
342 }
343 if (this.isBroadcast) {
344 controller = new StreamController.broadcast(
345 onListen: onListen,
346 onCancel: () { subscription.cancel(); },
347 sync: true
348 );
349 } else {
350 controller = new StreamController(
351 onListen: onListen,
352 onPause: () { subscription.pause(); },
353 onResume: () { subscription.resume(); },
354 onCancel: () { subscription.cancel(); },
355 sync: true
356 );
357 }
358 return controller.stream;
359 }
360
361 /**
362 * Creates a new stream with the events of a stream per original event.
363 *
364 * This acts like [expand], except that [convert] returns a [Stream]
365 * instead of an [Iterable].
366 * The events of the returned stream becomes the events of the returned
367 * stream, in the order they are produced.
368 *
369 * If [convert] returns `null`, no value is put on the output stream,
370 * just as if it returned an empty stream.
371 *
372 * The returned stream is a broadcast stream if this stream is.
373 */
374 Stream asyncExpand(Stream convert(T event)) {
375 StreamController controller;
376 StreamSubscription subscription;
377 void onListen() {
378 assert(controller is _StreamController ||
379 controller is _BroadcastStreamController);
380 final eventSink = controller;
381 subscription = this.listen(
382 (T event) {
383 Stream newStream;
384 try {
385 newStream = convert(event);
386 } catch (e, s) {
387 controller.addError(e, s);
388 return;
389 }
390 if (newStream != null) {
391 subscription.pause();
392 controller.addStream(newStream)
393 .whenComplete(subscription.resume);
394 }
395 },
396 onError: eventSink._addError, // Avoid Zone error replacement.
397 onDone: controller.close
398 );
399 }
400 if (this.isBroadcast) {
401 controller = new StreamController.broadcast(
402 onListen: onListen,
403 onCancel: () { subscription.cancel(); },
404 sync: true
405 );
406 } else {
407 controller = new StreamController(
408 onListen: onListen,
409 onPause: () { subscription.pause(); },
410 onResume: () { subscription.resume(); },
411 onCancel: () { subscription.cancel(); },
412 sync: true
413 );
414 }
415 return controller.stream;
416 }
417
418 /**
419 * Creates a wrapper Stream that intercepts some errors from this stream.
420 *
421 * If this stream sends an error that matches [test], then it is intercepted
422 * by the [handle] function.
423 *
424 * The [onError] callback must be of type `void onError(error)` or
425 * `void onError(error, StackTrace stackTrace)`. Depending on the function
426 * type the the stream either invokes [onError] with or without a stack
427 * trace. The stack trace argument might be `null` if the stream itself
428 * received an error without stack trace.
429 *
430 * An asynchronous error [:e:] is matched by a test function if [:test(e):]
431 * returns true. If [test] is omitted, every error is considered matching.
432 *
433 * If the error is intercepted, the [handle] function can decide what to do
434 * with it. It can throw if it wants to raise a new (or the same) error,
435 * or simply return to make the stream forget the error.
436 *
437 * If you need to transform an error into a data event, use the more generic
438 * [Stream.transform] to handle the event by writing a data event to
439 * the output sink.
440 *
441 * The returned stream is a broadcast stream if this stream is.
442 * If a broadcast stream is listened to more than once, each subscription
443 * will individually perform the `test` and handle the error.
444 */
445 Stream<T> handleError(Function onError, { bool test(error) }) {
446 return new _HandleErrorStream<T>(this, onError, test);
447 }
448
449 /**
450 * Creates a new stream from this stream that converts each element
451 * into zero or more events.
452 *
453 * Each incoming event is converted to an [Iterable] of new events,
454 * and each of these new events are then sent by the returned stream
455 * in order.
456 *
457 * The returned stream is a broadcast stream if this stream is.
458 * If a broadcast stream is listened to more than once, each subscription
459 * will individually call `convert` and expand the events.
460 */
461 Stream expand(Iterable convert(T value)) {
462 return new _ExpandStream<T, dynamic>(this, convert);
463 }
464
465 /**
466 * Binds this stream as the input of the provided [StreamConsumer].
467 *
468 * The `streamConsumer` is closed when the stream has been added to it.
469 *
470 * Returns a future which completes when the stream has been consumed
471 * and the consumer has been closed.
472 */
473 Future pipe(StreamConsumer<T> streamConsumer) {
474 return streamConsumer.addStream(this).then((_) => streamConsumer.close());
475 }
476
477 /**
478 * Chains this stream as the input of the provided [StreamTransformer].
479 *
480 * Returns the result of [:streamTransformer.bind:] itself.
481 *
482 * The `streamTransformer` can decide whether it wants to return a
483 * broadcast stream or not.
484 */
485 Stream transform(StreamTransformer<T, dynamic> streamTransformer) {
486 return streamTransformer.bind(this);
487 }
488
489 /**
490 * Reduces a sequence of values by repeatedly applying [combine].
491 */
492 Future<T> reduce(T combine(T previous, T element)) {
493 _Future<T> result = new _Future<T>();
494 bool seenFirst = false;
495 T value;
496 StreamSubscription subscription;
497 subscription = this.listen(
498 (T element) {
499 if (seenFirst) {
500 _runUserCode(() => combine(value, element),
501 (T newValue) { value = newValue; },
502 _cancelAndErrorClosure(subscription, result));
503 } else {
504 value = element;
505 seenFirst = true;
506 }
507 },
508 onError: result._completeError,
509 onDone: () {
510 if (!seenFirst) {
511 try {
512 throw IterableElementError.noElement();
513 } catch (e, s) {
514 _completeWithErrorCallback(result, e, s);
515 }
516 } else {
517 result._complete(value);
518 }
519 },
520 cancelOnError: true
521 );
522 return result;
523 }
524
525 /** Reduces a sequence of values by repeatedly applying [combine]. */
526 Future fold(var initialValue, combine(var previous, T element)) {
527 _Future result = new _Future();
528 var value = initialValue;
529 StreamSubscription subscription;
530 subscription = this.listen(
531 (T element) {
532 _runUserCode(
533 () => combine(value, element),
534 (newValue) { value = newValue; },
535 _cancelAndErrorClosure(subscription, result)
536 );
537 },
538 onError: (e, st) {
539 result._completeError(e, st);
540 },
541 onDone: () {
542 result._complete(value);
543 },
544 cancelOnError: true);
545 return result;
546 }
547
548 /**
549 * Collects string of data events' string representations.
550 *
551 * If [separator] is provided, it is inserted between any two
552 * elements.
553 *
554 * Any error in the stream causes the future to complete with that
555 * error. Otherwise it completes with the collected string when
556 * the "done" event arrives.
557 */
558 Future<String> join([String separator = ""]) {
559 _Future<String> result = new _Future<String>();
560 StringBuffer buffer = new StringBuffer();
561 StreamSubscription subscription;
562 bool first = true;
563 subscription = this.listen(
564 (T element) {
565 if (!first) {
566 buffer.write(separator);
567 }
568 first = false;
569 try {
570 buffer.write(element);
571 } catch (e, s) {
572 _cancelAndErrorWithReplacement(subscription, result, e, s);
573 }
574 },
575 onError: (e) {
576 result._completeError(e);
577 },
578 onDone: () {
579 result._complete(buffer.toString());
580 },
581 cancelOnError: true);
582 return result;
583 }
584
585 /**
586 * Checks whether [needle] occurs in the elements provided by this stream.
587 *
588 * Completes the [Future] when the answer is known.
589 * If this stream reports an error, the [Future] will report that error.
590 */
591 Future<bool> contains(Object needle) {
592 _Future<bool> future = new _Future<bool>();
593 StreamSubscription subscription;
594 subscription = this.listen(
595 (T element) {
596 _runUserCode(
597 () => (element == needle),
598 (bool isMatch) {
599 if (isMatch) {
600 _cancelAndValue(subscription, future, true);
601 }
602 },
603 _cancelAndErrorClosure(subscription, future)
604 );
605 },
606 onError: future._completeError,
607 onDone: () {
608 future._complete(false);
609 },
610 cancelOnError: true);
611 return future;
612 }
613
614 /**
615 * Executes [action] on each data event of the stream.
616 *
617 * Completes the returned [Future] when all events of the stream
618 * have been processed. Completes the future with an error if the
619 * stream has an error event, or if [action] throws.
620 */
621 Future forEach(void action(T element)) {
622 _Future future = new _Future();
623 StreamSubscription subscription;
624 subscription = this.listen(
625 (T element) {
626 _runUserCode(
627 () => action(element),
628 (_) {},
629 _cancelAndErrorClosure(subscription, future)
630 );
631 },
632 onError: future._completeError,
633 onDone: () {
634 future._complete(null);
635 },
636 cancelOnError: true);
637 return future;
638 }
639
640 /**
641 * Checks whether [test] accepts all elements provided by this stream.
642 *
643 * Completes the [Future] when the answer is known.
644 * If this stream reports an error, the [Future] will report that error.
645 */
646 Future<bool> every(bool test(T element)) {
647 _Future<bool> future = new _Future<bool>();
648 StreamSubscription subscription;
649 subscription = this.listen(
650 (T element) {
651 _runUserCode(
652 () => test(element),
653 (bool isMatch) {
654 if (!isMatch) {
655 _cancelAndValue(subscription, future, false);
656 }
657 },
658 _cancelAndErrorClosure(subscription, future)
659 );
660 },
661 onError: future._completeError,
662 onDone: () {
663 future._complete(true);
664 },
665 cancelOnError: true);
666 return future;
667 }
668
669 /**
670 * Checks whether [test] accepts any element provided by this stream.
671 *
672 * Completes the [Future] when the answer is known.
673 *
674 * If this stream reports an error, the [Future] reports that error.
675 *
676 * Stops listening to the stream after the first matching element has been
677 * found.
678 *
679 * Internally the method cancels its subscription after this element. This
680 * means that single-subscription (non-broadcast) streams are closed and
681 * cannot be reused after a call to this method.
682 */
683 Future<bool> any(bool test(T element)) {
684 _Future<bool> future = new _Future<bool>();
685 StreamSubscription subscription;
686 subscription = this.listen(
687 (T element) {
688 _runUserCode(
689 () => test(element),
690 (bool isMatch) {
691 if (isMatch) {
692 _cancelAndValue(subscription, future, true);
693 }
694 },
695 _cancelAndErrorClosure(subscription, future)
696 );
697 },
698 onError: future._completeError,
699 onDone: () {
700 future._complete(false);
701 },
702 cancelOnError: true);
703 return future;
704 }
705
706
707 /** Counts the elements in the stream. */
708 Future<int> get length {
709 _Future<int> future = new _Future<int>();
710 int count = 0;
711 this.listen(
712 (_) { count++; },
713 onError: future._completeError,
714 onDone: () {
715 future._complete(count);
716 },
717 cancelOnError: true);
718 return future;
719 }
720
721 /**
722 * Reports whether this stream contains any elements.
723 *
724 * Stops listening to the stream after the first element has been received.
725 *
726 * Internally the method cancels its subscription after the first element.
727 * This means that single-subscription (non-broadcast) streams are closed and
728 * cannot be reused after a call to this getter.
729 */
730 Future<bool> get isEmpty {
731 _Future<bool> future = new _Future<bool>();
732 StreamSubscription subscription;
733 subscription = this.listen(
734 (_) {
735 _cancelAndValue(subscription, future, false);
736 },
737 onError: future._completeError,
738 onDone: () {
739 future._complete(true);
740 },
741 cancelOnError: true);
742 return future;
743 }
744
745 /** Collects the data of this stream in a [List]. */
746 Future<List<T>> toList() {
747 List<T> result = <T>[];
748 _Future<List<T>> future = new _Future<List<T>>();
749 this.listen(
750 (T data) {
751 result.add(data);
752 },
753 onError: future._completeError,
754 onDone: () {
755 future._complete(result);
756 },
757 cancelOnError: true);
758 return future;
759 }
760
761 /**
762 * Collects the data of this stream in a [Set].
763 *
764 * The returned set is the same type as returned by `new Set<T>()`.
765 * If another type of set is needed, either use [forEach] to add each
766 * element to the set, or use
767 * `toList().then((list) => new SomeOtherSet.from(list))`
768 * to create the set.
769 */
770 Future<Set<T>> toSet() {
771 Set<T> result = new Set<T>();
772 _Future<Set<T>> future = new _Future<Set<T>>();
773 this.listen(
774 (T data) {
775 result.add(data);
776 },
777 onError: future._completeError,
778 onDone: () {
779 future._complete(result);
780 },
781 cancelOnError: true);
782 return future;
783 }
784
785 /**
786 * Discards all data on the stream, but signals when it's done or an error
787 * occured.
788 *
789 * When subscribing using [drain], cancelOnError will be true. This means
790 * that the future will complete with the first error on the stream and then
791 * cancel the subscription.
792 *
793 * In case of a `done` event the future completes with the given
794 * [futureValue].
795 */
796 Future drain([var futureValue]) => listen(null, cancelOnError: true)
797 .asFuture(futureValue);
798
799 /**
800 * Provides at most the first [n] values of this stream.
801 *
802 * Forwards the first [n] data events of this stream, and all error
803 * events, to the returned stream, and ends with a done event.
804 *
805 * If this stream produces fewer than [count] values before it's done,
806 * so will the returned stream.
807 *
808 * Stops listening to the stream after the first [n] elements have been
809 * received.
810 *
811 * Internally the method cancels its subscription after these elements. This
812 * means that single-subscription (non-broadcast) streams are closed and
813 * cannot be reused after a call to this method.
814 *
815 * The returned stream is a broadcast stream if this stream is.
816 * For a broadcast stream, the events are only counted from the time
817 * the returned stream is listened to.
818 */
819 Stream<T> take(int count) {
820 return new _TakeStream(this, count);
821 }
822
823 /**
824 * Forwards data events while [test] is successful.
825 *
826 * The returned stream provides the same events as this stream as long
827 * as [test] returns [:true:] for the event data. The stream is done
828 * when either this stream is done, or when this stream first provides
829 * a value that [test] doesn't accept.
830 *
831 * Stops listening to the stream after the accepted elements.
832 *
833 * Internally the method cancels its subscription after these elements. This
834 * means that single-subscription (non-broadcast) streams are closed and
835 * cannot be reused after a call to this method.
836 *
837 * The returned stream is a broadcast stream if this stream is.
838 * For a broadcast stream, the events are only tested from the time
839 * the returned stream is listened to.
840 */
841 Stream<T> takeWhile(bool test(T element)) {
842 return new _TakeWhileStream(this, test);
843 }
844
845 /**
846 * Skips the first [count] data events from this stream.
847 *
848 * The returned stream is a broadcast stream if this stream is.
849 * For a broadcast stream, the events are only counted from the time
850 * the returned stream is listened to.
851 */
852 Stream<T> skip(int count) {
853 return new _SkipStream(this, count);
854 }
855
856 /**
857 * Skip data events from this stream while they are matched by [test].
858 *
859 * Error and done events are provided by the returned stream unmodified.
860 *
861 * Starting with the first data event where [test] returns false for the
862 * event data, the returned stream will have the same events as this stream.
863 *
864 * The returned stream is a broadcast stream if this stream is.
865 * For a broadcast stream, the events are only tested from the time
866 * the returned stream is listened to.
867 */
868 Stream<T> skipWhile(bool test(T element)) {
869 return new _SkipWhileStream(this, test);
870 }
871
872 /**
873 * Skips data events if they are equal to the previous data event.
874 *
875 * The returned stream provides the same events as this stream, except
876 * that it never provides two consequtive data events that are equal.
877 *
878 * Equality is determined by the provided [equals] method. If that is
879 * omitted, the '==' operator on the last provided data element is used.
880 *
881 * The returned stream is a broadcast stream if this stream is.
882 * If a broadcast stream is listened to more than once, each subscription
883 * will individually perform the `equals` test.
884 */
885 Stream<T> distinct([bool equals(T previous, T next)]) {
886 return new _DistinctStream(this, equals);
887 }
888
889 /**
890 * Returns the first element of the stream.
891 *
892 * Stops listening to the stream after the first element has been received.
893 *
894 * Internally the method cancels its subscription after the first element.
895 * This means that single-subscription (non-broadcast) streams are closed
896 * and cannot be reused after a call to this getter.
897 *
898 * If an error event occurs before the first data event, the resulting future
899 * is completed with that error.
900 *
901 * If this stream is empty (a done event occurs before the first data event),
902 * the resulting future completes with a [StateError].
903 *
904 * Except for the type of the error, this method is equivalent to
905 * [:this.elementAt(0):].
906 */
907 Future<T> get first {
908 _Future<T> future = new _Future<T>();
909 StreamSubscription subscription;
910 subscription = this.listen(
911 (T value) {
912 _cancelAndValue(subscription, future, value);
913 },
914 onError: future._completeError,
915 onDone: () {
916 try {
917 throw IterableElementError.noElement();
918 } catch (e, s) {
919 _completeWithErrorCallback(future, e, s);
920 }
921 },
922 cancelOnError: true);
923 return future;
924 }
925
926 /**
927 * Returns the last element of the stream.
928 *
929 * If an error event occurs before the first data event, the resulting future
930 * is completed with that error.
931 *
932 * If this stream is empty (a done event occurs before the first data event),
933 * the resulting future completes with a [StateError].
934 */
935 Future<T> get last {
936 _Future<T> future = new _Future<T>();
937 T result = null;
938 bool foundResult = false;
939 StreamSubscription subscription;
940 subscription = this.listen(
941 (T value) {
942 foundResult = true;
943 result = value;
944 },
945 onError: future._completeError,
946 onDone: () {
947 if (foundResult) {
948 future._complete(result);
949 return;
950 }
951 try {
952 throw IterableElementError.noElement();
953 } catch (e, s) {
954 _completeWithErrorCallback(future, e, s);
955 }
956 },
957 cancelOnError: true);
958 return future;
959 }
960
961 /**
962 * Returns the single element.
963 *
964 * If an error event occurs before or after the first data event, the
965 * resulting future is completed with that error.
966 *
967 * If [this] is empty or has more than one element throws a [StateError].
968 */
969 Future<T> get single {
970 _Future<T> future = new _Future<T>();
971 T result = null;
972 bool foundResult = false;
973 StreamSubscription subscription;
974 subscription = this.listen(
975 (T value) {
976 if (foundResult) {
977 // This is the second element we get.
978 try {
979 throw IterableElementError.tooMany();
980 } catch (e, s) {
981 _cancelAndErrorWithReplacement(subscription, future, e, s);
982 }
983 return;
984 }
985 foundResult = true;
986 result = value;
987 },
988 onError: future._completeError,
989 onDone: () {
990 if (foundResult) {
991 future._complete(result);
992 return;
993 }
994 try {
995 throw IterableElementError.noElement();
996 } catch (e, s) {
997 _completeWithErrorCallback(future, e, s);
998 }
999 },
1000 cancelOnError: true);
1001 return future;
1002 }
1003
1004 /**
1005 * Finds the first element of this stream matching [test].
1006 *
1007 * Returns a future that is filled with the first element of this stream
1008 * that [test] returns true for.
1009 *
1010 * If no such element is found before this stream is done, and a
1011 * [defaultValue] function is provided, the result of calling [defaultValue]
1012 * becomes the value of the future.
1013 *
1014 * Stops listening to the stream after the first matching element has been
1015 * received.
1016 *
1017 * Internally the method cancels its subscription after the first element that
1018 * matches the predicate. This means that single-subscription (non-broadcast)
1019 * streams are closed and cannot be reused after a call to this method.
1020 *
1021 * If an error occurs, or if this stream ends without finding a match and
1022 * with no [defaultValue] function provided, the future will receive an
1023 * error.
1024 */
1025 Future<dynamic> firstWhere(bool test(T element), {Object defaultValue()}) {
1026 _Future<dynamic> future = new _Future();
1027 StreamSubscription subscription;
1028 subscription = this.listen(
1029 (T value) {
1030 _runUserCode(
1031 () => test(value),
1032 (bool isMatch) {
1033 if (isMatch) {
1034 _cancelAndValue(subscription, future, value);
1035 }
1036 },
1037 _cancelAndErrorClosure(subscription, future)
1038 );
1039 },
1040 onError: future._completeError,
1041 onDone: () {
1042 if (defaultValue != null) {
1043 _runUserCode(defaultValue, future._complete, future._completeError);
1044 return;
1045 }
1046 try {
1047 throw IterableElementError.noElement();
1048 } catch (e, s) {
1049 _completeWithErrorCallback(future, e, s);
1050 }
1051 },
1052 cancelOnError: true);
1053 return future;
1054 }
1055
1056 /**
1057 * Finds the last element in this stream matching [test].
1058 *
1059 * As [firstWhere], except that the last matching element is found.
1060 * That means that the result cannot be provided before this stream
1061 * is done.
1062 */
1063 Future<dynamic> lastWhere(bool test(T element), {Object defaultValue()}) {
1064 _Future<dynamic> future = new _Future();
1065 T result = null;
1066 bool foundResult = false;
1067 StreamSubscription subscription;
1068 subscription = this.listen(
1069 (T value) {
1070 _runUserCode(
1071 () => true == test(value),
1072 (bool isMatch) {
1073 if (isMatch) {
1074 foundResult = true;
1075 result = value;
1076 }
1077 },
1078 _cancelAndErrorClosure(subscription, future)
1079 );
1080 },
1081 onError: future._completeError,
1082 onDone: () {
1083 if (foundResult) {
1084 future._complete(result);
1085 return;
1086 }
1087 if (defaultValue != null) {
1088 _runUserCode(defaultValue, future._complete, future._completeError);
1089 return;
1090 }
1091 try {
1092 throw IterableElementError.noElement();
1093 } catch (e, s) {
1094 _completeWithErrorCallback(future, e, s);
1095 }
1096 },
1097 cancelOnError: true);
1098 return future;
1099 }
1100
1101 /**
1102 * Finds the single element in this stream matching [test].
1103 *
1104 * Like [lastMatch], except that it is an error if more than one
1105 * matching element occurs in the stream.
1106 */
1107 Future<T> singleWhere(bool test(T element)) {
1108 _Future<T> future = new _Future<T>();
1109 T result = null;
1110 bool foundResult = false;
1111 StreamSubscription subscription;
1112 subscription = this.listen(
1113 (T value) {
1114 _runUserCode(
1115 () => true == test(value),
1116 (bool isMatch) {
1117 if (isMatch) {
1118 if (foundResult) {
1119 try {
1120 throw IterableElementError.tooMany();
1121 } catch (e, s) {
1122 _cancelAndErrorWithReplacement(subscription, future, e, s);
1123 }
1124 return;
1125 }
1126 foundResult = true;
1127 result = value;
1128 }
1129 },
1130 _cancelAndErrorClosure(subscription, future)
1131 );
1132 },
1133 onError: future._completeError,
1134 onDone: () {
1135 if (foundResult) {
1136 future._complete(result);
1137 return;
1138 }
1139 try {
1140 throw IterableElementError.noElement();
1141 } catch (e, s) {
1142 _completeWithErrorCallback(future, e, s);
1143 }
1144 },
1145 cancelOnError: true);
1146 return future;
1147 }
1148
1149 /**
1150 * Returns the value of the [index]th data event of this stream.
1151 *
1152 * Stops listening to the stream after the [index]th data event has been
1153 * received.
1154 *
1155 * Internally the method cancels its subscription after these elements. This
1156 * means that single-subscription (non-broadcast) streams are closed and
1157 * cannot be reused after a call to this method.
1158 *
1159 * If an error event occurs before the value is found, the future completes
1160 * with this error.
1161 *
1162 * If a done event occurs before the value is found, the future completes
1163 * with a [RangeError].
1164 */
1165 Future<T> elementAt(int index) {
1166 if (index is! int || index < 0) throw new ArgumentError(index);
1167 _Future<T> future = new _Future<T>();
1168 StreamSubscription subscription;
1169 int elementIndex = 0;
1170 subscription = this.listen(
1171 (T value) {
1172 if (index == elementIndex) {
1173 _cancelAndValue(subscription, future, value);
1174 return;
1175 }
1176 elementIndex += 1;
1177 },
1178 onError: future._completeError,
1179 onDone: () {
1180 future._completeError(
1181 new RangeError.index(index, this, "index", null, elementIndex));
1182 },
1183 cancelOnError: true);
1184 return future;
1185 }
1186
1187 /**
1188 * Creates a new stream with the same events as this stream.
1189 *
1190 * Whenever more than [timeLimit] passes between two events from this stream,
1191 * the [onTimeout] function is called.
1192 *
1193 * The countdown doesn't start until the returned stream is listened to.
1194 * The countdown is reset every time an event is forwarded from this stream,
1195 * or when the stream is paused and resumed.
1196 *
1197 * The [onTimeout] function is called with one argument: an
1198 * [EventSink] that allows putting events into the returned stream.
1199 * This `EventSink` is only valid during the call to `onTimeout`.
1200 *
1201 * If `onTimeout` is omitted, a timeout will just put a [TimeoutException]
1202 * into the error channel of the returned stream.
1203 *
1204 * The returned stream is a broadcast stream if this stream is.
1205 * If a broadcast stream is listened to more than once, each subscription
1206 * will have its individually timer that starts counting on listen,
1207 * and the subscriptions' timers can be paused individually.
1208 */
1209 Stream timeout(Duration timeLimit, {void onTimeout(EventSink sink)}) {
1210 StreamController controller;
1211 // The following variables are set on listen.
1212 StreamSubscription<T> subscription;
1213 Timer timer;
1214 Zone zone;
1215 Function timeout;
1216
1217 void onData(T event) {
1218 timer.cancel();
1219 controller.add(event);
1220 timer = zone.createTimer(timeLimit, timeout);
1221 }
1222 void onError(error, StackTrace stackTrace) {
1223 timer.cancel();
1224 assert(controller is _StreamController ||
1225 controller is _BroadcastStreamController);
1226 var eventSink = controller;
1227 eventSink._addError(error, stackTrace); // Avoid Zone error replacement.
1228 timer = zone.createTimer(timeLimit, timeout);
1229 }
1230 void onDone() {
1231 timer.cancel();
1232 controller.close();
1233 }
1234 void onListen() {
1235 // This is the onListen callback for of controller.
1236 // It runs in the same zone that the subscription was created in.
1237 // Use that zone for creating timers and running the onTimeout
1238 // callback.
1239 zone = Zone.current;
1240 if (onTimeout == null) {
1241 timeout = () {
1242 controller.addError(new TimeoutException("No stream event",
1243 timeLimit), null);
1244 };
1245 } else {
1246 onTimeout = zone.registerUnaryCallback(onTimeout);
1247 _ControllerEventSinkWrapper wrapper =
1248 new _ControllerEventSinkWrapper(null);
1249 timeout = () {
1250 wrapper._sink = controller; // Only valid during call.
1251 zone.runUnaryGuarded(onTimeout, wrapper);
1252 wrapper._sink = null;
1253 };
1254 }
1255
1256 subscription = this.listen(onData, onError: onError, onDone: onDone);
1257 timer = zone.createTimer(timeLimit, timeout);
1258 }
1259 Future onCancel() {
1260 timer.cancel();
1261 Future result = subscription.cancel();
1262 subscription = null;
1263 return result;
1264 }
1265 controller = isBroadcast
1266 ? new _SyncBroadcastStreamController(onListen, onCancel)
1267 : new _SyncStreamController(
1268 onListen,
1269 () {
1270 // Don't null the timer, onCancel may call cancel again.
1271 timer.cancel();
1272 subscription.pause();
1273 },
1274 () {
1275 subscription.resume();
1276 timer = zone.createTimer(timeLimit, timeout);
1277 },
1278 onCancel);
1279 return controller.stream;
1280 }
1281 }
1282
1283 /**
1284 * A subscritption on events from a [Stream].
1285 *
1286 * When you listen on a [Stream] using [Stream.listen],
1287 * a [StreamSubscription] object is returned.
1288 *
1289 * The subscription provides events to the listener,
1290 * and holds the callbacks used to handle the events.
1291 * The subscription can also be used to unsubscribe from the events,
1292 * or to temporarily pause the events from the stream.
1293 */
1294 abstract class StreamSubscription<T> {
1295 /**
1296 * Cancels this subscription. It will no longer receive events.
1297 *
1298 * May return a future which completes when the stream is done cleaning up.
1299 * This can be used if the stream needs to release some resources
1300 * that are needed for a following operation,
1301 * for example a file being read, that should be deleted afterwards.
1302 * In that case, the file may not be able to be deleted successfully
1303 * until the returned future has completed.
1304 *
1305 * The future will be completed with a `null` value.
1306 * If the cleanup throws, which it really shouldn't, the returned future
1307 * will be completed with that error.
1308 *
1309 * Returns `null` if there is no need to wait.
1310 */
1311 Future cancel();
1312
1313 /**
1314 * Set or override the data event handler of this subscription.
1315 *
1316 * This method overrides the handler that has been set at the invocation of
1317 * [Stream.listen].
1318 */
1319 void onData(void handleData(T data));
1320
1321 /**
1322 * Set or override the error event handler of this subscription.
1323 *
1324 * This method overrides the handler that has been set at the invocation of
1325 * [Stream.listen] or by calling [asFuture].
1326 */
1327 void onError(Function handleError);
1328
1329 /**
1330 * Set or override the done event handler of this subscription.
1331 *
1332 * This method overrides the handler that has been set at the invocation of
1333 * [Stream.listen] or by calling [asFuture].
1334 */
1335 void onDone(void handleDone());
1336
1337 /**
1338 * Request that the stream pauses events until further notice.
1339 *
1340 * While paused, the subscription will not fire any events.
1341 * If it receives events from its source, they will be buffered until
1342 * the subscription is resumed.
1343 * The underlying source is usually informed about the pause,
1344 * so it can stop generating events until the subscription is resumed.
1345 *
1346 * To avoid buffering events on a broadcast stream, it is better to
1347 * cancel this subscription, and start to listen again when events
1348 * are needed.
1349 *
1350 * If [resumeSignal] is provided, the stream will undo the pause
1351 * when the future completes. If the future completes with an error,
1352 * the stream will resume, but the error will not be handled!
1353 *
1354 * A call to [resume] will also undo a pause.
1355 *
1356 * If the subscription is paused more than once, an equal number
1357 * of resumes must be performed to resume the stream.
1358 *
1359 * Currently DOM streams silently drop events when the stream is paused. This
1360 * is a bug and will be fixed.
1361 */
1362 void pause([Future resumeSignal]);
1363
1364 /**
1365 * Resume after a pause.
1366 */
1367 void resume();
1368
1369 /**
1370 * Returns true if the [StreamSubscription] is paused.
1371 */
1372 bool get isPaused;
1373
1374 /**
1375 * Returns a future that handles the [onDone] and [onError] callbacks.
1376 *
1377 * This method *overwrites* the existing [onDone] and [onError] callbacks
1378 * with new ones that complete the returned future.
1379 *
1380 * In case of an error the subscription will automatically cancel (even
1381 * when it was listening with `cancelOnError` set to `false`).
1382 *
1383 * In case of a `done` event the future completes with the given
1384 * [futureValue].
1385 */
1386 Future asFuture([var futureValue]);
1387 }
1388
1389
1390 /**
1391 * An interface that abstracts creation or handling of [Stream] events.
1392 */
1393 abstract class EventSink<T> implements Sink<T> {
1394 /** Send a data event to a stream. */
1395 void add(T event);
1396
1397 /** Send an async error to a stream. */
1398 void addError(errorEvent, [StackTrace stackTrace]);
1399
1400 /** Close the sink. No further events can be added after closing. */
1401 void close();
1402 }
1403
1404
1405 /** [Stream] wrapper that only exposes the [Stream] interface. */
1406 class StreamView<T> extends Stream<T> {
1407 Stream<T> _stream;
1408
1409 StreamView(this._stream);
1410
1411 bool get isBroadcast => _stream.isBroadcast;
1412
1413 Stream<T> asBroadcastStream({void onListen(StreamSubscription<T> subscription) ,
1414 void onCancel(StreamSubscription<T> subscription) })
1415 => _stream.asBroadcastStream(onListen: onListen, onCancel: onCancel);
1416
1417 StreamSubscription<T> listen(void onData(T value),
1418 { Function onError,
1419 void onDone(),
1420 bool cancelOnError }) {
1421 return _stream.listen(onData, onError: onError, onDone: onDone,
1422 cancelOnError: cancelOnError);
1423 }
1424 }
1425
1426
1427 /**
1428 * The target of a [Stream.pipe] call.
1429 *
1430 * The [Stream.pipe] call will pass itself to this object, and then return
1431 * the resulting [Future]. The pipe should complete the future when it's
1432 * done.
1433 */
1434 abstract class StreamConsumer<S> {
1435 /**
1436 * Consumes the elements of [stream].
1437 *
1438 * Listens on [stream] and does something for each event.
1439 *
1440 * The consumer may stop listening after an error, or it may consume
1441 * all the errors and only stop at a done event.
1442 */
1443 Future addStream(Stream<S> stream);
1444
1445 /**
1446 * Tell the consumer that no futher streams will be added.
1447 *
1448 * Returns a future that is completed when the consumer is done handling
1449 * events.
1450 */
1451 Future close();
1452 }
1453
1454
1455 /**
1456 * A [StreamSink] unifies the asynchronous methods from [StreamConsumer] and
1457 * the synchronous methods from [EventSink].
1458 *
1459 * The [EventSink] methods can't be used while the [addStream] is called.
1460 * As soon as the [addStream]'s [Future] completes with a value, the
1461 * [EventSink] methods can be used again.
1462 *
1463 * If [addStream] is called after any of the [EventSink] methods, it'll
1464 * be delayed until the underlying system has consumed the data added by the
1465 * [EventSink] methods.
1466 *
1467 * When [EventSink] methods are used, the [done] [Future] can be used to
1468 * catch any errors.
1469 *
1470 * When [close] is called, it will return the [done] [Future].
1471 */
1472 abstract class StreamSink<S> implements StreamConsumer<S>, EventSink<S> {
1473 /**
1474 * As [EventSink.close], but returns a future.
1475 *
1476 * Returns the same future as [done].
1477 */
1478 Future close();
1479
1480 /**
1481 * Return a future which is completed when the [StreamSink] is finished.
1482 *
1483 * If the `StreamSink` fails with an error,
1484 * perhaps in response to adding events using [add], [addError] or [close],
1485 * the [done] future will complete with that error.
1486 *
1487 * Otherwise, the returned future will complete when either:
1488 *
1489 * * all events have been processed and the sink has been closed, or
1490 * * the sink has otherwise been stopped from handling more events
1491 * (for example by cancelling a stream subscription).
1492 */
1493 Future get done;
1494 }
1495
1496
1497 /**
1498 * The target of a [Stream.transform] call.
1499 *
1500 * The [Stream.transform] call will pass itself to this object and then return
1501 * the resulting stream.
1502 *
1503 * It is good practice to write transformers that can be used multiple times.
1504 */
1505 abstract class StreamTransformer<S, T> {
1506 /**
1507 * Creates a [StreamTransformer].
1508 *
1509 * The returned instance takes responsibility of implementing ([bind]).
1510 * When the user invokes `bind` it returns a new "bound" stream. Only when
1511 * the user starts listening to the bound stream, the `listen` method
1512 * invokes the given closure [transformer].
1513 *
1514 * The [transformer] closure receives the stream, that was bound, as argument
1515 * and returns a [StreamSubscription]. In almost all cases the closure
1516 * listens itself to the stream that is given as argument.
1517 *
1518 * The result of invoking the [transformer] closure is a [StreamSubscription].
1519 * The bound stream-transformer (created by the `bind` method above) then sets
1520 * the handlers it received as part of the `listen` call.
1521 *
1522 * Conceptually this can be summarized as follows:
1523 *
1524 * 1. `var transformer = new StreamTransformer(transformerClosure);`
1525 * creates a `StreamTransformer` that supports the `bind` method.
1526 * 2. `var boundStream = stream.transform(transformer);` binds the `stream`
1527 * and returns a bound stream that has a pointer to `stream`.
1528 * 3. `boundStream.listen(f1, onError: f2, onDone: f3, cancelOnError: b)`
1529 * starts the listening and transformation. This is accomplished
1530 * in 2 steps: first the `boundStream` invokes the `transformerClosure` with
1531 * the `stream` it captured: `transformerClosure(stream, b)`.
1532 * The result `subscription`, a [StreamSubscription], is then
1533 * updated to receive its handlers: `subscription.onData(f1)`,
1534 * `subscription.onError(f2)`, `subscription(f3)`. Finally the subscription
1535 * is returned as result of the `listen` call.
1536 *
1537 * There are two common ways to create a StreamSubscription:
1538 *
1539 * 1. by creating a new class that implements [StreamSubscription].
1540 * Note that the subscription should run callbacks in the [Zone] the
1541 * stream was listened to.
1542 * 2. by allocating a [StreamController] and to return the result of
1543 * listening to its stream.
1544 *
1545 * Example use of a duplicating transformer:
1546 *
1547 * stringStream.transform(new StreamTransformer<String, String>(
1548 * (Stream<String> input, bool cancelOnError) {
1549 * StreamController<String> controller;
1550 * StreamSubscription<String> subscription;
1551 * controller = new StreamController<String>(
1552 * onListen: () {
1553 * subscription = input.listen((data) {
1554 * // Duplicate the data.
1555 * controller.add(data);
1556 * controller.add(data);
1557 * },
1558 * onError: controller.addError,
1559 * onDone: controller.close,
1560 * cancelOnError: cancelOnError);
1561 * },
1562 * onPause: subscription.pause,
1563 * onResume: subscription.resume,
1564 * onCancel: subscription.cancel,
1565 * sync: true);
1566 * return controller.stream.listen(null);
1567 * });
1568 */
1569 const factory StreamTransformer(
1570 StreamSubscription<T> transformer(Stream<S> stream, bool cancelOnError))
1571 = _StreamSubscriptionTransformer;
1572
1573 /**
1574 * Creates a [StreamTransformer] that delegates events to the given functions.
1575 *
1576 * Example use of a duplicating transformer:
1577 *
1578 * stringStream.transform(new StreamTransformer<String, String>.fromHandle rs(
1579 * handleData: (String value, EventSink<String> sink) {
1580 * sink.add(value);
1581 * sink.add(value); // Duplicate the incoming events.
1582 * }));
1583 */
1584 factory StreamTransformer.fromHandlers({
1585 void handleData(S data, EventSink<T> sink),
1586 void handleError(Object error, StackTrace stackTrace, EventSink<T> sink),
1587 void handleDone(EventSink<T> sink)})
1588 = _StreamHandlerTransformer;
1589
1590 /**
1591 * Transform the incoming [stream]'s events.
1592 *
1593 * Creates a new stream.
1594 * When this stream is listened to, it will start listening on [stream],
1595 * and generate events on the new stream based on the events from [stream].
1596 *
1597 * Subscriptions on the returned stream should propagate pause state
1598 * to the subscription on [stream].
1599 */
1600 Stream<T> bind(Stream<S> stream);
1601 }
1602
1603 /**
1604 * An [Iterable] like interface for the values of a [Stream].
1605 *
1606 * This wraps a [Stream] and a subscription on the stream. It listens
1607 * on the stream, and completes the future returned by [moveNext] when the
1608 * next value becomes available.
1609 */
1610 abstract class StreamIterator<T> {
1611
1612 /** Create a [StreamIterator] on [stream]. */
1613 factory StreamIterator(Stream<T> stream)
1614 // TODO(lrn): use redirecting factory constructor when type
1615 // arguments are supported.
1616 => new _StreamIteratorImpl<T>(stream);
1617
1618 /**
1619 * Wait for the next stream value to be available.
1620 *
1621 * It is not allowed to call this function again until the future has
1622 * completed. If the returned future completes with anything except `true`,
1623 * the iterator is done, and no new value will ever be available.
1624 *
1625 * The future may complete with an error, if the stream produces an error.
1626 */
1627 Future<bool> moveNext();
1628
1629 /**
1630 * The current value of the stream.
1631 *
1632 * Only valid when the future returned by [moveNext] completes with `true`
1633 * as value, and only until the next call to [moveNext].
1634 */
1635 T get current;
1636
1637 /**
1638 * Cancels the stream iterator (and the underlying stream subscription) early.
1639 *
1640 * The stream iterator is automatically canceled if the [moveNext] future
1641 * completes with either `false` or an error.
1642 *
1643 * If a [moveNext] call has been made, it will complete with `false` as value,
1644 * as will all further calls to [moveNext].
1645 *
1646 * If you need to stop listening for values before the stream iterator is
1647 * automatically closed, you must call [cancel] to ensure that the stream
1648 * is properly closed.
1649 *
1650 * Returns a future if the cancel-operation is not completed synchronously.
1651 * Otherwise returns `null`.
1652 */
1653 Future cancel();
1654 }
1655
1656
1657 /**
1658 * Wraps an [_EventSink] so it exposes only the [EventSink] interface.
1659 */
1660 class _ControllerEventSinkWrapper<T> implements EventSink<T> {
1661 EventSink _sink;
1662 _ControllerEventSinkWrapper(this._sink);
1663
1664 void add(T data) { _sink.add(data); }
1665 void addError(error, [StackTrace stackTrace]) {
1666 _sink.addError(error, stackTrace);
1667 }
1668 void close() { _sink.close(); }
1669 }
OLDNEW
« no previous file with comments | « test/generated_sdk/lib/async/schedule_microtask.dart ('k') | test/generated_sdk/lib/async/stream_controller.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698