Skip to content

Commit 50bdab3

Browse files
committed
Steps towards making the convert library strong-mode compliant.
This version has a few deprecated methods. In a future release they will be removed. See https://codereview.chromium.org/1827803002 for the final patch (once the deprecated methods have been removed). R=leafp@google.com, lrn@google.com Committed: 4ab1219 Reverted: 045a375 Review URL: https://codereview.chromium.org/1847843002 .
1 parent 688eeb5 commit 50bdab3

File tree

17 files changed

+147
-57
lines changed

17 files changed

+147
-57
lines changed

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@
88
* Added `SecurityContext.alpnSupported`, which is true if a platform
99
supports ALPN, and false otherwise.
1010

11+
* `dart:convert`
12+
* Introduce `ChunkedConverter` and deprecate chunked methods on `Converter`.
13+
1114
### Analyzer
1215

1316
* Static checking of `for in` statements. These will now produce static

pkg/analysis_server/benchmark/integration/input_converter.dart

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -271,7 +271,9 @@ abstract class CommonInputConverter extends Converter<String, Operation> {
271271
* into a series of operations to be sent to the analysis server.
272272
* The input stream can be either an instrumenation or log file.
273273
*/
274-
class InputConverter extends Converter<String, Operation> {
274+
class InputConverter
275+
extends ChunkedConverter<String, Operation, String, Operation> {
276+
275277
final Logger logger = new Logger('InputConverter');
276278

277279
/**

pkg/analysis_server/lib/src/channel/channel.dart

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -85,37 +85,40 @@ abstract class ClientCommunicationChannel {
8585
* Instances of the class [JsonStreamDecoder] convert JSON strings to JSON
8686
* maps.
8787
*/
88-
class JsonStreamDecoder extends Converter<String, Map> {
88+
class JsonStreamDecoder extends
89+
ChunkedConverter<String, Map, String, Map> {
8990
@override
9091
Map convert(String text) => JSON.decode(text);
9192

9293
@override
93-
ChunkedConversionSink startChunkedConversion(Sink sink) =>
94+
ChunkedConversionSink<String> startChunkedConversion(Sink<Map> sink) =>
9495
new ChannelChunkSink<String, Map>(this, sink);
9596
}
9697

9798
/**
9899
* Instances of the class [NotificationConverter] convert JSON maps to
99100
* [Notification]s.
100101
*/
101-
class NotificationConverter extends Converter<Map, Notification> {
102+
class NotificationConverter extends
103+
ChunkedConverter<Map, Notification, Map, Notification> {
102104
@override
103105
Notification convert(Map json) => new Notification.fromJson(json);
104106

105107
@override
106-
ChunkedConversionSink startChunkedConversion(Sink sink) =>
108+
ChunkedConversionSink<Map> startChunkedConversion(Sink<Notification> sink) =>
107109
new ChannelChunkSink<Map, Notification>(this, sink);
108110
}
109111

110112
/**
111113
* Instances of the class [ResponseConverter] convert JSON maps to [Response]s.
112114
*/
113-
class ResponseConverter extends Converter<Map, Response> {
115+
class ResponseConverter extends
116+
ChunkedConverter<Map, Response, Map, Response> {
114117
@override
115118
Response convert(Map json) => new Response.fromJson(json);
116119

117120
@override
118-
ChunkedConversionSink startChunkedConversion(Sink sink) =>
121+
ChunkedConversionSink<Map> startChunkedConversion(Sink<Response> sink) =>
119122
new ChannelChunkSink<Map, Response>(this, sink);
120123
}
121124

runtime/lib/convert_patch.dart

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,13 +39,14 @@ patch class Utf8Decoder {
3939
}
4040
}
4141

42-
class _JsonUtf8Decoder extends Converter<List<int>, Object> {
42+
class _JsonUtf8Decoder extends
43+
ChunkedConverter<List<int>, Object, List<int>, Object> {
4344
final _Reviver _reviver;
4445
final bool _allowMalformed;
4546

4647
_JsonUtf8Decoder(this._reviver, this._allowMalformed);
4748

48-
dynamic convert(List<int> input) {
49+
Object convert(List<int> input) {
4950
var parser = _JsonUtf8DecoderSink._createParser(_reviver, _allowMalformed);
5051
parser.chunk = input;
5152
parser.chunkEnd = input.length;

sdk/lib/convert/ascii.dart

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,8 @@ class AsciiCodec extends Encoding {
6969

7070
// Superclass for [AsciiEncoder] and [Latin1Encoder].
7171
// Generalizes common operations that only differ by a mask;
72-
class _UnicodeSubsetEncoder extends Converter<String, List<int>> {
72+
class _UnicodeSubsetEncoder extends
73+
ChunkedConverter<String, List<int>, String, List<int>> {
7374
final int _subsetMask;
7475

7576
const _UnicodeSubsetEncoder(this._subsetMask);
@@ -154,7 +155,8 @@ class _UnicodeSubsetEncoderSink extends StringConversionSinkBase {
154155
* This class converts Latin-1 bytes (lists of unsigned 8-bit integers)
155156
* to a string.
156157
*/
157-
abstract class _UnicodeSubsetDecoder extends Converter<List<int>, String> {
158+
abstract class _UnicodeSubsetDecoder extends
159+
ChunkedConverter<List<int>, String, List<int>, String> {
158160
final bool _allowInvalid;
159161
final int _subsetMask;
160162

sdk/lib/convert/base64.dart

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,8 @@ class Base64Codec extends Codec<List<int>, String> {
7070
*
7171
* The results are ASCII strings using a restricted alphabet.
7272
*/
73-
class Base64Encoder extends Converter<List<int>, String> {
73+
class Base64Encoder extends
74+
ChunkedConverter<List<int>, String, List<int>, String> {
7475
final bool _urlSafe;
7576

7677
const Base64Encoder() : _urlSafe = false;
@@ -89,14 +90,6 @@ class Base64Encoder extends Converter<List<int>, String> {
8990
}
9091
return new _AsciiBase64EncoderSink(sink, _urlSafe);
9192
}
92-
93-
Stream<String> bind(Stream<List<int>> stream) {
94-
return new Stream<String>.eventTransformed(
95-
stream,
96-
(EventSink sink) =>
97-
new _ConverterStreamEventSink<List<int>, String>(
98-
this, sink));
99-
}
10093
}
10194

10295
/**
@@ -348,7 +341,9 @@ class _Utf8Base64EncoderSink extends _Base64EncoderSink {
348341
*
349342
* The encoding is required to be properly padded.
350343
*/
351-
class Base64Decoder extends Converter<String, List<int>> {
344+
class Base64Decoder extends
345+
ChunkedConverter<String, List<int>, String, List<int>> {
346+
352347
const Base64Decoder();
353348

354349
List<int> convert(String input, [int start = 0, int end]) {

sdk/lib/convert/chunked_conversion.dart

Lines changed: 73 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,57 @@ part of dart.convert;
66

77
typedef void _ChunkedConversionCallback<T>(T accumulated);
88

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+
960
/**
1061
* A [ChunkedConversionSink] is used to transmit data more efficiently between
1162
* two converters during chunked conversions.
@@ -55,7 +106,7 @@ class _SimpleCallbackSink<T> extends ChunkedConversionSink<T> {
55106
}
56107

57108
/**
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
59110
* stream transformer.
60111
*
61112
* It is used as strategy in the [EventTransformStream].
@@ -71,9 +122,11 @@ class _ConverterStreamEventSink<S, T> implements EventSink<S> {
71122
* The input sink for new data. All data that is received with
72123
* [handleData] is added into this sink.
73124
*/
74-
ChunkedConversionSink _chunkedSink;
125+
ChunkedConversionSink<S> _chunkedSink;
75126

76-
_ConverterStreamEventSink(Converter converter, EventSink<T> sink)
127+
_ConverterStreamEventSink(
128+
Converter/*=ChunkedConverter<dynamic, dynamic, S, T>*/ converter,
129+
EventSink<T> sink)
77130
: this._eventSink = sink,
78131
_chunkedSink = converter.startChunkedConversion(sink);
79132

@@ -83,3 +136,20 @@ class _ConverterStreamEventSink<S, T> implements EventSink<S> {
83136
}
84137
void close() => _chunkedSink.close();
85138
}
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+
}

sdk/lib/convert/converter.dart

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -29,14 +29,22 @@ abstract class Converter<S, T> implements StreamTransformer {
2929
}
3030

3131
/**
32-
* Starts a chunked conversion.
32+
* Deprecated.
33+
*
34+
* Use the [ChunkedConverter] interface instead.
3335
*/
36+
@deprecated
3437
ChunkedConversionSink startChunkedConversion(Sink sink) {
3538
throw new UnsupportedError(
3639
"This converter does not support chunked conversions: $this");
3740
}
3841

39-
// Subclasses are encouraged to provide better types.
42+
/**
43+
* Deprecated.
44+
*
45+
* Use the [ChunkedConverter] interface instead.
46+
*/
47+
@deprecated
4048
Stream bind(Stream stream) {
4149
return new Stream.eventTransformed(
4250
stream,
@@ -50,14 +58,10 @@ abstract class Converter<S, T> implements StreamTransformer {
5058
* For a non-chunked conversion converts the input in sequence.
5159
*/
5260
class _FusedConverter<S, M, T> extends Converter<S, T> {
53-
final Converter _first;
54-
final Converter _second;
61+
final Converter<S, M> _first;
62+
final Converter<M, T> _second;
5563

5664
_FusedConverter(this._first, this._second);
5765

5866
T convert(S input) => _second.convert(_first.convert(input));
59-
60-
ChunkedConversionSink startChunkedConversion(Sink sink) {
61-
return _first.startChunkedConversion(_second.startChunkedConversion(sink));
62-
}
6367
}

sdk/lib/convert/encoding.dart

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@ part of dart.convert;
1010
abstract class Encoding extends Codec<String, List<int>> {
1111
const Encoding();
1212

13+
ChunkedConverter<String, List<int>, String, List<int>> get encoder;
14+
ChunkedConverter<List<int>, String, List<int>, String> get decoder;
15+
1316
Future<String> decodeStream(Stream<List<int>> byteStream) {
1417
return byteStream
1518
.transform(decoder)

sdk/lib/convert/html_escape.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,7 @@ class HtmlEscapeMode {
152152
* found to be easier to read if greater-than is also escaped whenever
153153
* less-than is.
154154
*/
155-
class HtmlEscape extends Converter<String, String> {
155+
class HtmlEscape extends ChunkedConverter<String, String, String, String> {
156156

157157
/** The [HtmlEscapeMode] used by the converter. */
158158
final HtmlEscapeMode mode;

sdk/lib/convert/json.dart

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,7 @@ class JsonCodec extends Codec<Object, String> {
159159
/**
160160
* This class converts JSON objects to strings.
161161
*/
162-
class JsonEncoder extends Converter<Object, String> {
162+
class JsonEncoder extends ChunkedConverter<Object, String, Object, String> {
163163
/**
164164
* The string used for indention.
165165
*
@@ -283,7 +283,8 @@ class JsonEncoder extends Converter<Object, String> {
283283
* a JSON string, and then UTF-8 encoding the string, but without
284284
* creating an intermediate string.
285285
*/
286-
class JsonUtf8Encoder extends Converter<Object, List<int>> {
286+
class JsonUtf8Encoder extends
287+
ChunkedConverter<Object, List<int>, Object, List<int>> {
287288
/** Default buffer size used by the JSON-to-UTF-8 encoder. */
288289
static const int DEFAULT_BUFFER_SIZE = 256;
289290
/** Indentation used in pretty-print mode, `null` if not pretty. */
@@ -473,7 +474,7 @@ class _JsonUtf8EncoderSink extends ChunkedConversionSink<Object> {
473474
/**
474475
* This class parses JSON strings and builds the corresponding objects.
475476
*/
476-
class JsonDecoder extends Converter<String, Object> {
477+
class JsonDecoder extends ChunkedConverter<String, Object, String, Object> {
477478
final _Reviver _reviver;
478479
/**
479480
* Constructs a new JsonDecoder.

sdk/lib/convert/latin1.dart

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,9 +59,9 @@ class Latin1Codec extends Encoding {
5959
}
6060
}
6161

62-
Converter<String, List<int>> get encoder => const Latin1Encoder();
62+
Latin1Encoder get encoder => const Latin1Encoder();
6363

64-
Converter<List<int>, String> get decoder =>
64+
Latin1Decoder get decoder =>
6565
_allowInvalid ? const Latin1Decoder(allowInvalid: true)
6666
: const Latin1Decoder(allowInvalid: false);
6767
}

sdk/lib/convert/line_splitter.dart

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,8 @@ const int _CR = 13;
1717
*
1818
* The returned lines do not contain the line terminators.
1919
*/
20-
class LineSplitter extends Converter<String, List<String>> {
20+
class LineSplitter extends
21+
ChunkedConverter<String, List<String>, String, String> {
2122

2223
const LineSplitter();
2324

@@ -79,9 +80,6 @@ class LineSplitter extends Converter<String, List<String>> {
7980
}
8081
return new _LineSplitterSink(sink);
8182
}
82-
83-
// Override the base-class' bind, to provide a better type.
84-
Stream<String> bind(Stream<String> stream) => super.bind(stream);
8583
}
8684

8785
// TODO(floitsch): deal with utf8.

sdk/lib/convert/utf.dart

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,8 @@ class Utf8Codec extends Encoding {
7676
* This class converts strings to their UTF-8 code units (a list of
7777
* unsigned 8-bit integers).
7878
*/
79-
class Utf8Encoder extends Converter<String, List<int>> {
79+
class Utf8Encoder extends
80+
ChunkedConverter<String, List<int>, String, List<int>> {
8081

8182
const Utf8Encoder();
8283

@@ -304,7 +305,8 @@ class _Utf8EncoderSink extends _Utf8Encoder with StringConversionSinkMixin {
304305
* This class converts UTF-8 code units (lists of unsigned 8-bit integers)
305306
* to a string.
306307
*/
307-
class Utf8Decoder extends Converter<List<int>, String> {
308+
class Utf8Decoder extends
309+
ChunkedConverter<List<int>, String, List<int>, String> {
308310
final bool _allowMalformed;
309311

310312
/**

0 commit comments

Comments
 (0)