| OLD | NEW | 
|---|
| 1 // Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file | 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 | 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. | 3 // BSD-style license that can be found in the LICENSE file. | 
| 4 | 4 | 
| 5 part of dart.convert; | 5 part of dart.convert; | 
| 6 | 6 | 
| 7 typedef void _ChunkedConversionCallback<T>(T accumulated); | 7 typedef void _ChunkedConversionCallback<T>(T accumulated); | 
| 8 | 8 | 
| 9 /** | 9 /** | 
|  | 10  * A converter that supports chunked conversions. | 
|  | 11  * | 
|  | 12  * In addition to immediate conversions from [S] to [T], a chunked converter | 
|  | 13  * also supports longer-running conversions from [S2] to [T2]. | 
|  | 14  * | 
|  | 15  * Frequently, the source and target types are the same, but this is not a | 
|  | 16  * requirement. In particular, converters that work with lists in the | 
|  | 17  * immediate conversion, could flatten the type for the chunked conversion. | 
|  | 18  * | 
|  | 19  * For example, the [LineSplitter] class returns a `List<String>` for the | 
|  | 20  * immediate conversion, but returns individual `String`s in the chunked | 
|  | 21  * conversion. | 
|  | 22  */ | 
|  | 23 abstract class ChunkedConverter<S, T, S2, T2> extends Converter<S, T> { | 
|  | 24 | 
|  | 25   const ChunkedConverter(); | 
|  | 26 | 
|  | 27   /** | 
|  | 28    * Starts a chunked conversion. | 
|  | 29    * | 
|  | 30    * The returned sink serves as input for the long-running conversion. The | 
|  | 31    * given [sink] serves as output. | 
|  | 32    */ | 
|  | 33   ChunkedConversionSink<S2> startChunkedConversion(Sink<T2> sink) { | 
|  | 34     throw new UnsupportedError( | 
|  | 35         "This converter does not support chunked conversions: $this"); | 
|  | 36   } | 
|  | 37 | 
|  | 38   Stream<T2> bind(Stream<S2> stream) { | 
|  | 39     return new Stream<T2>.eventTransformed( | 
|  | 40         stream, | 
|  | 41         (EventSink<T2> sink) => | 
|  | 42             new _ConverterStreamEventSink<S2, T2>(this, sink)); | 
|  | 43   } | 
|  | 44 | 
|  | 45   /** | 
|  | 46    * Fuses this instance with the given [other] converter. | 
|  | 47    * | 
|  | 48    * If [other] is a ChunkedConverter (with matching generic types), returns a | 
|  | 49    * [ChunkedConverter]. | 
|  | 50    */ | 
|  | 51   Converter<S, dynamic> fuse(Converter<T, dynamic> other) { | 
|  | 52     if (other is ChunkedConverter<T, dynamic, T2, dynamic>) { | 
|  | 53       return new _FusedChunkedConverter<S, T, dynamic, S2, T2, dynamic>( | 
|  | 54           this, other); | 
|  | 55     } | 
|  | 56     return super.fuse(other); | 
|  | 57   } | 
|  | 58 } | 
|  | 59 | 
|  | 60 /** | 
| 10  * A [ChunkedConversionSink] is used to transmit data more efficiently between | 61  * A [ChunkedConversionSink] is used to transmit data more efficiently between | 
| 11  * two converters during chunked conversions. | 62  * two converters during chunked conversions. | 
| 12  * | 63  * | 
| 13  * The basic `ChunkedConversionSink` is just a [Sink], and converters should | 64  * The basic `ChunkedConversionSink` is just a [Sink], and converters should | 
| 14  * work with a plain `Sink`, but may work more efficiently with certain | 65  * work with a plain `Sink`, but may work more efficiently with certain | 
| 15  * specialized types of `ChunkedConversionSink`. | 66  * specialized types of `ChunkedConversionSink`. | 
| 16  * | 67  * | 
| 17  * It is recommended that implementations of `ChunkedConversionSink` extends | 68  * It is recommended that implementations of `ChunkedConversionSink` extends | 
| 18  * this class, to inherit any further methods that may be added to the class. | 69  * this class, to inherit any further methods that may be added to the class. | 
| 19  */ | 70  */ | 
| (...skipping 28 matching lines...) Expand all  Loading... | 
| 48   final _ChunkedConversionCallback<List<T>> _callback; | 99   final _ChunkedConversionCallback<List<T>> _callback; | 
| 49   final List<T> _accumulated = <T>[]; | 100   final List<T> _accumulated = <T>[]; | 
| 50 | 101 | 
| 51   _SimpleCallbackSink(this._callback); | 102   _SimpleCallbackSink(this._callback); | 
| 52 | 103 | 
| 53   void add(T chunk) { _accumulated.add(chunk); } | 104   void add(T chunk) { _accumulated.add(chunk); } | 
| 54   void close() { _callback(_accumulated); } | 105   void close() { _callback(_accumulated); } | 
| 55 } | 106 } | 
| 56 | 107 | 
| 57 /** | 108 /** | 
| 58  * This class converts implements the logic for a chunked conversion as a | 109  * This class implements the logic for a chunked conversion as a | 
| 59  * stream transformer. | 110  * stream transformer. | 
| 60  * | 111  * | 
| 61  * It is used as strategy in the [EventTransformStream]. | 112  * It is used as strategy in the [EventTransformStream]. | 
| 62  * | 113  * | 
| 63  * It also implements the [ChunkedConversionSink] interface so that it | 114  * It also implements the [ChunkedConversionSink] interface so that it | 
| 64  * can be used as output sink in a chunked conversion. | 115  * can be used as output sink in a chunked conversion. | 
| 65  */ | 116  */ | 
| 66 class _ConverterStreamEventSink<S, T> implements EventSink<S> { | 117 class _ConverterStreamEventSink<S, T> implements EventSink<S> { | 
| 67   /** The output sink for the converter. */ | 118   /** The output sink for the converter. */ | 
| 68   final EventSink<T> _eventSink; | 119   final EventSink<T> _eventSink; | 
| 69 | 120 | 
| 70   /** | 121   /** | 
| 71    * The input sink for new data. All data that is received with | 122    * The input sink for new data. All data that is received with | 
| 72    * [handleData] is added into this sink. | 123    * [handleData] is added into this sink. | 
| 73    */ | 124    */ | 
| 74   ChunkedConversionSink _chunkedSink; | 125   ChunkedConversionSink<S> _chunkedSink; | 
| 75 | 126 | 
| 76   _ConverterStreamEventSink(Converter converter, EventSink<T> sink) | 127   _ConverterStreamEventSink( | 
|  | 128       Converter/*=ChunkedConverter<dynamic, dynamic, S, T>*/ converter, | 
|  | 129       EventSink<T> sink) | 
| 77       : this._eventSink = sink, | 130       : this._eventSink = sink, | 
| 78         _chunkedSink = converter.startChunkedConversion(sink); | 131         _chunkedSink = converter.startChunkedConversion(sink); | 
| 79 | 132 | 
| 80   void add(S o) => _chunkedSink.add(o); | 133   void add(S o) => _chunkedSink.add(o); | 
| 81   void addError(Object error, [StackTrace stackTrace]) { | 134   void addError(Object error, [StackTrace stackTrace]) { | 
| 82     _eventSink.addError(error, stackTrace); | 135     _eventSink.addError(error, stackTrace); | 
| 83   } | 136   } | 
| 84   void close() => _chunkedSink.close(); | 137   void close() => _chunkedSink.close(); | 
| 85 } | 138 } | 
|  | 139 | 
|  | 140 /** | 
|  | 141  * Fuses two chunked converters. | 
|  | 142  */ | 
|  | 143 class _FusedChunkedConverter<S, M, T, S2, M2, T2> extends | 
|  | 144     ChunkedConverter<S, T, S2, T2> { | 
|  | 145   final ChunkedConverter<S, M, S2, M2> _first; | 
|  | 146   final ChunkedConverter<M, T, M2, T2> _second; | 
|  | 147 | 
|  | 148   _FusedChunkedConverter(this._first, this._second); | 
|  | 149 | 
|  | 150   T convert(S input) => _second.convert(_first.convert(input)); | 
|  | 151 | 
|  | 152   ChunkedConversionSink<S2> startChunkedConversion(Sink<T2> sink) { | 
|  | 153     return _first.startChunkedConversion(_second.startChunkedConversion(sink)); | 
|  | 154   } | 
|  | 155 } | 
| OLD | NEW | 
|---|