|  | // Copyright (c) 2012, 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. | 
|  |  | 
|  | import "package:expect/expect.dart"; | 
|  | import 'dart:convert'; | 
|  |  | 
|  | var latin1Strings = ["pure ascii", "blåbærgrød", "\x00 edge cases \xff"]; | 
|  |  | 
|  | var nonLatin1Strings = ["Edge case \u{100}", "Edge case super-BMP \u{10000}"]; | 
|  |  | 
|  | void main() { | 
|  | // Build longer versions of the example strings. | 
|  | for (int i = 0, n = latin1Strings.length; i < n; i++) { | 
|  | var string = latin1Strings[i]; | 
|  | while (string.length < 1024) { | 
|  | string += string; | 
|  | } | 
|  | latin1Strings.add(string); | 
|  | } | 
|  | for (int i = 0, n = nonLatin1Strings.length; i < n; i++) { | 
|  | var string = nonLatin1Strings[i]; | 
|  | while (string.length < 1024) { | 
|  | string += string; | 
|  | } | 
|  | nonLatin1Strings.add(string); | 
|  | } | 
|  | testDirectConversions(); | 
|  | testChunkedConversions(); | 
|  | } | 
|  |  | 
|  | void testDirectConversions() { | 
|  | for (var codec in [latin1, new Latin1Codec()]) { | 
|  | for (var latin1String in latin1Strings) { | 
|  | var bytes = codec.encoder.convert(latin1String); | 
|  | Expect.listEquals(latin1String.codeUnits.toList(), bytes, latin1String); | 
|  | String roundTripString = codec.decoder.convert(bytes); | 
|  | Expect.equals(latin1String, roundTripString); | 
|  | roundTripString = codec.decode(bytes); | 
|  | Expect.equals(latin1String, roundTripString); | 
|  | } | 
|  |  | 
|  | for (var nonLatin1String in nonLatin1Strings) { | 
|  | Expect.throws(() { | 
|  | print(codec.encoder.convert(nonLatin1String)); | 
|  | }, (_) => true, nonLatin1String); | 
|  | } | 
|  |  | 
|  | var encode = codec.encoder.convert; | 
|  | Expect.listEquals([0x42, 0xff, 0x44], encode("AB\xffDE", 1, 4)); | 
|  | Expect.listEquals([0x42, 0xff, 0x44, 0x45], encode("AB\xffDE", 1)); | 
|  | Expect.listEquals([0x42, 0xff, 0x44], encode("\u3000B\xffD\u3000", 1, 4)); | 
|  | Expect.throws(() { | 
|  | encode("\u3000B\xffD\u3000", 0, 4); | 
|  | }); | 
|  | Expect.throws(() { | 
|  | encode("\u3000B\xffD\u3000", 1); | 
|  | }); | 
|  | Expect.throws(() { | 
|  | encode("\u3000B\xffD\u3000", 1, 5); | 
|  | }); | 
|  | Expect.throws(() { | 
|  | encode("\u3000B\xffD\u3000", -1, 4); | 
|  | }); | 
|  | Expect.throws(() { | 
|  | encode("\u3000B\xffD\u3000", 1, -1); | 
|  | }); | 
|  | Expect.throws(() { | 
|  | encode("\u3000B\xffD\u3000", 3, 2); | 
|  | }); | 
|  |  | 
|  | var decode = codec.decoder.convert; | 
|  | Expect.equals("B\xffD", decode([0x41, 0x42, 0xff, 0x44, 0x45], 1, 4)); | 
|  | Expect.equals("B\xffDE", decode([0x41, 0x42, 0xff, 0x44, 0x45], 1)); | 
|  | Expect.equals("B\xffD", decode([0xFF, 0x42, 0xff, 0x44, 0xFF], 1, 4)); | 
|  | Expect.throws(() { | 
|  | decode([0x3000, 0x42, 0xff, 0x44, 0x3000], 0, 4); | 
|  | }); | 
|  | Expect.throws(() { | 
|  | decode([0x3000, 0x42, 0xff, 0x44, 0x3000], 1); | 
|  | }); | 
|  | Expect.throws(() { | 
|  | decode([0x3000, 0x42, 0xff, 0x44, 0x3000], 1, 5); | 
|  | }); | 
|  | Expect.throws(() { | 
|  | decode([0x3000, 0x42, 0xff, 0x44, 0x3000], -1, 4); | 
|  | }); | 
|  | Expect.throws(() { | 
|  | decode([0x3000, 0x42, 0xff, 0x44, 0x3000], 1, -1); | 
|  | }); | 
|  | Expect.throws(() { | 
|  | decode([0x3000, 0x42, 0xff, 0x44, 0x3000], 3, 2); | 
|  | }); | 
|  | } | 
|  |  | 
|  | var allowInvalidCodec = new Latin1Codec(allowInvalid: true); | 
|  | var invalidBytes = [0, 1, 0xff, 0xdead, 0]; | 
|  | String decoded = allowInvalidCodec.decode(invalidBytes); | 
|  | Expect.equals("\x00\x01\xFF\uFFFD\x00", decoded); | 
|  | decoded = allowInvalidCodec.decoder.convert(invalidBytes); | 
|  | Expect.equals("\x00\x01\xFF\uFFFD\x00", decoded); | 
|  | decoded = latin1.decode(invalidBytes, allowInvalid: true); | 
|  | Expect.equals("\x00\x01\xFF\uFFFD\x00", decoded); | 
|  | } | 
|  |  | 
|  | List<int> encode( | 
|  | String str, int chunkSize, Converter<String, List<int>> converter) { | 
|  | List<int> bytes = <int>[]; | 
|  | var byteSink = new ByteConversionSink.withCallback(bytes.addAll); | 
|  | var stringConversionSink = converter.startChunkedConversion(byteSink); | 
|  | for (int i = 0; i < str.length; i += chunkSize) { | 
|  | if (i + chunkSize <= str.length) { | 
|  | stringConversionSink.add(str.substring(i, i + chunkSize)); | 
|  | } else { | 
|  | stringConversionSink.add(str.substring(i)); | 
|  | } | 
|  | } | 
|  | stringConversionSink.close(); | 
|  | return bytes; | 
|  | } | 
|  |  | 
|  | String decode( | 
|  | List<int> bytes, int chunkSize, Converter<List<int>, String> converter) { | 
|  | StringBuffer buf = new StringBuffer(); | 
|  | var stringSink = new StringConversionSink.fromStringSink(buf); | 
|  | var byteConversionSink = converter.startChunkedConversion(stringSink); | 
|  | for (int i = 0; i < bytes.length; i += chunkSize) { | 
|  | if (i + chunkSize <= bytes.length) { | 
|  | byteConversionSink.add(bytes.sublist(i, i + chunkSize)); | 
|  | } else { | 
|  | byteConversionSink.add(bytes.sublist(i)); | 
|  | } | 
|  | } | 
|  | byteConversionSink.close(); | 
|  | return buf.toString(); | 
|  | } | 
|  |  | 
|  | void testChunkedConversions() { | 
|  | // Check encoding. | 
|  | for (var converter in [ | 
|  | latin1.encoder, | 
|  | new Latin1Codec().encoder, | 
|  | new Latin1Encoder() | 
|  | ]) { | 
|  | for (int chunkSize in [1, 2, 5, 50]) { | 
|  | for (var latin1String in latin1Strings) { | 
|  | var units = latin1String.codeUnits.toList(); | 
|  | List bytes = encode(latin1String, chunkSize, converter); | 
|  | Expect.listEquals(units, bytes); | 
|  | } | 
|  | for (var nonLatin1String in nonLatin1Strings) { | 
|  | Expect.throws(() { | 
|  | encode(nonLatin1String, chunkSize, converter); | 
|  | }); | 
|  | } | 
|  | } | 
|  | } | 
|  | // Check decoding. | 
|  | for (var converter in [ | 
|  | latin1.decoder, | 
|  | new Latin1Codec().decoder, | 
|  | new Latin1Decoder() | 
|  | ]) { | 
|  | for (int chunkSize in [1, 2, 5, 50]) { | 
|  | for (var latin1String in latin1Strings) { | 
|  | var units = latin1String.codeUnits.toList(); | 
|  | Expect.equals(latin1String, decode(units, chunkSize, converter)); | 
|  | } | 
|  | for (var nonLatin1String in nonLatin1Strings) { | 
|  | var units = nonLatin1String.codeUnits.toList(); | 
|  | Expect.throws(() { | 
|  | decode(units, chunkSize, converter); | 
|  | }); | 
|  | } | 
|  | } | 
|  | } | 
|  | } |