Index: sdk/lib/convert/chunked_conversion.dart |
diff --git a/sdk/lib/convert/chunked_conversion.dart b/sdk/lib/convert/chunked_conversion.dart |
new file mode 100644 |
index 0000000000000000000000000000000000000000..6312807ccd9758c191d024f57044b9a8dd5e1ba6 |
--- /dev/null |
+++ b/sdk/lib/convert/chunked_conversion.dart |
@@ -0,0 +1,134 @@ |
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
+// for details. All rights reserved. Use of this source code is governed by a |
+// BSD-style license that can be found in the LICENSE file. |
+ |
+part of dart.convert; |
+ |
+/** |
+ * This exception is thrown when two chunked-conversion interfaces don't |
+ * match. |
+ */ |
+// TODO(floitsch): better documentation. |
+class ChunkedConversionInterfaceMismatchException implements Exception { |
+ final ChunkedConversionInterface interface1; |
+ final ChunkedConversionInterface interface2; |
+ |
+ // TODO(floitsch): provide constructor with the chunked conversion sink |
+ // that tried to be adapted. |
+ ChunkedConversionInterfaceMismatchException(this.interface1, this.interface2); |
+ |
+ String toString() { |
+ return "Chunked-conversion interfaces are incompatible: " |
+ "$interface1, $interface2"; |
+ } |
+} |
+ |
+typedef void _ChunkedConversionCallback<T>(T accumulated); |
+ |
+/** |
+ * This class defines an interface through which a converter can be accessed |
+ * when doing chunked conversions. |
+ * |
+ * A [ChunkedConversionInterface]s is associated with a [ChunkedConversionSink]. |
+ * It represents this sink and can adapt sinks to this interface. |
+ */ |
+abstract class ChunkedConversionInterface<T> { |
+ const ChunkedConversionInterface(); |
+ |
+ /** |
+ * Adapts the given [sink] to the [ChunkedConversionSink] associated with |
+ * `this`. |
+ * |
+ * This method must not invoke the [sink]'s `adaptTo` method. |
+ */ |
+ ChunkedConversionSink<T> adapt(ChunkedConversionSink sink); |
+ |
+ /** |
+ * Creates a [ChunkedConversionSink] that accumulates all incoming data. |
+ * |
+ * Invokes the given [callback] with the accumulated data when the returned |
+ * sink is closed. |
+ */ |
+ ChunkedConversionSink<T> createSink(void callback(accumulated)); |
+} |
+ |
+/** |
+ * This class represents the simple [ChunkedConversionSink] interface without |
+ * additional methods. It is accessed through [ChunkedConversionSink.INTERFACE] |
+ * or as instance field `interface` from sinks that support this interface. |
+ */ |
+class _SimpleChunkedConversionInterface<T> |
+ extends ChunkedConversionInterface<T> { |
+ const _SimpleChunkedConversionInterface(); |
+ |
+ ChunkedConversionSink<T> adapt(ChunkedConversionSink sink) { |
+ // Every sink implements the simple chunked conversion sink. |
+ return sink; |
+ } |
+ |
+ /** |
+ * Creates a [ChunkedConversionSink] that accumulates all incoming data. |
+ * |
+ * Invokes the given [callback] with a list of the accumulated data when the |
+ * returned sink is closed. |
+ */ |
+ ChunkedConversionSink<T> createSink(void callback(List<T> accumulated)) { |
+ return new _SimpleCallbackSink<T>(callback); |
+ } |
+} |
+ |
+/** |
+ * A [ChunkedConversionSink] is used to transmit data more efficiently between |
+ * two converters during chunked conversions. |
+ */ |
+abstract class ChunkedConversionSink<T> { |
+ static const INTERFACE = const _SimpleChunkedConversionInterface(); |
+ |
+ ChunkedConversionSink(); |
+ |
+ /** |
+ * The interface this sink implements. |
+ */ |
+ ChunkedConversionInterface get interface => INTERFACE; |
+ |
+ /** |
+ * Adds chunked data to this sink. |
+ * |
+ * This method is also used when converters are used as [StreamTransformer]s. |
+ */ |
+ void add(T chunk); |
+ |
+ /** |
+ * Closes the sink. |
+ * |
+ * This signals the end of the chunked conversion. This method is called |
+ * when converters are used as [StreamTransformer]'s. |
+ */ |
+ void close(); |
+ |
+ /** |
+ * Adapts `this` to support the given [interface]. |
+ * |
+ * This method may use the [interface]'s `adapt` method. |
+ */ |
+ ChunkedConversionSink adaptTo(ChunkedConversionInterface interface) { |
+ if (this.interface == interface) return this; |
+ return interface.adapt(this); |
+ } |
+} |
+ |
+/** |
+ * This class accumulates all chunks and invokes a callback with a list of |
+ * the chunks when the sink is closed. |
+ * |
+ * This class can be used to terminate a chunked conversion. |
+ */ |
+class _SimpleCallbackSink<T> extends ChunkedConversionSink<T> { |
+ final _ChunkedConversionCallback<List<T>> _callback; |
+ final List<T> _accumulated = <T>[]; |
+ |
+ _SimpleCallbackSink(this._callback); |
+ |
+ void add(T chunk) { _accumulated.add(chunk); } |
+ void close() { _callback(_accumulated); } |
+} |