| Index: tool/input_sdk/lib/convert/chunked_conversion.dart
|
| diff --git a/tool/input_sdk/lib/convert/chunked_conversion.dart b/tool/input_sdk/lib/convert/chunked_conversion.dart
|
| index c933820d030e23fd5acf903727f6e13998122134..95e561c47d2941f1478e361dff1fe9908b7162fe 100644
|
| --- a/tool/input_sdk/lib/convert/chunked_conversion.dart
|
| +++ b/tool/input_sdk/lib/convert/chunked_conversion.dart
|
| @@ -7,6 +7,57 @@ part of dart.convert;
|
| typedef void _ChunkedConversionCallback<T>(T accumulated);
|
|
|
| /**
|
| + * A converter that supports chunked conversions.
|
| + *
|
| + * In addition to immediate conversions from [S] to [T], a chunked converter
|
| + * also supports longer-running conversions from [S2] to [T2].
|
| + *
|
| + * Frequently, the source and target types are the same, but this is not a
|
| + * requirement. In particular, converters that work with lists in the
|
| + * immediate conversion, could flatten the type for the chunked conversion.
|
| + *
|
| + * For example, the [LineSplitter] class returns a `List<String>` for the
|
| + * immediate conversion, but returns individual `String`s in the chunked
|
| + * conversion.
|
| + */
|
| +abstract class ChunkedConverter<S, T, S2, T2> extends Converter<S, T> {
|
| +
|
| + const ChunkedConverter();
|
| +
|
| + /**
|
| + * Starts a chunked conversion.
|
| + *
|
| + * The returned sink serves as input for the long-running conversion. The
|
| + * given [sink] serves as output.
|
| + */
|
| + ChunkedConversionSink<S2> startChunkedConversion(Sink<T2> sink) {
|
| + throw new UnsupportedError(
|
| + "This converter does not support chunked conversions: $this");
|
| + }
|
| +
|
| + Stream<T2> bind(Stream<S2> stream) {
|
| + return new Stream<T2>.eventTransformed(
|
| + stream,
|
| + (EventSink<T2> sink) =>
|
| + new _ConverterStreamEventSink<S2, T2>(this, sink));
|
| + }
|
| +
|
| + /**
|
| + * Fuses this instance with the given [other] converter.
|
| + *
|
| + * If [other] is a ChunkedConverter (with matching generic types), returns a
|
| + * [ChunkedConverter].
|
| + */
|
| + Converter<S, dynamic> fuse(Converter<T, dynamic> other) {
|
| + if (other is ChunkedConverter<T, dynamic, T2, dynamic>) {
|
| + return new _FusedChunkedConverter<S, T, dynamic, S2, T2, dynamic>(
|
| + this, other);
|
| + }
|
| + return super.fuse(other);
|
| + }
|
| +}
|
| +
|
| +/**
|
| * A [ChunkedConversionSink] is used to transmit data more efficiently between
|
| * two converters during chunked conversions.
|
| *
|
| @@ -20,7 +71,7 @@ typedef void _ChunkedConversionCallback<T>(T accumulated);
|
| abstract class ChunkedConversionSink<T> implements Sink<T> {
|
| ChunkedConversionSink();
|
| factory ChunkedConversionSink.withCallback(
|
| - void callback(List<T> accumulated)) = _SimpleCallbackSink<T>;
|
| + void callback(List<T> accumulated)) = _SimpleCallbackSink;
|
|
|
| /**
|
| * Adds chunked data to this sink.
|
| @@ -54,17 +105,8 @@ class _SimpleCallbackSink<T> extends ChunkedConversionSink<T> {
|
| void close() { _callback(_accumulated); }
|
| }
|
|
|
| -class _EventSinkAdapter<T> implements ChunkedConversionSink<T> {
|
| - final EventSink<T> _sink;
|
| -
|
| - _EventSinkAdapter(this._sink);
|
| -
|
| - void add(T data) => _sink.add(data);
|
| - void close() => _sink.close();
|
| -}
|
| -
|
| /**
|
| - * This class converts implements the logic for a chunked conversion as a
|
| + * This class implements the logic for a chunked conversion as a
|
| * stream transformer.
|
| *
|
| * It is used as strategy in the [EventTransformStream].
|
| @@ -80,15 +122,34 @@ class _ConverterStreamEventSink<S, T> implements EventSink<S> {
|
| * The input sink for new data. All data that is received with
|
| * [handleData] is added into this sink.
|
| */
|
| - ChunkedConversionSink _chunkedSink;
|
| + final ChunkedConversionSink<S> _chunkedSink;
|
|
|
| - _ConverterStreamEventSink(Converter converter, EventSink<T> sink)
|
| + _ConverterStreamEventSink(
|
| + Converter/*=ChunkedConverter<dynamic, dynamic, S, T>*/ converter,
|
| + EventSink<T> sink)
|
| : this._eventSink = sink,
|
| _chunkedSink = converter.startChunkedConversion(sink);
|
|
|
| - void add(S o) => _chunkedSink.add(o);
|
| + void add(S o) { _chunkedSink.add(o); }
|
| void addError(Object error, [StackTrace stackTrace]) {
|
| _eventSink.addError(error, stackTrace);
|
| }
|
| - void close() => _chunkedSink.close();
|
| + void close() { _chunkedSink.close(); }
|
| +}
|
| +
|
| +/**
|
| + * Fuses two chunked converters.
|
| + */
|
| +class _FusedChunkedConverter<S, M, T, S2, M2, T2> extends
|
| + ChunkedConverter<S, T, S2, T2> {
|
| + final ChunkedConverter<S, M, S2, M2> _first;
|
| + final ChunkedConverter<M, T, M2, T2> _second;
|
| +
|
| + _FusedChunkedConverter(this._first, this._second);
|
| +
|
| + T convert(S input) => _second.convert(_first.convert(input));
|
| +
|
| + ChunkedConversionSink<S2> startChunkedConversion(Sink<T2> sink) {
|
| + return _first.startChunkedConversion(_second.startChunkedConversion(sink));
|
| + }
|
| }
|
|
|