Chromium Code Reviews| Index: sdk/lib/convert/chunked_conversion.dart |
| diff --git a/sdk/lib/convert/chunked_conversion.dart b/sdk/lib/convert/chunked_conversion.dart |
| index 4c962eb62c589db90f57512002408d7f12e931be..216cafe43dadee2ed34f4f843b2a210de7b25364 100644 |
| --- a/sdk/lib/convert/chunked_conversion.dart |
| +++ b/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>) { |
|
floitsch
2016/04/11 18:37:53
Looking at this again, I guess there is no way to
Leaf
2016/04/11 19:46:27
I don't see anything in this code that is directly
floitsch
2016/04/12 15:28:57
My mistake. Somehow I was convinced that strong mo
Leaf
2016/04/12 17:44:30
We tried... but without generic methods it's hard
floitsch
2016/04/12 17:55:29
Yes. This is not perfect yet...
I will make 'fuse'
|
| + 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. |
| * |
| @@ -55,7 +106,7 @@ class _SimpleCallbackSink<T> extends ChunkedConversionSink<T> { |
| } |
| /** |
| - * 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]. |
| @@ -71,9 +122,10 @@ 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; |
| + ChunkedConversionSink<S> _chunkedSink; |
| - _ConverterStreamEventSink(Converter converter, EventSink<T> sink) |
| + _ConverterStreamEventSink( |
| + ChunkedConverter<dynamic, dynamic, S, T> converter, EventSink<T> sink) |
|
floitsch
2016/04/11 18:37:53
This is the line that broke the build. Since not a
Leaf
2016/04/11 19:46:27
I'm probably just off to a slow start this week, b
floitsch
2016/04/12 15:28:57
ditto.
|
| : this._eventSink = sink, |
| _chunkedSink = converter.startChunkedConversion(sink); |
| @@ -83,3 +135,20 @@ class _ConverterStreamEventSink<S, T> implements EventSink<S> { |
| } |
| 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)); |
| + } |
| +} |