// 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 encode( String str, int chunkSize, Converter> converter) { List bytes = []; 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 bytes, int chunkSize, Converter, 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); }); } } } }