From ed782b7241caeee741187644991463d277bf52ff Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Tue, 22 Sep 2015 14:44:58 -0700 Subject: [PATCH 001/100] Add template files. --- pkgs/convert/.gitignore | 9 +++++++++ pkgs/convert/.test_config | 3 +++ pkgs/convert/AUTHORS | 6 ++++++ pkgs/convert/CHANGELOG.md | 5 +++++ pkgs/convert/CONTRIBUTING.md | 33 ++++++++++++++++++++++++++++++++ pkgs/convert/LICENSE | 26 +++++++++++++++++++++++++ pkgs/convert/README.md | 9 +++++++++ pkgs/convert/codereview.settings | 3 +++ pkgs/convert/pubspec.yaml | 14 ++++++++++++++ 9 files changed, 108 insertions(+) create mode 100644 pkgs/convert/.gitignore create mode 100644 pkgs/convert/.test_config create mode 100644 pkgs/convert/AUTHORS create mode 100644 pkgs/convert/CHANGELOG.md create mode 100644 pkgs/convert/CONTRIBUTING.md create mode 100644 pkgs/convert/LICENSE create mode 100644 pkgs/convert/README.md create mode 100644 pkgs/convert/codereview.settings create mode 100644 pkgs/convert/pubspec.yaml diff --git a/pkgs/convert/.gitignore b/pkgs/convert/.gitignore new file mode 100644 index 00000000..25a1df33 --- /dev/null +++ b/pkgs/convert/.gitignore @@ -0,0 +1,9 @@ +.buildlog +.DS_Store +.idea +.pub/ +.settings/ +build/ +packages +.packages +pubspec.lock diff --git a/pkgs/convert/.test_config b/pkgs/convert/.test_config new file mode 100644 index 00000000..352d2fee --- /dev/null +++ b/pkgs/convert/.test_config @@ -0,0 +1,3 @@ +{ + "test_package": true +} diff --git a/pkgs/convert/AUTHORS b/pkgs/convert/AUTHORS new file mode 100644 index 00000000..e8063a8c --- /dev/null +++ b/pkgs/convert/AUTHORS @@ -0,0 +1,6 @@ +# Below is a list of people and organizations that have contributed +# to the project. Names should be added to the list like so: +# +# Name/Organization + +Google Inc. diff --git a/pkgs/convert/CHANGELOG.md b/pkgs/convert/CHANGELOG.md new file mode 100644 index 00000000..2a2d63cf --- /dev/null +++ b/pkgs/convert/CHANGELOG.md @@ -0,0 +1,5 @@ +# Changelog + +## 0.0.1 + +- Initial version diff --git a/pkgs/convert/CONTRIBUTING.md b/pkgs/convert/CONTRIBUTING.md new file mode 100644 index 00000000..6f5e0ea6 --- /dev/null +++ b/pkgs/convert/CONTRIBUTING.md @@ -0,0 +1,33 @@ +Want to contribute? Great! First, read this page (including the small print at +the end). + +### Before you contribute +Before we can use your code, you must sign the +[Google Individual Contributor License Agreement](https://cla.developers.google.com/about/google-individual) +(CLA), which you can do online. The CLA is necessary mainly because you own the +copyright to your changes, even after your contribution becomes part of our +codebase, so we need your permission to use and distribute your code. We also +need to be sure of various other things—for instance that you'll tell us if you +know that your code infringes on other people's patents. You don't have to sign +the CLA until after you've submitted your code for review and a member has +approved it, but you must do it before we can put your code into our codebase. + +Before you start working on a larger contribution, you should get in touch with +us first through the issue tracker with your idea so that we can help out and +possibly guide you. Coordinating up front makes it much easier to avoid +frustration later on. + +### Code reviews +All submissions, including submissions by project members, require review. + +### File headers +All files in the project must start with the following header. + + // Copyright (c) 2015, 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. + +### The small print +Contributions made by corporations are covered by a different agreement than the +one above, the +[Software Grant and Corporate Contributor License Agreement](https://developers.google.com/open-source/cla/corporate). diff --git a/pkgs/convert/LICENSE b/pkgs/convert/LICENSE new file mode 100644 index 00000000..de31e1a0 --- /dev/null +++ b/pkgs/convert/LICENSE @@ -0,0 +1,26 @@ +Copyright 2015, the Dart project authors. All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of Google Inc. nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/pkgs/convert/README.md b/pkgs/convert/README.md new file mode 100644 index 00000000..289911be --- /dev/null +++ b/pkgs/convert/README.md @@ -0,0 +1,9 @@ +# sample + +A library for Dart developers. It is awesome. + +## Features and bugs + +Please file feature requests and bugs at the [issue tracker][tracker]. + +[tracker]: https://github.com/dart-lang/sample/issues diff --git a/pkgs/convert/codereview.settings b/pkgs/convert/codereview.settings new file mode 100644 index 00000000..82376363 --- /dev/null +++ b/pkgs/convert/codereview.settings @@ -0,0 +1,3 @@ +CODE_REVIEW_SERVER: http://codereview.chromium.org/ +VIEW_VC: https://github.com/dart-lang/convert/commit/ +CC_LIST: reviews@dartlang.org \ No newline at end of file diff --git a/pkgs/convert/pubspec.yaml b/pkgs/convert/pubspec.yaml new file mode 100644 index 00000000..212a7636 --- /dev/null +++ b/pkgs/convert/pubspec.yaml @@ -0,0 +1,14 @@ +name: sample +version: 0.0.1 +description: A sample library. +author: Dart Team +homepage: https://github.com/dart-lang/sample + +environment: + sdk: '>=1.0.0 <2.0.0' + +#dependencies: +# lib_name: any +dev_dependencies: +# change this to a specific version range when you create your project + test: any From d9d51d045db8cb3874eec4cdc4d7dd465c09f723 Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Tue, 22 Sep 2015 14:49:38 -0700 Subject: [PATCH 002/100] Update the README and pubspec for this package. --- pkgs/convert/README.md | 13 +++++-------- pkgs/convert/pubspec.yaml | 13 +++++-------- 2 files changed, 10 insertions(+), 16 deletions(-) diff --git a/pkgs/convert/README.md b/pkgs/convert/README.md index 289911be..9a832fda 100644 --- a/pkgs/convert/README.md +++ b/pkgs/convert/README.md @@ -1,9 +1,6 @@ -# sample +# Conversion utilities package -A library for Dart developers. It is awesome. - -## Features and bugs - -Please file feature requests and bugs at the [issue tracker][tracker]. - -[tracker]: https://github.com/dart-lang/sample/issues +This package contains encoders and decoders for converting between different +data representations. It's the external counterpart of the `dart:convert` core +library, and contains less-central APIs and APIs that need more flexible +versioning. diff --git a/pkgs/convert/pubspec.yaml b/pkgs/convert/pubspec.yaml index 212a7636..a7b179ce 100644 --- a/pkgs/convert/pubspec.yaml +++ b/pkgs/convert/pubspec.yaml @@ -1,14 +1,11 @@ -name: sample +name: convert version: 0.0.1 -description: A sample library. +description: Utilities for converting between data representations. author: Dart Team -homepage: https://github.com/dart-lang/sample +homepage: https://github.com/dart-lang/convert environment: - sdk: '>=1.0.0 <2.0.0' + sdk: '>=1.8.0 <2.0.0' -#dependencies: -# lib_name: any dev_dependencies: -# change this to a specific version range when you create your project - test: any + test: '^1.12.0' From 0f4f74cd81430c3360b7dea496e175136f6552ac Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Thu, 24 Sep 2015 16:23:07 -0700 Subject: [PATCH 003/100] Add a hexadecimal codec. R=lrn@google.com Review URL: https://codereview.chromium.org//1364613002 . --- pkgs/convert/lib/convert.dart | 7 + pkgs/convert/lib/src/hex.dart | 29 ++++ pkgs/convert/lib/src/hex/decoder.dart | 193 ++++++++++++++++++++++++++ pkgs/convert/lib/src/hex/encoder.dart | 87 ++++++++++++ pkgs/convert/pubspec.yaml | 7 +- pkgs/convert/test/hex_test.dart | 153 ++++++++++++++++++++ 6 files changed, 474 insertions(+), 2 deletions(-) create mode 100644 pkgs/convert/lib/convert.dart create mode 100644 pkgs/convert/lib/src/hex.dart create mode 100644 pkgs/convert/lib/src/hex/decoder.dart create mode 100644 pkgs/convert/lib/src/hex/encoder.dart create mode 100644 pkgs/convert/test/hex_test.dart diff --git a/pkgs/convert/lib/convert.dart b/pkgs/convert/lib/convert.dart new file mode 100644 index 00000000..5b053226 --- /dev/null +++ b/pkgs/convert/lib/convert.dart @@ -0,0 +1,7 @@ +// Copyright (c) 2015, 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. + +library convert; + +export 'src/hex.dart'; diff --git a/pkgs/convert/lib/src/hex.dart b/pkgs/convert/lib/src/hex.dart new file mode 100644 index 00000000..ec4451e4 --- /dev/null +++ b/pkgs/convert/lib/src/hex.dart @@ -0,0 +1,29 @@ +// Copyright (c) 2015, 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. + +library convert.hex; + +import 'dart:convert'; + +import 'hex/encoder.dart'; +import 'hex/decoder.dart'; + +export 'hex/encoder.dart' hide hexEncoder; +export 'hex/decoder.dart' hide hexDecoder; + +/// The canonical instance of [HexCodec]. +const hex = const HexCodec._(); + +/// A codec that converts byte arrays to and from hexadecimal strings, following +/// [the Base16 spec][rfc]. +/// +/// [rfc]: https://tools.ietf.org/html/rfc4648#section-8 +/// +/// This should be used via the [hex] field. +class HexCodec extends Codec, String> { + HexEncoder get encoder => hexEncoder; + HexDecoder get decoder => hexDecoder; + + const HexCodec._(); +} diff --git a/pkgs/convert/lib/src/hex/decoder.dart b/pkgs/convert/lib/src/hex/decoder.dart new file mode 100644 index 00000000..2ba169af --- /dev/null +++ b/pkgs/convert/lib/src/hex/decoder.dart @@ -0,0 +1,193 @@ +// Copyright (c) 2015, 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. + +library convert.hex.decoder; + +import 'dart:convert'; +import 'dart:typed_data'; + +import 'package:charcode/ascii.dart'; + +/// The canonical instance of [HexDecoder]. +const hexDecoder = const HexDecoder._(); + +/// A converter that decodes hexadecimal strings into byte arrays. +/// +/// Because two hexadecimal digits correspond to a single byte, this will throw +/// a [FormatException] if given an odd-length string. It will also throw a +/// [FormatException] if given a string containing non-hexadecimal code units. +class HexDecoder extends Converter> { + const HexDecoder._(); + + List convert(String string) { + if (!string.length.isEven) { + throw new FormatException("Invalid input length, must be even.", + string, string.length); + } + + var bytes = new Uint8List(string.length ~/ 2); + _decode(string.codeUnits, 0, string.length, bytes, 0); + return bytes; + } + + StringConversionSink startChunkedConversion(Sink> sink) => + new _HexDecoderSink(sink); +} + +/// A conversion sink for chunked hexadecimal decoding. +class _HexDecoderSink extends StringConversionSinkBase { + /// The underlying sink to which decoded byte arrays will be passed. + final Sink> _sink; + + /// The trailing digit from the previous string. + /// + /// This will be non-`null` if the most recent string had an odd number of + /// hexadecimal digits. Since it's the most significant digit, it's always a + /// multiple of 16. + int _lastDigit; + + _HexDecoderSink(this._sink); + + void addSlice(String string, int start, int end, bool isLast) { + RangeError.checkValidRange(start, end, string.length); + + if (start == end) { + if (isLast) close(); + return; + } + + var codeUnits = string.codeUnits; + var bytes; + var bytesStart; + if (_lastDigit == null) { + bytes = new Uint8List((end - start) ~/ 2); + bytesStart = 0; + } else { + var hexPairs = (end - start - 1) ~/ 2; + bytes = new Uint8List(1 + hexPairs); + bytes[0] = _lastDigit + _digitForCodeUnit(codeUnits, start); + start++; + bytesStart = 1; + } + + _lastDigit = _decode(codeUnits, start, end, bytes, bytesStart); + + _sink.add(bytes); + if (isLast) close(); + } + + ByteConversionSink asUtf8Sink(bool allowMalformed) => + new _HexDecoderByteSink(_sink); + + void close() { + if (_lastDigit != null) { + throw new FormatException("Invalid input length, must be even."); + } + + _sink.close(); + } +} + +/// A conversion sink for chunked hexadecimal decoding from UTF-8 bytes. +class _HexDecoderByteSink extends ByteConversionSinkBase { + /// The underlying sink to which decoded byte arrays will be passed. + final Sink> _sink; + + /// The trailing digit from the previous string. + /// + /// This will be non-`null` if the most recent string had an odd number of + /// hexadecimal digits. Since it's the most significant digit, it's always a + /// multiple of 16. + int _lastDigit; + + _HexDecoderByteSink(this._sink); + + void add(List chunk) => addSlice(chunk, 0, chunk.length, false); + + void addSlice(List chunk, int start, int end, bool isLast) { + RangeError.checkValidRange(start, end, chunk.length); + + if (start == end) { + if (isLast) close(); + return; + } + + var bytes; + var bytesStart; + if (_lastDigit == null) { + bytes = new Uint8List((end - start) ~/ 2); + bytesStart = 0; + } else { + var hexPairs = (end - start - 1) ~/ 2; + bytes = new Uint8List(1 + hexPairs); + bytes[0] = _lastDigit + _digitForCodeUnit(chunk, start); + start++; + bytesStart = 1; + } + + _lastDigit = _decode(chunk, start, end, bytes, bytesStart); + + _sink.add(bytes); + if (isLast) close(); + } + + void close() { + if (_lastDigit != null) { + throw new FormatException("Invalid input length, must be even."); + } + + _sink.close(); + } +} + +/// Decodes [codeUnits] and writes the result into [destination]. +/// +/// This reads from [codeUnits] between [sourceStart] and [sourceEnd]. It writes +/// the result into [destination] starting at [destinationStart]. +/// +/// If there's a leftover digit at the end of the decoding, this returns that +/// digit. Otherwise it returns `null`. +int _decode(List codeUnits, int sourceStart, int sourceEnd, + List destination, int destinationStart) { + var destinationIndex = destinationStart; + for (var i = sourceStart; i < sourceEnd - 1; i += 2) { + var firstDigit = _digitForCodeUnit(codeUnits, i); + var secondDigit = _digitForCodeUnit(codeUnits, i + 1); + destination[destinationIndex++] = 16 * firstDigit + secondDigit; + } + + if ((sourceEnd - sourceStart).isEven) return null; + return 16 * _digitForCodeUnit(codeUnits, sourceEnd - 1); +} + +/// Returns the digit (0 through 15) corresponding to the hexadecimal code unit +/// at index [i] in [codeUnits]. +/// +/// If the given code unit isn't valid hexadecimal, throws a [FormatException]. +int _digitForCodeUnit(List codeUnits, int index) { + // If the code unit is a numeral, get its value. XOR works because 0 in ASCII + // is `0b110000` and the other numerals come after it in ascending order and + // take up at most four bits. + // + // We check for digits first because it ensures there's only a single branch + // for 10 out of 16 of the expected cases. We don't count the `digit >= 0` + // check because branch prediction will always work on it for valid data. + var codeUnit = codeUnits[index]; + var digit = $0 ^ codeUnit; + if (digit <= 9) { + if (digit >= 0) return digit; + } else { + // If the code unit is an uppercase letter, convert it to lowercase. This + // works because uppercase letters in ASCII are exactly `0b100000 = 0x20` + // less than lowercase letters, so if we ensure that that bit is 1 we ensure + // that the letter is lowercase. + var letter = 0x20 | codeUnit; + if ($a <= letter && letter <= $f) return letter - $a + 10; + } + + throw new FormatException( + "Invalid hexadecimal code unit " + "U+${codeUnit.toRadixString(16).padLeft(4, '0')}.", + codeUnits, index); +} diff --git a/pkgs/convert/lib/src/hex/encoder.dart b/pkgs/convert/lib/src/hex/encoder.dart new file mode 100644 index 00000000..7a974e3d --- /dev/null +++ b/pkgs/convert/lib/src/hex/encoder.dart @@ -0,0 +1,87 @@ +// Copyright (c) 2015, 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. + +library convert.hex.encoder; + +import 'dart:convert'; +import 'dart:typed_data'; + +import 'package:charcode/ascii.dart'; + +/// The canonical instance of [HexEncoder]. +const hexEncoder = const HexEncoder._(); + +/// A converter that encodes byte arrays into hexadecimal strings. +/// +/// This will throw a [RangeError] if the byte array has any digits that don't +/// fit in the gamut of a byte. +class HexEncoder extends Converter, String> { + const HexEncoder._(); + + String convert(List bytes) => _convert(bytes, 0, bytes.length); + + ByteConversionSink startChunkedConversion(Sink sink) => + new _HexEncoderSink(sink); +} + +/// A conversion sink for chunked hexadecimal encoding. +class _HexEncoderSink extends ByteConversionSinkBase { + /// The underlying sink to which decoded byte arrays will be passed. + final Sink _sink; + + _HexEncoderSink(this._sink); + + void add(List chunk) { + _sink.add(_convert(chunk, 0, chunk.length)); + } + + void addSlice(List chunk, int start, int end, bool isLast) { + RangeError.checkValidRange(start, end, chunk.length); + _sink.add(_convert(chunk, start, end)); + if (isLast) _sink.close(); + } + + void close() { + _sink.close(); + } +} + +String _convert(List bytes, int start, int end) { + // A Uint8List is more efficient than a StringBuffer given that we know that + // we're only emitting ASCII-compatible characters, and that we know the + // length ahead of time. + var buffer = new Uint8List((end - start) * 2); + var bufferIndex = 0; + + // A bitwise OR of all bytes in [bytes]. This allows us to check for + // out-of-range bytes without adding more branches than necessary to the + // core loop. + var byteOr = 0; + for (var i = start; i < end; i++) { + var byte = bytes[i]; + byteOr |= byte; + + // The bitwise arithmetic here is equivalent to `byte ~/ 16` and `byte % 16` + // for valid byte values, but is easier for dart2js to optimize given that + // it can't prove that [byte] will always be positive. + buffer[bufferIndex++] = _codeUnitForDigit((byte & 0xF0) >> 4); + buffer[bufferIndex++] = _codeUnitForDigit(byte & 0x0F); + } + + if (byteOr >= 0 && byteOr <= 255) return new String.fromCharCodes(buffer); + + // If there was an invalid byte, find it and throw an exception. + for (var i = start; i < end; i++) { + var byte = bytes[i]; + if (byte >= 0 && byte <= 0xff) continue; + throw new FormatException("Invalid byte 0x${byte.toRadixString(16)}.", + bytes, i); + } + + throw 'unreachable'; +} + +/// Returns the ASCII/Unicode code unit corresponding to the hexadecimal digit +/// [digit]. +int _codeUnitForDigit(int digit) => digit < 10 ? digit + $0 : digit + $a - 10; diff --git a/pkgs/convert/pubspec.yaml b/pkgs/convert/pubspec.yaml index a7b179ce..db13edff 100644 --- a/pkgs/convert/pubspec.yaml +++ b/pkgs/convert/pubspec.yaml @@ -1,5 +1,5 @@ name: convert -version: 0.0.1 +version: 0.0.1-dev description: Utilities for converting between data representations. author: Dart Team homepage: https://github.com/dart-lang/convert @@ -7,5 +7,8 @@ homepage: https://github.com/dart-lang/convert environment: sdk: '>=1.8.0 <2.0.0' +dependencies: + charcode: '^1.1.0' + dev_dependencies: - test: '^1.12.0' + test: '^0.12.0' diff --git a/pkgs/convert/test/hex_test.dart b/pkgs/convert/test/hex_test.dart new file mode 100644 index 00000000..f52edaf2 --- /dev/null +++ b/pkgs/convert/test/hex_test.dart @@ -0,0 +1,153 @@ +// Copyright (c) 2015, 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 'dart:async'; + +import 'package:convert/convert.dart'; +import 'package:test/test.dart'; + +void main() { + group("encoder", () { + test("converts byte arrays to hex", () { + expect(hex.encode([0x1a, 0xb2, 0x3c, 0xd4]), equals("1ab23cd4")); + expect(hex.encode([0x00, 0x01, 0xfe, 0xff]), equals("0001feff")); + }); + + group("with chunked conversion", () { + test("converts byte arrays to hex", () { + var results = []; + var controller = new StreamController(sync: true); + controller.stream.listen(results.add); + var sink = hex.encoder.startChunkedConversion(controller.sink); + + sink.add([0x1a, 0xb2, 0x3c, 0xd4]); + expect(results, equals(["1ab23cd4"])); + + sink.add([0x00, 0x01, 0xfe, 0xff]); + expect(results, equals(["1ab23cd4", "0001feff"])); + }); + + test("handles empty and single-byte lists", () { + var results = []; + var controller = new StreamController(sync: true); + controller.stream.listen(results.add); + var sink = hex.encoder.startChunkedConversion(controller.sink); + + sink.add([]); + expect(results, equals([""])); + + sink.add([0x00]); + expect(results, equals(["", "00"])); + + sink.add([]); + expect(results, equals(["", "00", ""])); + }); + }); + + test("rejects non-bytes", () { + expect(() => hex.encode([0x100]), throwsFormatException); + + var sink = hex.encoder.startChunkedConversion( + new StreamController(sync: true)); + expect(() => sink.add([0x100]), throwsFormatException); + }); + }); + + group("decoder", () { + test("converts hex to byte arrays", () { + expect(hex.decode("1ab23cd4"), equals([0x1a, 0xb2, 0x3c, 0xd4])); + expect(hex.decode("0001feff"), equals([0x00, 0x01, 0xfe, 0xff])); + }); + + test("supports uppercase letters", () { + expect(hex.decode("0123456789ABCDEFabcdef"), equals([ + 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0xab, 0xcd, 0xef + ])); + }); + + group("with chunked conversion", () { + var results; + var sink; + setUp(() { + results = []; + var controller = new StreamController(sync: true); + controller.stream.listen(results.add); + sink = hex.decoder.startChunkedConversion(controller.sink); + }); + + test("converts hex to byte arrays", () { + sink.add("1ab23cd4"); + expect(results, equals([[0x1a, 0xb2, 0x3c, 0xd4]])); + + sink.add("0001feff"); + expect(results, + equals([[0x1a, 0xb2, 0x3c, 0xd4], [0x00, 0x01, 0xfe, 0xff]])); + }); + + test("supports trailing digits split across chunks", () { + sink.add("1ab23"); + expect(results, equals([[0x1a, 0xb2]])); + + sink.add("cd"); + expect(results, equals([[0x1a, 0xb2], [0x3c]])); + + sink.add("40001"); + expect(results, equals([[0x1a, 0xb2], [0x3c], [0xd4, 0x00, 0x01]])); + + sink.add("feff"); + expect(results, + equals([[0x1a, 0xb2], [0x3c], [0xd4, 0x00, 0x01], [0xfe, 0xff]])); + }); + + test("supports empty strings", () { + sink.add(""); + expect(results, isEmpty); + + sink.add("0"); + expect(results, equals([[]])); + + sink.add(""); + expect(results, equals([[]])); + + sink.add("0"); + expect(results, equals([[], [0x00]])); + + sink.add(""); + expect(results, equals([[], [0x00]])); + }); + + test("rejects odd length detected in close()", () { + sink.add("1ab23"); + expect(results, equals([[0x1a, 0xb2]])); + expect(() => sink.close(), throwsFormatException); + }); + + test("rejects odd length detected in addSlice()", () { + sink.addSlice("1ab23cd", 0, 5, false); + expect(results, equals([[0x1a, 0xb2]])); + + expect(() => sink.addSlice("1ab23cd", 5, 7, true), + throwsFormatException); + }); + }); + + group("rejects non-hex character", () { + for (var char in + ["g", "G", "/", ":", "@", "`", "\x00", "\u0141", "\u{10041}"]) { + test('"$char"', () { + expect(() => hex.decode("a$char"), throwsFormatException); + expect(() => hex.decode("${char}a"), throwsFormatException); + + var sink = hex.decoder.startChunkedConversion( + new StreamController(sync: true)); + expect(() => sink.add(char), throwsFormatException); + }); + } + }); + + test("rejects odd length detected in convert()", () { + expect(() => hex.decode("1ab23cd"), throwsFormatException); + }); + }); +} From 2ea7048f0606e9c2446833fa7bae619c432ad3ed Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Thu, 8 Oct 2015 13:45:01 -0700 Subject: [PATCH 004/100] Add a percent-encoding converter. This is useful for percent-encoding binary or streaming data. R=lrn@google.com Review URL: https://codereview.chromium.org//1393003003 . --- pkgs/convert/CHANGELOG.md | 2 +- pkgs/convert/lib/convert.dart | 1 + pkgs/convert/lib/src/hex/decoder.dart | 69 +++--- pkgs/convert/lib/src/hex/encoder.dart | 3 +- pkgs/convert/lib/src/percent.dart | 38 ++++ pkgs/convert/lib/src/percent/decoder.dart | 244 ++++++++++++++++++++++ pkgs/convert/lib/src/percent/encoder.dart | 104 +++++++++ pkgs/convert/lib/src/utils.dart | 39 ++++ pkgs/convert/pubspec.yaml | 3 +- pkgs/convert/test/percent_test.dart | 208 ++++++++++++++++++ 10 files changed, 663 insertions(+), 48 deletions(-) create mode 100644 pkgs/convert/lib/src/percent.dart create mode 100644 pkgs/convert/lib/src/percent/decoder.dart create mode 100644 pkgs/convert/lib/src/percent/encoder.dart create mode 100644 pkgs/convert/lib/src/utils.dart create mode 100644 pkgs/convert/test/percent_test.dart diff --git a/pkgs/convert/CHANGELOG.md b/pkgs/convert/CHANGELOG.md index 2a2d63cf..dd213b1e 100644 --- a/pkgs/convert/CHANGELOG.md +++ b/pkgs/convert/CHANGELOG.md @@ -1,5 +1,5 @@ # Changelog -## 0.0.1 +## 1.0.0 - Initial version diff --git a/pkgs/convert/lib/convert.dart b/pkgs/convert/lib/convert.dart index 5b053226..50b02967 100644 --- a/pkgs/convert/lib/convert.dart +++ b/pkgs/convert/lib/convert.dart @@ -5,3 +5,4 @@ library convert; export 'src/hex.dart'; +export 'src/percent.dart'; diff --git a/pkgs/convert/lib/src/hex/decoder.dart b/pkgs/convert/lib/src/hex/decoder.dart index 2ba169af..efb0b0d4 100644 --- a/pkgs/convert/lib/src/hex/decoder.dart +++ b/pkgs/convert/lib/src/hex/decoder.dart @@ -7,7 +7,7 @@ library convert.hex.decoder; import 'dart:convert'; import 'dart:typed_data'; -import 'package:charcode/ascii.dart'; +import '../utils.dart'; /// The canonical instance of [HexDecoder]. const hexDecoder = const HexDecoder._(); @@ -53,7 +53,7 @@ class _HexDecoderSink extends StringConversionSinkBase { RangeError.checkValidRange(start, end, string.length); if (start == end) { - if (isLast) close(); + if (isLast) _close(string, end); return; } @@ -66,7 +66,7 @@ class _HexDecoderSink extends StringConversionSinkBase { } else { var hexPairs = (end - start - 1) ~/ 2; bytes = new Uint8List(1 + hexPairs); - bytes[0] = _lastDigit + _digitForCodeUnit(codeUnits, start); + bytes[0] = _lastDigit + digitForCodeUnit(codeUnits, start); start++; bytesStart = 1; } @@ -74,15 +74,20 @@ class _HexDecoderSink extends StringConversionSinkBase { _lastDigit = _decode(codeUnits, start, end, bytes, bytesStart); _sink.add(bytes); - if (isLast) close(); + if (isLast) _close(string, end); } ByteConversionSink asUtf8Sink(bool allowMalformed) => new _HexDecoderByteSink(_sink); - void close() { + void close() => _close(); + + /// Like [close], but includes [string] and [index] in the [FormatException] + /// if one is thrown. + void _close([String string, int index]) { if (_lastDigit != null) { - throw new FormatException("Invalid input length, must be even."); + throw new FormatException( + "Input ended with incomplete encoded byte.", string, index); } _sink.close(); @@ -109,7 +114,7 @@ class _HexDecoderByteSink extends ByteConversionSinkBase { RangeError.checkValidRange(start, end, chunk.length); if (start == end) { - if (isLast) close(); + if (isLast) _close(chunk, end); return; } @@ -121,7 +126,7 @@ class _HexDecoderByteSink extends ByteConversionSinkBase { } else { var hexPairs = (end - start - 1) ~/ 2; bytes = new Uint8List(1 + hexPairs); - bytes[0] = _lastDigit + _digitForCodeUnit(chunk, start); + bytes[0] = _lastDigit + digitForCodeUnit(chunk, start); start++; bytesStart = 1; } @@ -129,12 +134,17 @@ class _HexDecoderByteSink extends ByteConversionSinkBase { _lastDigit = _decode(chunk, start, end, bytes, bytesStart); _sink.add(bytes); - if (isLast) close(); + if (isLast) _close(chunk, end); } - void close() { + void close() => _close(); + + /// Like [close], but includes [chunk] and [index] in the [FormatException] + /// if one is thrown. + void _close([List chunk, int index]) { if (_lastDigit != null) { - throw new FormatException("Invalid input length, must be even."); + throw new FormatException( + "Input ended with incomplete encoded byte.", chunk, index); } _sink.close(); @@ -152,42 +162,11 @@ int _decode(List codeUnits, int sourceStart, int sourceEnd, List destination, int destinationStart) { var destinationIndex = destinationStart; for (var i = sourceStart; i < sourceEnd - 1; i += 2) { - var firstDigit = _digitForCodeUnit(codeUnits, i); - var secondDigit = _digitForCodeUnit(codeUnits, i + 1); + var firstDigit = digitForCodeUnit(codeUnits, i); + var secondDigit = digitForCodeUnit(codeUnits, i + 1); destination[destinationIndex++] = 16 * firstDigit + secondDigit; } if ((sourceEnd - sourceStart).isEven) return null; - return 16 * _digitForCodeUnit(codeUnits, sourceEnd - 1); -} - -/// Returns the digit (0 through 15) corresponding to the hexadecimal code unit -/// at index [i] in [codeUnits]. -/// -/// If the given code unit isn't valid hexadecimal, throws a [FormatException]. -int _digitForCodeUnit(List codeUnits, int index) { - // If the code unit is a numeral, get its value. XOR works because 0 in ASCII - // is `0b110000` and the other numerals come after it in ascending order and - // take up at most four bits. - // - // We check for digits first because it ensures there's only a single branch - // for 10 out of 16 of the expected cases. We don't count the `digit >= 0` - // check because branch prediction will always work on it for valid data. - var codeUnit = codeUnits[index]; - var digit = $0 ^ codeUnit; - if (digit <= 9) { - if (digit >= 0) return digit; - } else { - // If the code unit is an uppercase letter, convert it to lowercase. This - // works because uppercase letters in ASCII are exactly `0b100000 = 0x20` - // less than lowercase letters, so if we ensure that that bit is 1 we ensure - // that the letter is lowercase. - var letter = 0x20 | codeUnit; - if ($a <= letter && letter <= $f) return letter - $a + 10; - } - - throw new FormatException( - "Invalid hexadecimal code unit " - "U+${codeUnit.toRadixString(16).padLeft(4, '0')}.", - codeUnits, index); + return 16 * digitForCodeUnit(codeUnits, sourceEnd - 1); } diff --git a/pkgs/convert/lib/src/hex/encoder.dart b/pkgs/convert/lib/src/hex/encoder.dart index 7a974e3d..a9c66a5a 100644 --- a/pkgs/convert/lib/src/hex/encoder.dart +++ b/pkgs/convert/lib/src/hex/encoder.dart @@ -75,7 +75,8 @@ String _convert(List bytes, int start, int end) { for (var i = start; i < end; i++) { var byte = bytes[i]; if (byte >= 0 && byte <= 0xff) continue; - throw new FormatException("Invalid byte 0x${byte.toRadixString(16)}.", + throw new FormatException( + "Invalid byte ${byte < 0 ? "-" : ""}0x${byte.abs().toRadixString(16)}.", bytes, i); } diff --git a/pkgs/convert/lib/src/percent.dart b/pkgs/convert/lib/src/percent.dart new file mode 100644 index 00000000..3bb3da14 --- /dev/null +++ b/pkgs/convert/lib/src/percent.dart @@ -0,0 +1,38 @@ +// Copyright (c) 2015, 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. + +library convert.percent; + +import 'dart:convert'; + +import 'percent/encoder.dart'; +import 'percent/decoder.dart'; + +export 'percent/encoder.dart' hide percentEncoder; +export 'percent/decoder.dart' hide percentDecoder; + +/// The canonical instance of [PercentCodec]. +const percent = const PercentCodec._(); + +// TODO(nweiz): Add flags to support generating and interpreting "+" as a space +// character. Also add an option for custom sets of unreserved characters. +/// A codec that converts byte arrays to and from percent-encoded (also known as +/// URL-encoded) strings according to [RFC 3986][rfc]. +/// +/// [rfc]: https://tools.ietf.org/html/rfc3986#section-2.1 +/// +/// [encoder] encodes all bytes other than ASCII letters, decimal digits, or one +/// of `-._~`. This matches the behavior of [Uri.encodeQueryComponent] except +/// that it doesn't encode `0x20` bytes to the `+` character. +/// +/// To be maximally flexible, [decoder] will decode any percent-encoded byte and +/// will allow any non-percent-encoded byte other than `%`. By default, it +/// interprets `+` as `0x2B` rather than `0x20` as emitted by +/// [Uri.encodeQueryComponent]. +class PercentCodec extends Codec, String> { + PercentEncoder get encoder => percentEncoder; + PercentDecoder get decoder => percentDecoder; + + const PercentCodec._(); +} diff --git a/pkgs/convert/lib/src/percent/decoder.dart b/pkgs/convert/lib/src/percent/decoder.dart new file mode 100644 index 00000000..07406361 --- /dev/null +++ b/pkgs/convert/lib/src/percent/decoder.dart @@ -0,0 +1,244 @@ +// Copyright (c) 2015, 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. + +library convert.percent.decoder; + +import 'dart:convert'; + +import 'package:charcode/ascii.dart'; +import 'package:typed_data/typed_data.dart'; + +import '../utils.dart'; + +/// The canonical instance of [PercentDecoder]. +const percentDecoder = const PercentDecoder._(); + +const _lastPercent = -1; + +/// A converter that decodes percent-encoded strings into byte arrays. +/// +/// To be maximally flexible, this will decode any percent-encoded byte and +/// will allow any non-percent-encoded byte other than `%`. By default, it +/// interprets `+` as `0x2B` rather than `0x20` as emitted by +/// [Uri.encodeQueryComponent]. +/// +/// This will throw a [FormatException] if the input string has an incomplete +/// percent-encoding, or if it contains non-ASCII code units. +class PercentDecoder extends Converter> { + const PercentDecoder._(); + + List convert(String string) { + var buffer = new Uint8Buffer(); + var lastDigit = _decode(string.codeUnits, 0, string.length, buffer); + + if (lastDigit != null) { + throw new FormatException( + "Input ended with incomplete encoded byte.", + string, string.length); + } + + return buffer.buffer.asUint8List(0, buffer.length); + } + + StringConversionSink startChunkedConversion(Sink> sink) => + new _PercentDecoderSink(sink); +} + +/// A conversion sink for chunked percent-encoded decoding. +class _PercentDecoderSink extends StringConversionSinkBase { + /// The underlying sink to which decoded byte arrays will be passed. + final Sink> _sink; + + /// The trailing digit from the previous string. + /// + /// This is `null` if the previous string ended with a complete + /// percent-encoded byte or a literal character. It's [_lastPercent] if the + /// most recent string ended with `%`. Otherwise, the most recent string ended + /// with a `%` followed by a hexadecimal digit, and this is that digit. Since + /// it's the most significant digit, it's always a multiple of 16. + int _lastDigit; + + _PercentDecoderSink(this._sink); + + void addSlice(String string, int start, int end, bool isLast) { + RangeError.checkValidRange(start, end, string.length); + + if (start == end) { + if (isLast) _close(string, end); + return; + } + + var buffer = new Uint8Buffer(); + var codeUnits = string.codeUnits; + if (_lastDigit == _lastPercent) { + _lastDigit = 16 * digitForCodeUnit(codeUnits, start); + start++; + + if (start == end) { + if (isLast) _close(string, end); + return; + } + } + + if (_lastDigit != null) { + buffer.add(_lastDigit + digitForCodeUnit(codeUnits, start)); + start++; + } + + _lastDigit = _decode(codeUnits, start, end, buffer); + + _sink.add(buffer.buffer.asUint8List(0, buffer.length)); + if (isLast) _close(string, end); + } + + ByteConversionSink asUtf8Sink(bool allowMalformed) => + new _PercentDecoderByteSink(_sink); + + void close() => _close(); + + /// Like [close], but includes [string] and [index] in the [FormatException] + /// if one is thrown. + void _close([String string, int index]) { + if (_lastDigit != null) { + throw new FormatException( + "Input ended with incomplete encoded byte.", string, index); + } + + _sink.close(); + } +} + +/// A conversion sink for chunked percent-encoded decoding from UTF-8 bytes. +class _PercentDecoderByteSink extends ByteConversionSinkBase { + /// The underlying sink to which decoded byte arrays will be passed. + final Sink> _sink; + + /// The trailing digit from the previous string. + /// + /// This is `null` if the previous string ended with a complete + /// percent-encoded byte or a literal character. It's [_lastPercent] if the + /// most recent string ended with `%`. Otherwise, the most recent string ended + /// with a `%` followed by a hexadecimal digit, and this is that digit. Since + /// it's the most significant digit, it's always a multiple of 16. + int _lastDigit; + + _PercentDecoderByteSink(this._sink); + + void add(List chunk) => addSlice(chunk, 0, chunk.length, false); + + void addSlice(List chunk, int start, int end, bool isLast) { + RangeError.checkValidRange(start, end, chunk.length); + + if (start == end) { + if (isLast) _close(chunk, end); + return; + } + + var buffer = new Uint8Buffer(); + if (_lastDigit == _lastPercent) { + _lastDigit = 16 * digitForCodeUnit(chunk, start); + start++; + + if (start == end) { + if (isLast) _close(chunk, end); + return; + } + } + + if (_lastDigit != null) { + buffer.add(_lastDigit + digitForCodeUnit(chunk, start)); + start++; + } + + _lastDigit = _decode(chunk, start, end, buffer); + + _sink.add(buffer.buffer.asUint8List(0, buffer.length)); + if (isLast) _close(chunk, end); + } + + void close() => _close(); + + /// Like [close], but includes [chunk] and [index] in the [FormatException] + /// if one is thrown. + void _close([List chunk, int index]) { + if (_lastDigit != null) { + throw new FormatException( + "Input ended with incomplete encoded byte.", chunk, index); + } + + _sink.close(); + } +} + +/// Decodes [codeUnits] and writes the result into [destination]. +/// +/// This reads from [codeUnits] between [sourceStart] and [sourceEnd]. It writes +/// the result into [destination] starting at [destinationStart]. +/// +/// If there's a leftover digit at the end of the decoding, this returns that +/// digit. Otherwise it returns `null`. +int _decode(List codeUnits, int start, int end, Uint8Buffer buffer) { + // A bitwise OR of all code units in [codeUnits]. This allows us to check for + // out-of-range code units without adding more branches than necessary to the + // core loop. + var codeUnitOr = 0; + + // The beginning of the current slice of adjacent non-% characters. We can add + // all of these to the buffer at once. + var sliceStart = start; + for (var i = start; i < end; i++) { + // First, loop through non-% characters. + var codeUnit = codeUnits[i]; + if (codeUnits[i] != $percent) { + codeUnitOr |= codeUnit; + continue; + } + + // We found a %. The slice from `sliceStart` to `i` represents characters + // than can be copied to the buffer as-is. + if (i > sliceStart) { + _checkForInvalidCodeUnit(codeUnitOr, codeUnits, sliceStart, i); + buffer.addAll(codeUnits.getRange(sliceStart, i)); + } + + // Now decode the percent-encoded byte and add it as well. + i++; + if (i >= end) return _lastPercent; + + var firstDigit = digitForCodeUnit(codeUnits, i); + i++; + if (i >= end) return 16 * firstDigit; + + var secondDigit = digitForCodeUnit(codeUnits, i); + buffer.add(16 * firstDigit + secondDigit); + + // The next iteration will look for non-% characters again. + sliceStart = i + 1; + } + + if (end > sliceStart) { + _checkForInvalidCodeUnit(codeUnitOr, codeUnits, sliceStart, end); + if (start == sliceStart) { + buffer.addAll(codeUnits); + } else { + buffer.addAll(codeUnits.getRange(sliceStart, end)); + } + } + + return null; +} + +void _checkForInvalidCodeUnit(int codeUnitOr, List codeUnits, int start, + int end) { + if (codeUnitOr >= 0 && codeUnitOr <= 0x7f) return; + + for (var i = start; i < end; i++) { + var codeUnit = codeUnits[i]; + if (codeUnit >= 0 && codeUnit <= 0x7f) continue; + throw new FormatException( + "Non-ASCII code unit " + "U+${codeUnit.toRadixString(16).padLeft(4, '0')}", + codeUnits, i); + } +} diff --git a/pkgs/convert/lib/src/percent/encoder.dart b/pkgs/convert/lib/src/percent/encoder.dart new file mode 100644 index 00000000..c7817609 --- /dev/null +++ b/pkgs/convert/lib/src/percent/encoder.dart @@ -0,0 +1,104 @@ +// Copyright (c) 2015, 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. + +library convert.percent.encoder; + +import 'dart:convert'; + +import 'package:charcode/ascii.dart'; + +/// The canonical instance of [PercentEncoder]. +const percentEncoder = const PercentEncoder._(); + +/// A converter that encodes byte arrays into percent-encoded strings. +/// +/// [encoder] encodes all bytes other than ASCII letters, decimal digits, or one +/// of `-._~`. This matches the behavior of [Uri.encodeQueryComponent] except +/// that it doesn't encode `0x20` bytes to the `+` character. +/// +/// This will throw a [RangeError] if the byte array has any digits that don't +/// fit in the gamut of a byte. +class PercentEncoder extends Converter, String> { + const PercentEncoder._(); + + String convert(List bytes) => _convert(bytes, 0, bytes.length); + + ByteConversionSink startChunkedConversion(Sink sink) => + new _PercentEncoderSink(sink); +} + +/// A conversion sink for chunked percentadecimal encoding. +class _PercentEncoderSink extends ByteConversionSinkBase { + /// The underlying sink to which decoded byte arrays will be passed. + final Sink _sink; + + _PercentEncoderSink(this._sink); + + void add(List chunk) { + _sink.add(_convert(chunk, 0, chunk.length)); + } + + void addSlice(List chunk, int start, int end, bool isLast) { + RangeError.checkValidRange(start, end, chunk.length); + _sink.add(_convert(chunk, start, end)); + if (isLast) _sink.close(); + } + + void close() { + _sink.close(); + } +} + +String _convert(List bytes, int start, int end) { + var buffer = new StringBuffer(); + + // A bitwise OR of all bytes in [bytes]. This allows us to check for + // out-of-range bytes without adding more branches than necessary to the + // core loop. + var byteOr = 0; + for (var i = start; i < end; i++) { + var byte = bytes[i]; + byteOr |= byte; + + // If the byte is an uppercase letter, convert it to lowercase to check if + // it's unreserved. This works because uppercase letters in ASCII are + // exactly `0b100000 = 0x20` less than lowercase letters, so if we ensure + // that that bit is 1 we ensure that the letter is lowercase. + var letter = 0x20 | byte; + if ((letter >= $a && letter <= $z) || + byte == $dash || + byte == $dot || + byte == $underscore || + byte == $tilde) { + // Unreserved characters are safe to write as-is. + buffer.writeCharCode(byte); + continue; + } + + buffer.writeCharCode($percent); + + // The bitwise arithmetic here is equivalent to `byte ~/ 16` and `byte % 16` + // for valid byte values, but is easier for dart2js to optimize given that + // it can't prove that [byte] will always be positive. + buffer.writeCharCode(_codeUnitForDigit((byte & 0xF0) >> 4)); + buffer.writeCharCode(_codeUnitForDigit(byte & 0x0F)); + } + + if (byteOr >= 0 && byteOr <= 255) return buffer.toString(); + + // If there was an invalid byte, find it and throw an exception. + for (var i = start; i < end; i++) { + var byte = bytes[i]; + if (byte >= 0 && byte <= 0xff) continue; + throw new FormatException( + "Invalid byte ${byte < 0 ? "-" : ""}0x${byte.abs().toRadixString(16)}.", + bytes, i); + } + + throw 'unreachable'; +} + +/// Returns the ASCII/Unicode code unit corresponding to the hexadecimal digit +/// [digit]. +int _codeUnitForDigit(int digit) => digit < 10 ? digit + $0 : digit + $A - 10; diff --git a/pkgs/convert/lib/src/utils.dart b/pkgs/convert/lib/src/utils.dart new file mode 100644 index 00000000..6bd44689 --- /dev/null +++ b/pkgs/convert/lib/src/utils.dart @@ -0,0 +1,39 @@ +// Copyright (c) 2015, 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. + +library convert.utils; + +import 'package:charcode/ascii.dart'; + +/// Returns the digit (0 through 15) corresponding to the hexadecimal code unit +/// at index [i] in [codeUnits]. +/// +/// If the given code unit isn't valid hexadecimal, throws a [FormatException]. +int digitForCodeUnit(List codeUnits, int index) { + // If the code unit is a numeral, get its value. XOR works because 0 in ASCII + // is `0b110000` and the other numerals come after it in ascending order and + // take up at most four bits. + // + // We check for digits first because it ensures there's only a single branch + // for 10 out of 16 of the expected cases. We don't count the `digit >= 0` + // check because branch prediction will always work on it for valid data. + var codeUnit = codeUnits[index]; + var digit = $0 ^ codeUnit; + if (digit <= 9) { + if (digit >= 0) return digit; + } else { + // If the code unit is an uppercase letter, convert it to lowercase. This + // works because uppercase letters in ASCII are exactly `0b100000 = 0x20` + // less than lowercase letters, so if we ensure that that bit is 1 we ensure + // that the letter is lowercase. + var letter = 0x20 | codeUnit; + if ($a <= letter && letter <= $f) return letter - $a + 10; + } + + throw new FormatException( + "Invalid hexadecimal code unit " + "U+${codeUnit.toRadixString(16).padLeft(4, '0')}.", + codeUnits, index); +} + diff --git a/pkgs/convert/pubspec.yaml b/pkgs/convert/pubspec.yaml index db13edff..48ef1407 100644 --- a/pkgs/convert/pubspec.yaml +++ b/pkgs/convert/pubspec.yaml @@ -1,5 +1,5 @@ name: convert -version: 0.0.1-dev +version: 1.0.0 description: Utilities for converting between data representations. author: Dart Team homepage: https://github.com/dart-lang/convert @@ -9,6 +9,7 @@ environment: dependencies: charcode: '^1.1.0' + typed_data: '^1.0.0' dev_dependencies: test: '^0.12.0' diff --git a/pkgs/convert/test/percent_test.dart b/pkgs/convert/test/percent_test.dart new file mode 100644 index 00000000..f7a1c489 --- /dev/null +++ b/pkgs/convert/test/percent_test.dart @@ -0,0 +1,208 @@ +// Copyright (c) 2015, 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 'dart:async'; + +import 'package:charcode/ascii.dart'; +import 'package:convert/convert.dart'; +import 'package:test/test.dart'; + +void main() { + group("encoder", () { + test("doesn't percent-encode unreserved characters", () { + expect(percent.encode([ + $a, $b, $c, $d, $e, $f, $g, $h, $i, $j, $k, $l, $m, $n, $o, $p, $q, $r, + $s, $t, $u, $v, $w, $x, $y, $z, $A, $B, $C, $D, $E, $F, $G, $H, $I, $J, + $K, $L, $M, $N, $O, $P, $Q, $R, $S, $T, $U, $V, $W, $X, $Y, $Z, $dash, + $dot, $underscore, $tilde + ]), equals("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-._~")); + }); + + test("percent-encodes reserved ASCII characters", () { + expect(percent.encode([ + $space, $backquote, $open_brace, $at, $open_bracket, $comma, + $division, $caret, $close_brace, $del, $nul, $percent + ]), equals("%20%60%7B%40%5B%2C%2F%5E%7D%7F%00%25")); + }); + + test("percent-encodes non-ASCII characters", () { + expect(percent.encode([0x80, 0xFF]), equals("%80%FF")); + }); + + test("mixes encoded and unencoded characters", () { + expect(percent.encode([$a, $plus, $b, $equal, 0x80]), + equals("a%2Bb%3D%80")); + }); + + group("with chunked conversion", () { + test("percent-encodes byte arrays", () { + var results = []; + var controller = new StreamController(sync: true); + controller.stream.listen(results.add); + var sink = percent.encoder.startChunkedConversion(controller.sink); + + sink.add([$a, $plus, $b, $equal, 0x80]); + expect(results, equals(["a%2Bb%3D%80"])); + + sink.add([0x00, 0x01, 0xfe, 0xff]); + expect(results, equals(["a%2Bb%3D%80", "%00%01%FE%FF"])); + }); + + test("handles empty and single-byte lists", () { + var results = []; + var controller = new StreamController(sync: true); + controller.stream.listen(results.add); + var sink = percent.encoder.startChunkedConversion(controller.sink); + + sink.add([]); + expect(results, equals([""])); + + sink.add([0x00]); + expect(results, equals(["", "%00"])); + + sink.add([]); + expect(results, equals(["", "%00", ""])); + }); + }); + + test("rejects non-bytes", () { + expect(() => percent.encode([0x100]), throwsFormatException); + + var sink = percent.encoder.startChunkedConversion( + new StreamController(sync: true)); + expect(() => sink.add([0x100]), throwsFormatException); + }); + }); + + group("decoder", () { + test("converts percent-encoded strings to byte arrays", () { + expect(percent.decode("a%2Bb%3D%80"), + equals([$a, $plus, $b, $equal, 0x80])); + }); + + test("supports lowercase letters", () { + expect(percent.decode("a%2bb%3d%80"), + equals([$a, $plus, $b, $equal, 0x80])); + }); + + test("supports more aggressive encoding", () { + expect(percent.decode("%61%2E%5A"), equals([$a, $dot, $Z])); + }); + + test("supports less aggressive encoding", () { + expect(percent.decode(" `{@[,/^}\x7F\x00"), equals([ + $space, $backquote, $open_brace, $at, $open_bracket, $comma, + $division, $caret, $close_brace, $del, $nul + ])); + }); + + group("with chunked conversion", () { + var results; + var sink; + setUp(() { + results = []; + var controller = new StreamController(sync: true); + controller.stream.listen(results.add); + sink = percent.decoder.startChunkedConversion(controller.sink); + }); + + test("converts percent to byte arrays", () { + sink.add("a%2Bb%3D%80"); + expect(results, equals([[$a, $plus, $b, $equal, 0x80]])); + + sink.add("%00%01%FE%FF"); + expect(results, + equals([[$a, $plus, $b, $equal, 0x80], [0x00, 0x01, 0xfe, 0xff]])); + }); + + test("supports trailing percents and digits split across chunks", () { + sink.add("ab%"); + expect(results, equals([[$a, $b]])); + + sink.add("2"); + expect(results, equals([[$a, $b]])); + + sink.add("0cd%2"); + expect(results, equals([[$a, $b], [$space, $c, $d]])); + + sink.add("0"); + expect(results, equals(([[$a, $b], [$space, $c, $d], [$space]]))); + }); + + test("supports empty strings", () { + sink.add(""); + expect(results, isEmpty); + + sink.add("%"); + expect(results, equals([[]])); + + sink.add(""); + expect(results, equals([[]])); + + sink.add("2"); + expect(results, equals([[]])); + + sink.add(""); + expect(results, equals([[]])); + + sink.add("0"); + expect(results, equals([[], [0x20]])); + }); + + test("rejects dangling % detected in close()", () { + sink.add("ab%"); + expect(results, equals([[$a, $b]])); + expect(() => sink.close(), throwsFormatException); + }); + + test("rejects dangling digit detected in close()", () { + sink.add("ab%2"); + expect(results, equals([[$a, $b]])); + expect(() => sink.close(), throwsFormatException); + }); + + test("rejects danging % detected in addSlice()", () { + sink.addSlice("ab%", 0, 3, false); + expect(results, equals([[$a, $b]])); + + expect(() => sink.addSlice("ab%", 0, 3, true), + throwsFormatException); + }); + + test("rejects danging digit detected in addSlice()", () { + sink.addSlice("ab%2", 0, 3, false); + expect(results, equals([[$a, $b]])); + + expect(() => sink.addSlice("ab%2", 0, 3, true), + throwsFormatException); + }); + }); + + group("rejects non-ASCII character", () { + for (var char in ["\u0141", "\u{10041}"]) { + test('"$char"', () { + expect(() => percent.decode("a$char"), throwsFormatException); + expect(() => percent.decode("${char}a"), throwsFormatException); + + var sink = percent.decoder.startChunkedConversion( + new StreamController(sync: true)); + expect(() => sink.add(char), throwsFormatException); + }); + } + }); + + test("rejects % followed by non-hex", () { + expect(() => percent.decode("%z2"), throwsFormatException); + expect(() => percent.decode("%2z"), throwsFormatException); + }); + + test("rejects dangling % detected in convert()", () { + expect(() => percent.decode("ab%"), throwsFormatException); + }); + + test("rejects dangling digit detected in convert()", () { + expect(() => percent.decode("ab%2"), throwsFormatException); + }); + }); +} From 59b0157ff9f66620c9d9b0ff5565a8cbe122282c Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Mon, 2 Nov 2015 16:48:17 -0800 Subject: [PATCH 005/100] Use the new Uint8Buffer.addAll start and end params. R=lrn@google.com Review URL: https://codereview.chromium.org//1411123012 . --- pkgs/convert/CHANGELOG.md | 6 ++++-- pkgs/convert/lib/src/percent/decoder.dart | 4 ++-- pkgs/convert/pubspec.yaml | 4 ++-- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/pkgs/convert/CHANGELOG.md b/pkgs/convert/CHANGELOG.md index dd213b1e..0c56ab15 100644 --- a/pkgs/convert/CHANGELOG.md +++ b/pkgs/convert/CHANGELOG.md @@ -1,5 +1,7 @@ -# Changelog +## 1.0.1 + +* Small improvement in percent decoder efficiency. ## 1.0.0 -- Initial version +* Initial version diff --git a/pkgs/convert/lib/src/percent/decoder.dart b/pkgs/convert/lib/src/percent/decoder.dart index 07406361..4d8f9941 100644 --- a/pkgs/convert/lib/src/percent/decoder.dart +++ b/pkgs/convert/lib/src/percent/decoder.dart @@ -199,7 +199,7 @@ int _decode(List codeUnits, int start, int end, Uint8Buffer buffer) { // than can be copied to the buffer as-is. if (i > sliceStart) { _checkForInvalidCodeUnit(codeUnitOr, codeUnits, sliceStart, i); - buffer.addAll(codeUnits.getRange(sliceStart, i)); + buffer.addAll(codeUnits, sliceStart, i); } // Now decode the percent-encoded byte and add it as well. @@ -222,7 +222,7 @@ int _decode(List codeUnits, int start, int end, Uint8Buffer buffer) { if (start == sliceStart) { buffer.addAll(codeUnits); } else { - buffer.addAll(codeUnits.getRange(sliceStart, end)); + buffer.addAll(codeUnits, sliceStart, end); } } diff --git a/pkgs/convert/pubspec.yaml b/pkgs/convert/pubspec.yaml index 48ef1407..0dc393b1 100644 --- a/pkgs/convert/pubspec.yaml +++ b/pkgs/convert/pubspec.yaml @@ -1,5 +1,5 @@ name: convert -version: 1.0.0 +version: 1.0.1 description: Utilities for converting between data representations. author: Dart Team homepage: https://github.com/dart-lang/convert @@ -9,7 +9,7 @@ environment: dependencies: charcode: '^1.1.0' - typed_data: '^1.0.0' + typed_data: '^1.1.0' dev_dependencies: test: '^0.12.0' From 75f50b5ce11e5b0b80018ecd1387217832b1760e Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Fri, 22 Apr 2016 14:20:03 -0700 Subject: [PATCH 006/100] Add sinks to provide synchronous access to events. These are useful when doing chunked conversion in a synchronous context. Closes dart-lang/convert#2 R=lrn@google.com Review URL: https://codereview.chromium.org//1911053002 . --- pkgs/convert/CHANGELOG.md | 5 ++ pkgs/convert/lib/convert.dart | 3 + pkgs/convert/lib/src/accumulator_sink.dart | 37 ++++++++++++ .../lib/src/byte_accumulator_sink.dart | 53 +++++++++++++++++ .../lib/src/string_accumulator_sink.dart | 46 +++++++++++++++ pkgs/convert/pubspec.yaml | 2 +- pkgs/convert/test/accumulator_sink_test.dart | 50 ++++++++++++++++ .../test/byte_accumulator_sink_test.dart | 58 +++++++++++++++++++ .../test/string_accumulator_sink_test.dart | 58 +++++++++++++++++++ 9 files changed, 311 insertions(+), 1 deletion(-) create mode 100644 pkgs/convert/lib/src/accumulator_sink.dart create mode 100644 pkgs/convert/lib/src/byte_accumulator_sink.dart create mode 100644 pkgs/convert/lib/src/string_accumulator_sink.dart create mode 100644 pkgs/convert/test/accumulator_sink_test.dart create mode 100644 pkgs/convert/test/byte_accumulator_sink_test.dart create mode 100644 pkgs/convert/test/string_accumulator_sink_test.dart diff --git a/pkgs/convert/CHANGELOG.md b/pkgs/convert/CHANGELOG.md index 0c56ab15..88ee3b22 100644 --- a/pkgs/convert/CHANGELOG.md +++ b/pkgs/convert/CHANGELOG.md @@ -1,3 +1,8 @@ +## 1.1.0 + +* Add `AccumulatorSink`, `ByteAccumulatorSink`, and `StringAccumulatorSink` + classes for providing synchronous access to the output of chunked converters. + ## 1.0.1 * Small improvement in percent decoder efficiency. diff --git a/pkgs/convert/lib/convert.dart b/pkgs/convert/lib/convert.dart index 50b02967..ad543e92 100644 --- a/pkgs/convert/lib/convert.dart +++ b/pkgs/convert/lib/convert.dart @@ -4,5 +4,8 @@ library convert; +export 'src/accumulator_sink.dart'; +export 'src/byte_accumulator_sink.dart'; export 'src/hex.dart'; export 'src/percent.dart'; +export 'src/string_accumulator_sink.dart'; diff --git a/pkgs/convert/lib/src/accumulator_sink.dart b/pkgs/convert/lib/src/accumulator_sink.dart new file mode 100644 index 00000000..ca35f7ad --- /dev/null +++ b/pkgs/convert/lib/src/accumulator_sink.dart @@ -0,0 +1,37 @@ +// Copyright (c) 2016, 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 'dart:collection'; + +/// A sink that provides access to all the [events] that have been passed to it. +/// +/// See also [ChunkedConversionSink.withCallback]. +class AccumulatorSink implements Sink { + /// An unmodifiable list of events passed to this sink so far. + List get events => new UnmodifiableListView(_events); + final _events = []; + + /// Whether [close] has been called. + bool get isClosed => _isClosed; + var _isClosed = false; + + /// Removes all events from [events]. + /// + /// This can be used to avoid double-processing events. + void clear() { + _events.clear(); + } + + void add(T event) { + if (_isClosed) { + throw new StateError("Can't add to a closed sink."); + } + + _events.add(event); + } + + void close() { + _isClosed = true; + } +} diff --git a/pkgs/convert/lib/src/byte_accumulator_sink.dart b/pkgs/convert/lib/src/byte_accumulator_sink.dart new file mode 100644 index 00000000..10bd8ee0 --- /dev/null +++ b/pkgs/convert/lib/src/byte_accumulator_sink.dart @@ -0,0 +1,53 @@ +// Copyright (c) 2016, 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 'dart:convert'; +import 'dart:typed_data'; + +import 'package:typed_data/typed_data.dart'; + +/// A sink that provides access to the concatenated bytes passed to it. +/// +/// See also [ByteConversionSink.withCallback]. +class ByteAccumulatorSink extends ByteConversionSinkBase { + /// The bytes accumulated so far. + /// + /// The returned [Uint8List] is viewing a shared buffer, so it should not be + /// changed and any bytes outside the view should not be accessed. + Uint8List get bytes => new Uint8List.view(_buffer.buffer, 0, _buffer.length); + + final _buffer = new Uint8Buffer(); + + /// Whether [close] has been called. + bool get isClosed => _isClosed; + var _isClosed = false; + + /// Removes all bytes from [bytes]. + /// + /// This can be used to avoid double-processing data. + void clear() { + _buffer.clear(); + } + + void add(List bytes) { + if (_isClosed) { + throw new StateError("Can't add to a closed sink."); + } + + _buffer.addAll(bytes); + } + + void addSlice(List chunk, int start, int end, bool isLast) { + if (_isClosed) { + throw new StateError("Can't add to a closed sink."); + } + + _buffer.addAll(chunk, start, end); + if (isLast) _isClosed = true; + } + + void close() { + _isClosed = true; + } +} diff --git a/pkgs/convert/lib/src/string_accumulator_sink.dart b/pkgs/convert/lib/src/string_accumulator_sink.dart new file mode 100644 index 00000000..95e22486 --- /dev/null +++ b/pkgs/convert/lib/src/string_accumulator_sink.dart @@ -0,0 +1,46 @@ +// Copyright (c) 2016, 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 'dart:convert'; + +/// A sink that provides access to the concatenated strings passed to it. +/// +/// See also [StringConversionSink.withCallback]. +class StringAccumulatorSink extends StringConversionSinkBase { + /// The string accumulated so far. + String get string => _buffer.toString(); + final _buffer = new StringBuffer(); + + /// Whether [close] has been called. + bool get isClosed => _isClosed; + var _isClosed = false; + + /// Empties [string]. + /// + /// This can be used to avoid double-processing data. + void clear() { + _buffer.clear(); + } + + void add(String chunk) { + if (_isClosed) { + throw new StateError("Can't add to a closed sink."); + } + + _buffer.write(chunk); + } + + void addSlice(String chunk, int start, int end, bool isLast) { + if (_isClosed) { + throw new StateError("Can't add to a closed sink."); + } + + _buffer.write(chunk.substring(start, end)); + if (isLast) _isClosed = true; + } + + void close() { + _isClosed = true; + } +} diff --git a/pkgs/convert/pubspec.yaml b/pkgs/convert/pubspec.yaml index 0dc393b1..c70ea397 100644 --- a/pkgs/convert/pubspec.yaml +++ b/pkgs/convert/pubspec.yaml @@ -1,5 +1,5 @@ name: convert -version: 1.0.1 +version: 1.1.0 description: Utilities for converting between data representations. author: Dart Team homepage: https://github.com/dart-lang/convert diff --git a/pkgs/convert/test/accumulator_sink_test.dart b/pkgs/convert/test/accumulator_sink_test.dart new file mode 100644 index 00000000..b0312f1f --- /dev/null +++ b/pkgs/convert/test/accumulator_sink_test.dart @@ -0,0 +1,50 @@ +// Copyright (c) 2016, 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 'dart:async'; + +import 'package:convert/convert.dart'; +import 'package:test/test.dart'; + +void main() { + var sink; + setUp(() { + sink = new AccumulatorSink(); + }); + + test("provides access to events as they're added", () { + expect(sink.events, isEmpty); + + sink.add(1); + expect(sink.events, equals([1])); + + sink.add(2); + expect(sink.events, equals([1, 2])); + + sink.add(3); + expect(sink.events, equals([1, 2, 3])); + }); + + test("clear() clears the events", () { + sink..add(1)..add(2)..add(3); + expect(sink.events, equals([1, 2, 3])); + + sink.clear(); + expect(sink.events, isEmpty); + + sink..add(4)..add(5)..add(6); + expect(sink.events, equals([4, 5, 6])); + }); + + test("indicates whether the sink is closed", () { + expect(sink.isClosed, isFalse); + sink.close(); + expect(sink.isClosed, isTrue); + }); + + test("doesn't allow add() to be called after close()", () { + sink.close(); + expect(() => sink.add(1), throwsStateError); + }); +} diff --git a/pkgs/convert/test/byte_accumulator_sink_test.dart b/pkgs/convert/test/byte_accumulator_sink_test.dart new file mode 100644 index 00000000..27c043e0 --- /dev/null +++ b/pkgs/convert/test/byte_accumulator_sink_test.dart @@ -0,0 +1,58 @@ +// Copyright (c) 2016, 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 'dart:async'; + +import 'package:convert/convert.dart'; +import 'package:test/test.dart'; + +void main() { + var sink; + setUp(() { + sink = new ByteAccumulatorSink(); + }); + + test("provides access to the concatenated bytes", () { + expect(sink.bytes, isEmpty); + + sink.add([1, 2, 3]); + expect(sink.bytes, equals([1, 2, 3])); + + sink.addSlice([4, 5, 6, 7, 8], 1, 4, false); + expect(sink.bytes, equals([1, 2, 3, 5, 6, 7])); + }); + + test("clear() clears the bytes", () { + sink.add([1, 2, 3]); + expect(sink.bytes, equals([1, 2, 3])); + + sink.clear(); + expect(sink.bytes, isEmpty); + + sink.add([4, 5, 6]); + expect(sink.bytes, equals([4, 5, 6])); + }); + + test("indicates whether the sink is closed", () { + expect(sink.isClosed, isFalse); + sink.close(); + expect(sink.isClosed, isTrue); + }); + + test("indicates whether the sink is closed via addSlice", () { + expect(sink.isClosed, isFalse); + sink.addSlice([], 0, 0, true); + expect(sink.isClosed, isTrue); + }); + + test("doesn't allow add() to be called after close()", () { + sink.close(); + expect(() => sink.add([1]), throwsStateError); + }); + + test("doesn't allow addSlice() to be called after close()", () { + sink.close(); + expect(() => sink.addSlice([], 0, 0, false), throwsStateError); + }); +} diff --git a/pkgs/convert/test/string_accumulator_sink_test.dart b/pkgs/convert/test/string_accumulator_sink_test.dart new file mode 100644 index 00000000..e6e30e6e --- /dev/null +++ b/pkgs/convert/test/string_accumulator_sink_test.dart @@ -0,0 +1,58 @@ +// Copyright (c) 2016, 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 'dart:async'; + +import 'package:convert/convert.dart'; +import 'package:test/test.dart'; + +void main() { + var sink; + setUp(() { + sink = new StringAccumulatorSink(); + }); + + test("provides access to the concatenated string", () { + expect(sink.string, isEmpty); + + sink.add("foo"); + expect(sink.string, equals("foo")); + + sink.addSlice(" bar baz", 1, 4, false); + expect(sink.string, equals("foobar")); + }); + + test("clear() clears the string", () { + sink.add("foo"); + expect(sink.string, equals("foo")); + + sink.clear(); + expect(sink.string, isEmpty); + + sink.add("bar"); + expect(sink.string, equals("bar")); + }); + + test("indicates whether the sink is closed", () { + expect(sink.isClosed, isFalse); + sink.close(); + expect(sink.isClosed, isTrue); + }); + + test("indicates whether the sink is closed via addSlice", () { + expect(sink.isClosed, isFalse); + sink.addSlice("", 0, 0, true); + expect(sink.isClosed, isTrue); + }); + + test("doesn't allow add() to be called after close()", () { + sink.close(); + expect(() => sink.add("x"), throwsStateError); + }); + + test("doesn't allow addSlice() to be called after close()", () { + sink.close(); + expect(() => sink.addSlice("", 0, 0, false), throwsStateError); + }); +} From 3948ffdbc11ee47d94db6709dcffa8933a8d5bc7 Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Tue, 26 Apr 2016 17:13:02 -0700 Subject: [PATCH 007/100] Make the package strong-mode clean. R=rnystrom@google.com, lrn@google.com Review URL: https://codereview.chromium.org//1912273003 . --- pkgs/convert/.analysis_options | 2 ++ pkgs/convert/CHANGELOG.md | 4 ++++ pkgs/convert/lib/src/hex/decoder.dart | 11 ++++++----- pkgs/convert/lib/src/hex/encoder.dart | 3 ++- pkgs/convert/lib/src/percent/decoder.dart | 3 ++- pkgs/convert/lib/src/percent/encoder.dart | 3 ++- pkgs/convert/pubspec.yaml | 4 ++-- pkgs/convert/test/accumulator_sink_test.dart | 2 -- pkgs/convert/test/byte_accumulator_sink_test.dart | 2 -- pkgs/convert/test/hex_test.dart | 12 ++++++------ pkgs/convert/test/percent_test.dart | 12 ++++++------ pkgs/convert/test/string_accumulator_sink_test.dart | 2 -- 12 files changed, 32 insertions(+), 28 deletions(-) create mode 100644 pkgs/convert/.analysis_options diff --git a/pkgs/convert/.analysis_options b/pkgs/convert/.analysis_options new file mode 100644 index 00000000..a10d4c5a --- /dev/null +++ b/pkgs/convert/.analysis_options @@ -0,0 +1,2 @@ +analyzer: + strong-mode: true diff --git a/pkgs/convert/CHANGELOG.md b/pkgs/convert/CHANGELOG.md index 88ee3b22..19fbce6f 100644 --- a/pkgs/convert/CHANGELOG.md +++ b/pkgs/convert/CHANGELOG.md @@ -1,3 +1,7 @@ +## 1.1.1 + +* Fix all strong-mode warnings. + ## 1.1.0 * Add `AccumulatorSink`, `ByteAccumulatorSink`, and `StringAccumulatorSink` diff --git a/pkgs/convert/lib/src/hex/decoder.dart b/pkgs/convert/lib/src/hex/decoder.dart index efb0b0d4..6a31641f 100644 --- a/pkgs/convert/lib/src/hex/decoder.dart +++ b/pkgs/convert/lib/src/hex/decoder.dart @@ -17,7 +17,8 @@ const hexDecoder = const HexDecoder._(); /// Because two hexadecimal digits correspond to a single byte, this will throw /// a [FormatException] if given an odd-length string. It will also throw a /// [FormatException] if given a string containing non-hexadecimal code units. -class HexDecoder extends Converter> { +class HexDecoder + extends ChunkedConverter, String, List> { const HexDecoder._(); List convert(String string) { @@ -58,8 +59,8 @@ class _HexDecoderSink extends StringConversionSinkBase { } var codeUnits = string.codeUnits; - var bytes; - var bytesStart; + Uint8List bytes; + int bytesStart; if (_lastDigit == null) { bytes = new Uint8List((end - start) ~/ 2); bytesStart = 0; @@ -118,8 +119,8 @@ class _HexDecoderByteSink extends ByteConversionSinkBase { return; } - var bytes; - var bytesStart; + Uint8List bytes; + int bytesStart; if (_lastDigit == null) { bytes = new Uint8List((end - start) ~/ 2); bytesStart = 0; diff --git a/pkgs/convert/lib/src/hex/encoder.dart b/pkgs/convert/lib/src/hex/encoder.dart index a9c66a5a..ee53dd70 100644 --- a/pkgs/convert/lib/src/hex/encoder.dart +++ b/pkgs/convert/lib/src/hex/encoder.dart @@ -16,7 +16,8 @@ const hexEncoder = const HexEncoder._(); /// /// This will throw a [RangeError] if the byte array has any digits that don't /// fit in the gamut of a byte. -class HexEncoder extends Converter, String> { +class HexEncoder + extends ChunkedConverter, String, List, String> { const HexEncoder._(); String convert(List bytes) => _convert(bytes, 0, bytes.length); diff --git a/pkgs/convert/lib/src/percent/decoder.dart b/pkgs/convert/lib/src/percent/decoder.dart index 4d8f9941..3ff3e016 100644 --- a/pkgs/convert/lib/src/percent/decoder.dart +++ b/pkgs/convert/lib/src/percent/decoder.dart @@ -25,7 +25,8 @@ const _lastPercent = -1; /// /// This will throw a [FormatException] if the input string has an incomplete /// percent-encoding, or if it contains non-ASCII code units. -class PercentDecoder extends Converter> { +class PercentDecoder + extends ChunkedConverter, String, List> { const PercentDecoder._(); List convert(String string) { diff --git a/pkgs/convert/lib/src/percent/encoder.dart b/pkgs/convert/lib/src/percent/encoder.dart index c7817609..b4cf1a19 100644 --- a/pkgs/convert/lib/src/percent/encoder.dart +++ b/pkgs/convert/lib/src/percent/encoder.dart @@ -19,7 +19,8 @@ const percentEncoder = const PercentEncoder._(); /// /// This will throw a [RangeError] if the byte array has any digits that don't /// fit in the gamut of a byte. -class PercentEncoder extends Converter, String> { +class PercentEncoder + extends ChunkedConverter, String, List, String> { const PercentEncoder._(); String convert(List bytes) => _convert(bytes, 0, bytes.length); diff --git a/pkgs/convert/pubspec.yaml b/pkgs/convert/pubspec.yaml index c70ea397..94315e0b 100644 --- a/pkgs/convert/pubspec.yaml +++ b/pkgs/convert/pubspec.yaml @@ -1,11 +1,11 @@ name: convert -version: 1.1.0 +version: 1.1.1 description: Utilities for converting between data representations. author: Dart Team homepage: https://github.com/dart-lang/convert environment: - sdk: '>=1.8.0 <2.0.0' + sdk: '>=1.16.0 <2.0.0' dependencies: charcode: '^1.1.0' diff --git a/pkgs/convert/test/accumulator_sink_test.dart b/pkgs/convert/test/accumulator_sink_test.dart index b0312f1f..81fe1db7 100644 --- a/pkgs/convert/test/accumulator_sink_test.dart +++ b/pkgs/convert/test/accumulator_sink_test.dart @@ -2,8 +2,6 @@ // 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 'dart:async'; - import 'package:convert/convert.dart'; import 'package:test/test.dart'; diff --git a/pkgs/convert/test/byte_accumulator_sink_test.dart b/pkgs/convert/test/byte_accumulator_sink_test.dart index 27c043e0..123baa8e 100644 --- a/pkgs/convert/test/byte_accumulator_sink_test.dart +++ b/pkgs/convert/test/byte_accumulator_sink_test.dart @@ -2,8 +2,6 @@ // 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 'dart:async'; - import 'package:convert/convert.dart'; import 'package:test/test.dart'; diff --git a/pkgs/convert/test/hex_test.dart b/pkgs/convert/test/hex_test.dart index f52edaf2..837085f6 100644 --- a/pkgs/convert/test/hex_test.dart +++ b/pkgs/convert/test/hex_test.dart @@ -16,8 +16,8 @@ void main() { group("with chunked conversion", () { test("converts byte arrays to hex", () { - var results = []; - var controller = new StreamController(sync: true); + var results = []; + var controller = new StreamController(sync: true); controller.stream.listen(results.add); var sink = hex.encoder.startChunkedConversion(controller.sink); @@ -29,8 +29,8 @@ void main() { }); test("handles empty and single-byte lists", () { - var results = []; - var controller = new StreamController(sync: true); + var results = []; + var controller = new StreamController(sync: true); controller.stream.listen(results.add); var sink = hex.encoder.startChunkedConversion(controller.sink); @@ -67,11 +67,11 @@ void main() { }); group("with chunked conversion", () { - var results; + List> results; var sink; setUp(() { results = []; - var controller = new StreamController(sync: true); + var controller = new StreamController>(sync: true); controller.stream.listen(results.add); sink = hex.decoder.startChunkedConversion(controller.sink); }); diff --git a/pkgs/convert/test/percent_test.dart b/pkgs/convert/test/percent_test.dart index f7a1c489..7a1daca4 100644 --- a/pkgs/convert/test/percent_test.dart +++ b/pkgs/convert/test/percent_test.dart @@ -37,8 +37,8 @@ void main() { group("with chunked conversion", () { test("percent-encodes byte arrays", () { - var results = []; - var controller = new StreamController(sync: true); + var results = []; + var controller = new StreamController(sync: true); controller.stream.listen(results.add); var sink = percent.encoder.startChunkedConversion(controller.sink); @@ -50,8 +50,8 @@ void main() { }); test("handles empty and single-byte lists", () { - var results = []; - var controller = new StreamController(sync: true); + var results = []; + var controller = new StreamController(sync: true); controller.stream.listen(results.add); var sink = percent.encoder.startChunkedConversion(controller.sink); @@ -98,11 +98,11 @@ void main() { }); group("with chunked conversion", () { - var results; + List> results; var sink; setUp(() { results = []; - var controller = new StreamController(sync: true); + var controller = new StreamController>(sync: true); controller.stream.listen(results.add); sink = percent.decoder.startChunkedConversion(controller.sink); }); diff --git a/pkgs/convert/test/string_accumulator_sink_test.dart b/pkgs/convert/test/string_accumulator_sink_test.dart index e6e30e6e..914dd930 100644 --- a/pkgs/convert/test/string_accumulator_sink_test.dart +++ b/pkgs/convert/test/string_accumulator_sink_test.dart @@ -2,8 +2,6 @@ // 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 'dart:async'; - import 'package:convert/convert.dart'; import 'package:test/test.dart'; From 7e211ae8e328117dcea0b9364bf8e5e6107d4d1f Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Fri, 3 Jun 2016 15:28:06 -0700 Subject: [PATCH 008/100] Stop implementing ChunkedConverter. This was deprecated in Dart 1.17, and its members were changed such that we can no longer implement it and be strong-mode clean. R=kevmoo@google.com Review URL: https://codereview.chromium.org//2031873006 . --- pkgs/convert/CHANGELOG.md | 8 ++++++++ pkgs/convert/lib/src/hex/decoder.dart | 3 +-- pkgs/convert/lib/src/hex/encoder.dart | 3 +-- pkgs/convert/lib/src/percent/decoder.dart | 3 +-- pkgs/convert/lib/src/percent/encoder.dart | 3 +-- pkgs/convert/pubspec.yaml | 4 ++-- 6 files changed, 14 insertions(+), 10 deletions(-) diff --git a/pkgs/convert/CHANGELOG.md b/pkgs/convert/CHANGELOG.md index 19fbce6f..b1599280 100644 --- a/pkgs/convert/CHANGELOG.md +++ b/pkgs/convert/CHANGELOG.md @@ -1,3 +1,11 @@ +## 2.0.0 + +**Note**: No new APIs have been added in 2.0.0. Packages that would use 2.0.0 as +a lower bound should use 1.0.0 instead—for example, `convert: ">=1.0.0 <3.0.0"`. + +* `HexDecoder`, `HexEncoder`, `PercentDecoder`, and `PercentEncoder` no longer + extend `ChunkedConverter`. + ## 1.1.1 * Fix all strong-mode warnings. diff --git a/pkgs/convert/lib/src/hex/decoder.dart b/pkgs/convert/lib/src/hex/decoder.dart index 6a31641f..d7a7555b 100644 --- a/pkgs/convert/lib/src/hex/decoder.dart +++ b/pkgs/convert/lib/src/hex/decoder.dart @@ -17,8 +17,7 @@ const hexDecoder = const HexDecoder._(); /// Because two hexadecimal digits correspond to a single byte, this will throw /// a [FormatException] if given an odd-length string. It will also throw a /// [FormatException] if given a string containing non-hexadecimal code units. -class HexDecoder - extends ChunkedConverter, String, List> { +class HexDecoder extends Converter> { const HexDecoder._(); List convert(String string) { diff --git a/pkgs/convert/lib/src/hex/encoder.dart b/pkgs/convert/lib/src/hex/encoder.dart index ee53dd70..a9c66a5a 100644 --- a/pkgs/convert/lib/src/hex/encoder.dart +++ b/pkgs/convert/lib/src/hex/encoder.dart @@ -16,8 +16,7 @@ const hexEncoder = const HexEncoder._(); /// /// This will throw a [RangeError] if the byte array has any digits that don't /// fit in the gamut of a byte. -class HexEncoder - extends ChunkedConverter, String, List, String> { +class HexEncoder extends Converter, String> { const HexEncoder._(); String convert(List bytes) => _convert(bytes, 0, bytes.length); diff --git a/pkgs/convert/lib/src/percent/decoder.dart b/pkgs/convert/lib/src/percent/decoder.dart index 3ff3e016..4d8f9941 100644 --- a/pkgs/convert/lib/src/percent/decoder.dart +++ b/pkgs/convert/lib/src/percent/decoder.dart @@ -25,8 +25,7 @@ const _lastPercent = -1; /// /// This will throw a [FormatException] if the input string has an incomplete /// percent-encoding, or if it contains non-ASCII code units. -class PercentDecoder - extends ChunkedConverter, String, List> { +class PercentDecoder extends Converter> { const PercentDecoder._(); List convert(String string) { diff --git a/pkgs/convert/lib/src/percent/encoder.dart b/pkgs/convert/lib/src/percent/encoder.dart index b4cf1a19..c7817609 100644 --- a/pkgs/convert/lib/src/percent/encoder.dart +++ b/pkgs/convert/lib/src/percent/encoder.dart @@ -19,8 +19,7 @@ const percentEncoder = const PercentEncoder._(); /// /// This will throw a [RangeError] if the byte array has any digits that don't /// fit in the gamut of a byte. -class PercentEncoder - extends ChunkedConverter, String, List, String> { +class PercentEncoder extends Converter, String> { const PercentEncoder._(); String convert(List bytes) => _convert(bytes, 0, bytes.length); diff --git a/pkgs/convert/pubspec.yaml b/pkgs/convert/pubspec.yaml index 94315e0b..e9d38be7 100644 --- a/pkgs/convert/pubspec.yaml +++ b/pkgs/convert/pubspec.yaml @@ -1,11 +1,11 @@ name: convert -version: 1.1.1 +version: 2.0.0 description: Utilities for converting between data representations. author: Dart Team homepage: https://github.com/dart-lang/convert environment: - sdk: '>=1.16.0 <2.0.0' + sdk: '>=1.17.0-dev.6.2 <2.0.0' dependencies: charcode: '^1.1.0' From 376ee4edb2a1b987cf105cba03b76a9b261709f4 Mon Sep 17 00:00:00 2001 From: Danny Tuppeny Date: Sun, 24 Jul 2016 14:31:17 +0100 Subject: [PATCH 009/100] Stop percent-encoding of numbers. RFC 3986 states that numbers are unreserved characters: Characters that are allowed in a URI but do not have a reserved purpose are called unreserved. These include uppercase and lowercase letters, decimal digits, hyphen, period, underscore, and tilde. unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~" [...] For consistency, percent-encoded octets in the ranges of ALPHA (%41-%5A and %61-%7A), DIGIT (%30-%39), hyphen (%2D), period (%2E), underscore (%5F), or tilde (%7E) should not be created by URI producers --- pkgs/convert/lib/src/percent/encoder.dart | 1 + pkgs/convert/test/percent_test.dart | 16 ++++++++-------- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/pkgs/convert/lib/src/percent/encoder.dart b/pkgs/convert/lib/src/percent/encoder.dart index c7817609..790caff1 100644 --- a/pkgs/convert/lib/src/percent/encoder.dart +++ b/pkgs/convert/lib/src/percent/encoder.dart @@ -67,6 +67,7 @@ String _convert(List bytes, int start, int end) { // that that bit is 1 we ensure that the letter is lowercase. var letter = 0x20 | byte; if ((letter >= $a && letter <= $z) || + (byte >= $0 && byte <= $9) || byte == $dash || byte == $dot || byte == $underscore || diff --git a/pkgs/convert/test/percent_test.dart b/pkgs/convert/test/percent_test.dart index 7a1daca4..a4a6fb7d 100644 --- a/pkgs/convert/test/percent_test.dart +++ b/pkgs/convert/test/percent_test.dart @@ -14,9 +14,9 @@ void main() { expect(percent.encode([ $a, $b, $c, $d, $e, $f, $g, $h, $i, $j, $k, $l, $m, $n, $o, $p, $q, $r, $s, $t, $u, $v, $w, $x, $y, $z, $A, $B, $C, $D, $E, $F, $G, $H, $I, $J, - $K, $L, $M, $N, $O, $P, $Q, $R, $S, $T, $U, $V, $W, $X, $Y, $Z, $dash, - $dot, $underscore, $tilde - ]), equals("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-._~")); + $K, $L, $M, $N, $O, $P, $Q, $R, $S, $T, $U, $V, $W, $X, $Y, $Z, $0, $1, + $2, $3, $4, $5, $6, $7, $8, $9, $dash, $dot, $underscore, $tilde + ]), equals("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._~")); }); test("percent-encodes reserved ASCII characters", () { @@ -77,8 +77,8 @@ void main() { group("decoder", () { test("converts percent-encoded strings to byte arrays", () { - expect(percent.decode("a%2Bb%3D%80"), - equals([$a, $plus, $b, $equal, 0x80])); + expect(percent.decode("a%2Bb%3D%801"), + equals([$a, $plus, $b, $equal, 0x80, $1])); }); test("supports lowercase letters", () { @@ -108,12 +108,12 @@ void main() { }); test("converts percent to byte arrays", () { - sink.add("a%2Bb%3D%80"); - expect(results, equals([[$a, $plus, $b, $equal, 0x80]])); + sink.add("a%2Bb%3D%801"); + expect(results, equals([[$a, $plus, $b, $equal, 0x80, $1]])); sink.add("%00%01%FE%FF"); expect(results, - equals([[$a, $plus, $b, $equal, 0x80], [0x00, 0x01, 0xfe, 0xff]])); + equals([[$a, $plus, $b, $equal, 0x80, $1], [0x00, 0x01, 0xfe, 0xff]])); }); test("supports trailing percents and digits split across chunks", () { From 2f91adead1e16e8d70068da245badac3daa741b1 Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Mon, 8 Aug 2016 15:13:16 -0700 Subject: [PATCH 010/100] Bump the version. --- pkgs/convert/CHANGELOG.md | 5 +++++ pkgs/convert/pubspec.yaml | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/pkgs/convert/CHANGELOG.md b/pkgs/convert/CHANGELOG.md index b1599280..984a0eed 100644 --- a/pkgs/convert/CHANGELOG.md +++ b/pkgs/convert/CHANGELOG.md @@ -1,3 +1,8 @@ +## 2.0.1 + +* `PercentEncoder` no longer encodes digits. This follows the specified + behavior. + ## 2.0.0 **Note**: No new APIs have been added in 2.0.0. Packages that would use 2.0.0 as diff --git a/pkgs/convert/pubspec.yaml b/pkgs/convert/pubspec.yaml index e9d38be7..e442f97a 100644 --- a/pkgs/convert/pubspec.yaml +++ b/pkgs/convert/pubspec.yaml @@ -1,5 +1,5 @@ name: convert -version: 2.0.0 +version: 2.0.1 description: Utilities for converting between data representations. author: Dart Team homepage: https://github.com/dart-lang/convert From 255f9c4fa7ed0cac191259631a9ff38f44003743 Mon Sep 17 00:00:00 2001 From: Matan Lurey Date: Tue, 16 May 2017 19:43:44 -0700 Subject: [PATCH 011/100] Add travis support and dartfmt... (dart-lang/convert#6) * Add travis support for pkg/convert. * Run dartfmt. * Only dartfmt stable. * Remove --platform chrome. --- pkgs/convert/.travis.yml | 18 ++ pkgs/convert/lib/src/hex/decoder.dart | 4 +- pkgs/convert/lib/src/hex/encoder.dart | 3 +- pkgs/convert/lib/src/percent/decoder.dart | 12 +- pkgs/convert/lib/src/percent/encoder.dart | 3 +- pkgs/convert/lib/src/utils.dart | 6 +- pkgs/convert/test/hex_test.dart | 116 +++++++++--- pkgs/convert/test/percent_test.dart | 210 ++++++++++++++++++---- 8 files changed, 297 insertions(+), 75 deletions(-) create mode 100644 pkgs/convert/.travis.yml diff --git a/pkgs/convert/.travis.yml b/pkgs/convert/.travis.yml new file mode 100644 index 00000000..10d307b7 --- /dev/null +++ b/pkgs/convert/.travis.yml @@ -0,0 +1,18 @@ +language: dart +sudo: false +dart: + - dev + - stable +cache: + directories: + - $HOME/.pub-cache +dart_task: + - test: --platform vm + - test: --platform dartium + install_dartium: true + - dartanalyzer + - dartfmt +matrix: + exclude: + - dart: dev + dart_task: dartfmt diff --git a/pkgs/convert/lib/src/hex/decoder.dart b/pkgs/convert/lib/src/hex/decoder.dart index d7a7555b..c1c8febf 100644 --- a/pkgs/convert/lib/src/hex/decoder.dart +++ b/pkgs/convert/lib/src/hex/decoder.dart @@ -22,8 +22,8 @@ class HexDecoder extends Converter> { List convert(String string) { if (!string.length.isEven) { - throw new FormatException("Invalid input length, must be even.", - string, string.length); + throw new FormatException( + "Invalid input length, must be even.", string, string.length); } var bytes = new Uint8List(string.length ~/ 2); diff --git a/pkgs/convert/lib/src/hex/encoder.dart b/pkgs/convert/lib/src/hex/encoder.dart index a9c66a5a..9339cda5 100644 --- a/pkgs/convert/lib/src/hex/encoder.dart +++ b/pkgs/convert/lib/src/hex/encoder.dart @@ -77,7 +77,8 @@ String _convert(List bytes, int start, int end) { if (byte >= 0 && byte <= 0xff) continue; throw new FormatException( "Invalid byte ${byte < 0 ? "-" : ""}0x${byte.abs().toRadixString(16)}.", - bytes, i); + bytes, + i); } throw 'unreachable'; diff --git a/pkgs/convert/lib/src/percent/decoder.dart b/pkgs/convert/lib/src/percent/decoder.dart index 4d8f9941..334e754f 100644 --- a/pkgs/convert/lib/src/percent/decoder.dart +++ b/pkgs/convert/lib/src/percent/decoder.dart @@ -34,8 +34,7 @@ class PercentDecoder extends Converter> { if (lastDigit != null) { throw new FormatException( - "Input ended with incomplete encoded byte.", - string, string.length); + "Input ended with incomplete encoded byte.", string, string.length); } return buffer.buffer.asUint8List(0, buffer.length); @@ -229,8 +228,8 @@ int _decode(List codeUnits, int start, int end, Uint8Buffer buffer) { return null; } -void _checkForInvalidCodeUnit(int codeUnitOr, List codeUnits, int start, - int end) { +void _checkForInvalidCodeUnit( + int codeUnitOr, List codeUnits, int start, int end) { if (codeUnitOr >= 0 && codeUnitOr <= 0x7f) return; for (var i = start; i < end; i++) { @@ -238,7 +237,8 @@ void _checkForInvalidCodeUnit(int codeUnitOr, List codeUnits, int start, if (codeUnit >= 0 && codeUnit <= 0x7f) continue; throw new FormatException( "Non-ASCII code unit " - "U+${codeUnit.toRadixString(16).padLeft(4, '0')}", - codeUnits, i); + "U+${codeUnit.toRadixString(16).padLeft(4, '0')}", + codeUnits, + i); } } diff --git a/pkgs/convert/lib/src/percent/encoder.dart b/pkgs/convert/lib/src/percent/encoder.dart index 790caff1..d4419a9e 100644 --- a/pkgs/convert/lib/src/percent/encoder.dart +++ b/pkgs/convert/lib/src/percent/encoder.dart @@ -94,7 +94,8 @@ String _convert(List bytes, int start, int end) { if (byte >= 0 && byte <= 0xff) continue; throw new FormatException( "Invalid byte ${byte < 0 ? "-" : ""}0x${byte.abs().toRadixString(16)}.", - bytes, i); + bytes, + i); } throw 'unreachable'; diff --git a/pkgs/convert/lib/src/utils.dart b/pkgs/convert/lib/src/utils.dart index 6bd44689..79907797 100644 --- a/pkgs/convert/lib/src/utils.dart +++ b/pkgs/convert/lib/src/utils.dart @@ -33,7 +33,7 @@ int digitForCodeUnit(List codeUnits, int index) { throw new FormatException( "Invalid hexadecimal code unit " - "U+${codeUnit.toRadixString(16).padLeft(4, '0')}.", - codeUnits, index); + "U+${codeUnit.toRadixString(16).padLeft(4, '0')}.", + codeUnits, + index); } - diff --git a/pkgs/convert/test/hex_test.dart b/pkgs/convert/test/hex_test.dart index 837085f6..95f0e905 100644 --- a/pkgs/convert/test/hex_test.dart +++ b/pkgs/convert/test/hex_test.dart @@ -48,8 +48,8 @@ void main() { test("rejects non-bytes", () { expect(() => hex.encode([0x100]), throwsFormatException); - var sink = hex.encoder.startChunkedConversion( - new StreamController(sync: true)); + var sink = + hex.encoder.startChunkedConversion(new StreamController(sync: true)); expect(() => sink.add([0x100]), throwsFormatException); }); }); @@ -61,9 +61,21 @@ void main() { }); test("supports uppercase letters", () { - expect(hex.decode("0123456789ABCDEFabcdef"), equals([ - 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0xab, 0xcd, 0xef - ])); + expect( + hex.decode("0123456789ABCDEFabcdef"), + equals([ + 0x01, + 0x23, + 0x45, + 0x67, + 0x89, + 0xab, + 0xcd, + 0xef, + 0xab, + 0xcd, + 0xef + ])); }); group("with chunked conversion", () { @@ -78,26 +90,55 @@ void main() { test("converts hex to byte arrays", () { sink.add("1ab23cd4"); - expect(results, equals([[0x1a, 0xb2, 0x3c, 0xd4]])); + expect( + results, + equals([ + [0x1a, 0xb2, 0x3c, 0xd4] + ])); sink.add("0001feff"); - expect(results, - equals([[0x1a, 0xb2, 0x3c, 0xd4], [0x00, 0x01, 0xfe, 0xff]])); + expect( + results, + equals([ + [0x1a, 0xb2, 0x3c, 0xd4], + [0x00, 0x01, 0xfe, 0xff] + ])); }); test("supports trailing digits split across chunks", () { sink.add("1ab23"); - expect(results, equals([[0x1a, 0xb2]])); + expect( + results, + equals([ + [0x1a, 0xb2] + ])); sink.add("cd"); - expect(results, equals([[0x1a, 0xb2], [0x3c]])); + expect( + results, + equals([ + [0x1a, 0xb2], + [0x3c] + ])); sink.add("40001"); - expect(results, equals([[0x1a, 0xb2], [0x3c], [0xd4, 0x00, 0x01]])); + expect( + results, + equals([ + [0x1a, 0xb2], + [0x3c], + [0xd4, 0x00, 0x01] + ])); sink.add("feff"); - expect(results, - equals([[0x1a, 0xb2], [0x3c], [0xd4, 0x00, 0x01], [0xfe, 0xff]])); + expect( + results, + equals([ + [0x1a, 0xb2], + [0x3c], + [0xd4, 0x00, 0x01], + [0xfe, 0xff] + ])); }); test("supports empty strings", () { @@ -111,36 +152,63 @@ void main() { expect(results, equals([[]])); sink.add("0"); - expect(results, equals([[], [0x00]])); + expect( + results, + equals([ + [], + [0x00] + ])); sink.add(""); - expect(results, equals([[], [0x00]])); + expect( + results, + equals([ + [], + [0x00] + ])); }); test("rejects odd length detected in close()", () { sink.add("1ab23"); - expect(results, equals([[0x1a, 0xb2]])); + expect( + results, + equals([ + [0x1a, 0xb2] + ])); expect(() => sink.close(), throwsFormatException); }); test("rejects odd length detected in addSlice()", () { sink.addSlice("1ab23cd", 0, 5, false); - expect(results, equals([[0x1a, 0xb2]])); - - expect(() => sink.addSlice("1ab23cd", 5, 7, true), - throwsFormatException); + expect( + results, + equals([ + [0x1a, 0xb2] + ])); + + expect( + () => sink.addSlice("1ab23cd", 5, 7, true), throwsFormatException); }); }); group("rejects non-hex character", () { - for (var char in - ["g", "G", "/", ":", "@", "`", "\x00", "\u0141", "\u{10041}"]) { + for (var char in [ + "g", + "G", + "/", + ":", + "@", + "`", + "\x00", + "\u0141", + "\u{10041}" + ]) { test('"$char"', () { expect(() => hex.decode("a$char"), throwsFormatException); expect(() => hex.decode("${char}a"), throwsFormatException); - var sink = hex.decoder.startChunkedConversion( - new StreamController(sync: true)); + var sink = hex.decoder + .startChunkedConversion(new StreamController(sync: true)); expect(() => sink.add(char), throwsFormatException); }); } diff --git a/pkgs/convert/test/percent_test.dart b/pkgs/convert/test/percent_test.dart index a4a6fb7d..c2f0a3cd 100644 --- a/pkgs/convert/test/percent_test.dart +++ b/pkgs/convert/test/percent_test.dart @@ -11,19 +11,96 @@ import 'package:test/test.dart'; void main() { group("encoder", () { test("doesn't percent-encode unreserved characters", () { - expect(percent.encode([ - $a, $b, $c, $d, $e, $f, $g, $h, $i, $j, $k, $l, $m, $n, $o, $p, $q, $r, - $s, $t, $u, $v, $w, $x, $y, $z, $A, $B, $C, $D, $E, $F, $G, $H, $I, $J, - $K, $L, $M, $N, $O, $P, $Q, $R, $S, $T, $U, $V, $W, $X, $Y, $Z, $0, $1, - $2, $3, $4, $5, $6, $7, $8, $9, $dash, $dot, $underscore, $tilde - ]), equals("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._~")); + expect( + percent.encode([ + $a, + $b, + $c, + $d, + $e, + $f, + $g, + $h, + $i, + $j, + $k, + $l, + $m, + $n, + $o, + $p, + $q, + $r, + $s, + $t, + $u, + $v, + $w, + $x, + $y, + $z, + $A, + $B, + $C, + $D, + $E, + $F, + $G, + $H, + $I, + $J, + $K, + $L, + $M, + $N, + $O, + $P, + $Q, + $R, + $S, + $T, + $U, + $V, + $W, + $X, + $Y, + $Z, + $0, + $1, + $2, + $3, + $4, + $5, + $6, + $7, + $8, + $9, + $dash, + $dot, + $underscore, + $tilde + ]), + equals( + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._~")); }); test("percent-encodes reserved ASCII characters", () { - expect(percent.encode([ - $space, $backquote, $open_brace, $at, $open_bracket, $comma, - $division, $caret, $close_brace, $del, $nul, $percent - ]), equals("%20%60%7B%40%5B%2C%2F%5E%7D%7F%00%25")); + expect( + percent.encode([ + $space, + $backquote, + $open_brace, + $at, + $open_bracket, + $comma, + $division, + $caret, + $close_brace, + $del, + $nul, + $percent + ]), + equals("%20%60%7B%40%5B%2C%2F%5E%7D%7F%00%25")); }); test("percent-encodes non-ASCII characters", () { @@ -31,8 +108,8 @@ void main() { }); test("mixes encoded and unencoded characters", () { - expect(percent.encode([$a, $plus, $b, $equal, 0x80]), - equals("a%2Bb%3D%80")); + expect( + percent.encode([$a, $plus, $b, $equal, 0x80]), equals("a%2Bb%3D%80")); }); group("with chunked conversion", () { @@ -69,8 +146,8 @@ void main() { test("rejects non-bytes", () { expect(() => percent.encode([0x100]), throwsFormatException); - var sink = percent.encoder.startChunkedConversion( - new StreamController(sync: true)); + var sink = percent.encoder + .startChunkedConversion(new StreamController(sync: true)); expect(() => sink.add([0x100]), throwsFormatException); }); }); @@ -82,8 +159,8 @@ void main() { }); test("supports lowercase letters", () { - expect(percent.decode("a%2bb%3d%80"), - equals([$a, $plus, $b, $equal, 0x80])); + expect( + percent.decode("a%2bb%3d%80"), equals([$a, $plus, $b, $equal, 0x80])); }); test("supports more aggressive encoding", () { @@ -91,10 +168,21 @@ void main() { }); test("supports less aggressive encoding", () { - expect(percent.decode(" `{@[,/^}\x7F\x00"), equals([ - $space, $backquote, $open_brace, $at, $open_bracket, $comma, - $division, $caret, $close_brace, $del, $nul - ])); + expect( + percent.decode(" `{@[,/^}\x7F\x00"), + equals([ + $space, + $backquote, + $open_brace, + $at, + $open_bracket, + $comma, + $division, + $caret, + $close_brace, + $del, + $nul + ])); }); group("with chunked conversion", () { @@ -109,25 +197,52 @@ void main() { test("converts percent to byte arrays", () { sink.add("a%2Bb%3D%801"); - expect(results, equals([[$a, $plus, $b, $equal, 0x80, $1]])); + expect( + results, + equals([ + [$a, $plus, $b, $equal, 0x80, $1] + ])); sink.add("%00%01%FE%FF"); - expect(results, - equals([[$a, $plus, $b, $equal, 0x80, $1], [0x00, 0x01, 0xfe, 0xff]])); + expect( + results, + equals([ + [$a, $plus, $b, $equal, 0x80, $1], + [0x00, 0x01, 0xfe, 0xff] + ])); }); test("supports trailing percents and digits split across chunks", () { sink.add("ab%"); - expect(results, equals([[$a, $b]])); + expect( + results, + equals([ + [$a, $b] + ])); sink.add("2"); - expect(results, equals([[$a, $b]])); + expect( + results, + equals([ + [$a, $b] + ])); sink.add("0cd%2"); - expect(results, equals([[$a, $b], [$space, $c, $d]])); + expect( + results, + equals([ + [$a, $b], + [$space, $c, $d] + ])); sink.add("0"); - expect(results, equals(([[$a, $b], [$space, $c, $d], [$space]]))); + expect( + results, + equals(([ + [$a, $b], + [$space, $c, $d], + [$space] + ]))); }); test("supports empty strings", () { @@ -147,35 +262,54 @@ void main() { expect(results, equals([[]])); sink.add("0"); - expect(results, equals([[], [0x20]])); + expect( + results, + equals([ + [], + [0x20] + ])); }); test("rejects dangling % detected in close()", () { sink.add("ab%"); - expect(results, equals([[$a, $b]])); + expect( + results, + equals([ + [$a, $b] + ])); expect(() => sink.close(), throwsFormatException); }); test("rejects dangling digit detected in close()", () { sink.add("ab%2"); - expect(results, equals([[$a, $b]])); + expect( + results, + equals([ + [$a, $b] + ])); expect(() => sink.close(), throwsFormatException); }); test("rejects danging % detected in addSlice()", () { sink.addSlice("ab%", 0, 3, false); - expect(results, equals([[$a, $b]])); + expect( + results, + equals([ + [$a, $b] + ])); - expect(() => sink.addSlice("ab%", 0, 3, true), - throwsFormatException); + expect(() => sink.addSlice("ab%", 0, 3, true), throwsFormatException); }); test("rejects danging digit detected in addSlice()", () { sink.addSlice("ab%2", 0, 3, false); - expect(results, equals([[$a, $b]])); + expect( + results, + equals([ + [$a, $b] + ])); - expect(() => sink.addSlice("ab%2", 0, 3, true), - throwsFormatException); + expect(() => sink.addSlice("ab%2", 0, 3, true), throwsFormatException); }); }); @@ -185,8 +319,8 @@ void main() { expect(() => percent.decode("a$char"), throwsFormatException); expect(() => percent.decode("${char}a"), throwsFormatException); - var sink = percent.decoder.startChunkedConversion( - new StreamController(sync: true)); + var sink = percent.decoder + .startChunkedConversion(new StreamController(sync: true)); expect(() => sink.add(char), throwsFormatException); }); } From e26293255d943440b25dddc35e179346b4629529 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Wed, 2 Aug 2017 10:40:51 -0700 Subject: [PATCH 012/100] Use recommended analysis_options name, support Dart v2-dev, test on FF (dart-lang/convert#9) --- pkgs/convert/.travis.yml | 1 + pkgs/convert/{.analysis_options => analysis_options.yaml} | 0 pkgs/convert/pubspec.yaml | 4 ++-- 3 files changed, 3 insertions(+), 2 deletions(-) rename pkgs/convert/{.analysis_options => analysis_options.yaml} (100%) diff --git a/pkgs/convert/.travis.yml b/pkgs/convert/.travis.yml index 10d307b7..3c25288c 100644 --- a/pkgs/convert/.travis.yml +++ b/pkgs/convert/.travis.yml @@ -8,6 +8,7 @@ cache: - $HOME/.pub-cache dart_task: - test: --platform vm + - test: --platform firefox - test: --platform dartium install_dartium: true - dartanalyzer diff --git a/pkgs/convert/.analysis_options b/pkgs/convert/analysis_options.yaml similarity index 100% rename from pkgs/convert/.analysis_options rename to pkgs/convert/analysis_options.yaml diff --git a/pkgs/convert/pubspec.yaml b/pkgs/convert/pubspec.yaml index e442f97a..9f4c1c58 100644 --- a/pkgs/convert/pubspec.yaml +++ b/pkgs/convert/pubspec.yaml @@ -1,11 +1,11 @@ name: convert -version: 2.0.1 +version: 2.0.2-dev description: Utilities for converting between data representations. author: Dart Team homepage: https://github.com/dart-lang/convert environment: - sdk: '>=1.17.0-dev.6.2 <2.0.0' + sdk: '>=1.17.0 <2.0.0-dev.infinity' dependencies: charcode: '^1.1.0' From 5c6796b4bf483578dfa46c1ed5ce723cb9776788 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Mon, 18 Sep 2017 18:07:32 -0700 Subject: [PATCH 013/100] Remove -dev.infinity in SDK upper constraint No longer require --- pkgs/convert/pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/convert/pubspec.yaml b/pkgs/convert/pubspec.yaml index 9f4c1c58..41dd9e90 100644 --- a/pkgs/convert/pubspec.yaml +++ b/pkgs/convert/pubspec.yaml @@ -5,7 +5,7 @@ author: Dart Team homepage: https://github.com/dart-lang/convert environment: - sdk: '>=1.17.0 <2.0.0-dev.infinity' + sdk: '>=1.17.0 <2.0.0' dependencies: charcode: '^1.1.0' From 2de436b1aea29cbacc000123b34b1690a3394e9f Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Wed, 14 Feb 2018 13:21:09 -0800 Subject: [PATCH 014/100] Stop testing Dartium (dart-lang/convert#12) Closes dart-lang/convert#11 --- pkgs/convert/.travis.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/pkgs/convert/.travis.yml b/pkgs/convert/.travis.yml index 3c25288c..d355076a 100644 --- a/pkgs/convert/.travis.yml +++ b/pkgs/convert/.travis.yml @@ -9,8 +9,6 @@ cache: dart_task: - test: --platform vm - test: --platform firefox - - test: --platform dartium - install_dartium: true - dartanalyzer - dartfmt matrix: From 5a002160ca649380dc014702543704ccba156f53 Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Wed, 2 May 2018 12:59:19 -0700 Subject: [PATCH 015/100] Fix a Dart 2 runtime test failure (dart-lang/convert#14) --- pkgs/convert/test/byte_accumulator_sink_test.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/convert/test/byte_accumulator_sink_test.dart b/pkgs/convert/test/byte_accumulator_sink_test.dart index 123baa8e..332e71ca 100644 --- a/pkgs/convert/test/byte_accumulator_sink_test.dart +++ b/pkgs/convert/test/byte_accumulator_sink_test.dart @@ -6,7 +6,7 @@ import 'package:convert/convert.dart'; import 'package:test/test.dart'; void main() { - var sink; + ByteAccumulatorSink sink; setUp(() { sink = new ByteAccumulatorSink(); }); From 16ef0532fb54e1c60400fc205b7af4b233ae7a5c Mon Sep 17 00:00:00 2001 From: Patrice Chalin Date: Wed, 18 Jul 2018 16:47:34 -0400 Subject: [PATCH 016/100] chore: set max SDK version to <3.0.0 (dart-lang/convert#15) --- pkgs/convert/CHANGELOG.md | 4 ++++ pkgs/convert/analysis_options.yaml | 2 -- pkgs/convert/pubspec.yaml | 10 +++++----- 3 files changed, 9 insertions(+), 7 deletions(-) delete mode 100644 pkgs/convert/analysis_options.yaml diff --git a/pkgs/convert/CHANGELOG.md b/pkgs/convert/CHANGELOG.md index 984a0eed..51996092 100644 --- a/pkgs/convert/CHANGELOG.md +++ b/pkgs/convert/CHANGELOG.md @@ -1,3 +1,7 @@ +## 2.0.2 + +* Set max SDK version to `<3.0.0`, and adjust other dependencies. + ## 2.0.1 * `PercentEncoder` no longer encodes digits. This follows the specified diff --git a/pkgs/convert/analysis_options.yaml b/pkgs/convert/analysis_options.yaml deleted file mode 100644 index a10d4c5a..00000000 --- a/pkgs/convert/analysis_options.yaml +++ /dev/null @@ -1,2 +0,0 @@ -analyzer: - strong-mode: true diff --git a/pkgs/convert/pubspec.yaml b/pkgs/convert/pubspec.yaml index 41dd9e90..d6bfdb47 100644 --- a/pkgs/convert/pubspec.yaml +++ b/pkgs/convert/pubspec.yaml @@ -1,15 +1,15 @@ name: convert -version: 2.0.2-dev +version: 2.0.2 description: Utilities for converting between data representations. author: Dart Team homepage: https://github.com/dart-lang/convert environment: - sdk: '>=1.17.0 <2.0.0' + sdk: '>=1.17.0 <3.0.0' dependencies: - charcode: '^1.1.0' - typed_data: '^1.1.0' + charcode: ^1.1.0 + typed_data: ^1.1.0 dev_dependencies: - test: '^0.12.0' + test: '>=0.12.0 <2.0.0' From fd09f82f480f866c485884000107846e1e303861 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Fri, 2 Nov 2018 13:15:04 -0700 Subject: [PATCH 017/100] Test on Chrome on Travis (dart-lang/convert#16) --- pkgs/convert/.travis.yml | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/pkgs/convert/.travis.yml b/pkgs/convert/.travis.yml index d355076a..0e7bde85 100644 --- a/pkgs/convert/.travis.yml +++ b/pkgs/convert/.travis.yml @@ -1,17 +1,24 @@ language: dart -sudo: false + dart: - dev - stable -cache: - directories: - - $HOME/.pub-cache + dart_task: - test: --platform vm - - test: --platform firefox + - test: --platform chrome - dartanalyzer - dartfmt + matrix: exclude: - dart: dev dart_task: dartfmt + +# Only building master means that we don't run two builds for each pull request. +branches: + only: [master] + +cache: + directories: + - $HOME/.pub-cache From 1da0fa014dd701a908d0df74d8876d4114a75299 Mon Sep 17 00:00:00 2001 From: Jonas Finnemann Jensen Date: Wed, 12 Dec 2018 19:35:58 +0100 Subject: [PATCH 018/100] Added IdentityCodec (dart-lang/convert#17) Added IdentityCodec --- pkgs/convert/CHANGELOG.md | 5 ++++ pkgs/convert/lib/convert.dart | 1 + pkgs/convert/lib/src/identity_codec.dart | 28 ++++++++++++++++++++++ pkgs/convert/pubspec.yaml | 2 +- pkgs/convert/test/identity_codec_test.dart | 23 ++++++++++++++++++ 5 files changed, 58 insertions(+), 1 deletion(-) create mode 100644 pkgs/convert/lib/src/identity_codec.dart create mode 100644 pkgs/convert/test/identity_codec_test.dart diff --git a/pkgs/convert/CHANGELOG.md b/pkgs/convert/CHANGELOG.md index 51996092..f300a0c8 100644 --- a/pkgs/convert/CHANGELOG.md +++ b/pkgs/convert/CHANGELOG.md @@ -1,3 +1,8 @@ +## 2.1.0 + + * Added an `IdentityCodec` which implements `Codec` for use as default + value for in functions accepting an optional `Codec` as parameter. + ## 2.0.2 * Set max SDK version to `<3.0.0`, and adjust other dependencies. diff --git a/pkgs/convert/lib/convert.dart b/pkgs/convert/lib/convert.dart index ad543e92..d745856f 100644 --- a/pkgs/convert/lib/convert.dart +++ b/pkgs/convert/lib/convert.dart @@ -7,5 +7,6 @@ library convert; export 'src/accumulator_sink.dart'; export 'src/byte_accumulator_sink.dart'; export 'src/hex.dart'; +export 'src/identity_codec.dart'; export 'src/percent.dart'; export 'src/string_accumulator_sink.dart'; diff --git a/pkgs/convert/lib/src/identity_codec.dart b/pkgs/convert/lib/src/identity_codec.dart new file mode 100644 index 00000000..19364815 --- /dev/null +++ b/pkgs/convert/lib/src/identity_codec.dart @@ -0,0 +1,28 @@ +import 'dart:convert'; + +class _IdentityConverter extends Converter { + const _IdentityConverter(); + T convert(T input) => input; +} + +/// A [Codec] that performs the identity conversion (changing nothing) in both +/// directions. +/// +/// The identity codec passes input directly to output in both directions. +/// This class can be used as a base when combining multiple codecs, +/// because fusing the identity codec with any other codec gives the other +/// codec back. +/// +/// Note, that when fused with another [Codec] the identity codec disppears. +class IdentityCodec extends Codec { + const IdentityCodec(); + + Converter get decoder => _IdentityConverter(); + Converter get encoder => _IdentityConverter(); + + /// Fuse with an other codec. + /// + /// Fusing with the identify converter is a no-op, so this always return + /// [other]. + Codec fuse(Codec other) => other; +} diff --git a/pkgs/convert/pubspec.yaml b/pkgs/convert/pubspec.yaml index d6bfdb47..f3a4d672 100644 --- a/pkgs/convert/pubspec.yaml +++ b/pkgs/convert/pubspec.yaml @@ -1,5 +1,5 @@ name: convert -version: 2.0.2 +version: 2.1.0 description: Utilities for converting between data representations. author: Dart Team homepage: https://github.com/dart-lang/convert diff --git a/pkgs/convert/test/identity_codec_test.dart b/pkgs/convert/test/identity_codec_test.dart new file mode 100644 index 00000000..658027a5 --- /dev/null +++ b/pkgs/convert/test/identity_codec_test.dart @@ -0,0 +1,23 @@ +import 'dart:convert'; +import 'package:convert/convert.dart'; +import 'package:test/test.dart'; + +void main() { + group('IdentityCodec', () { + test('encode', () { + final codec = IdentityCodec(); + expect(codec.encode('hello-world'), equals('hello-world')); + }); + + test('decode', () { + final codec = IdentityCodec(); + expect(codec.decode('hello-world'), equals('hello-world')); + }); + + test('fuse', () { + final stringCodec = IdentityCodec(); + final utf8Strings = stringCodec.fuse(utf8); + expect(utf8Strings, equals(utf8)); + }); + }); +} From db8d7657971b536771065342cd46c8cd968a42b6 Mon Sep 17 00:00:00 2001 From: Aaron Lademann Date: Wed, 19 Dec 2018 11:05:28 -0700 Subject: [PATCH 019/100] Make _IdentityConverter compatible with Dart SDK 1.x (dart-lang/convert#18) Fixes DDC compilation regression introduced by dart-lang/convert#17 --- pkgs/convert/CHANGELOG.md | 4 ++++ pkgs/convert/lib/src/identity_codec.dart | 6 +++--- pkgs/convert/pubspec.yaml | 2 +- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/pkgs/convert/CHANGELOG.md b/pkgs/convert/CHANGELOG.md index f300a0c8..d3b34108 100644 --- a/pkgs/convert/CHANGELOG.md +++ b/pkgs/convert/CHANGELOG.md @@ -1,3 +1,7 @@ +## 2.1.1 + + * Fixed a DDC compilation regression for consumers using the Dart 1.x SDK that was introduced in `2.1.0`. + ## 2.1.0 * Added an `IdentityCodec` which implements `Codec` for use as default diff --git a/pkgs/convert/lib/src/identity_codec.dart b/pkgs/convert/lib/src/identity_codec.dart index 19364815..3a2d028b 100644 --- a/pkgs/convert/lib/src/identity_codec.dart +++ b/pkgs/convert/lib/src/identity_codec.dart @@ -1,7 +1,7 @@ import 'dart:convert'; class _IdentityConverter extends Converter { - const _IdentityConverter(); + _IdentityConverter(); T convert(T input) => input; } @@ -17,8 +17,8 @@ class _IdentityConverter extends Converter { class IdentityCodec extends Codec { const IdentityCodec(); - Converter get decoder => _IdentityConverter(); - Converter get encoder => _IdentityConverter(); + Converter get decoder => new _IdentityConverter(); + Converter get encoder => new _IdentityConverter(); /// Fuse with an other codec. /// diff --git a/pkgs/convert/pubspec.yaml b/pkgs/convert/pubspec.yaml index f3a4d672..e788c487 100644 --- a/pkgs/convert/pubspec.yaml +++ b/pkgs/convert/pubspec.yaml @@ -1,5 +1,5 @@ name: convert -version: 2.1.0 +version: 2.1.1 description: Utilities for converting between data representations. author: Dart Team homepage: https://github.com/dart-lang/convert From 07f50d499e6545276a4d83d69a9986aee89a0fe9 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Fri, 26 Apr 2019 15:26:16 -0700 Subject: [PATCH 020/100] Enable and fix standard lints, test on oldest supported SDK (dart-lang/convert#20) --- pkgs/convert/.travis.yml | 7 ++- pkgs/convert/analysis_options.yaml | 43 +++++++++++++++++++ pkgs/convert/codereview.settings | 3 -- pkgs/convert/lib/src/accumulator_sink.dart | 4 +- .../lib/src/byte_accumulator_sink.dart | 8 ++-- pkgs/convert/lib/src/hex.dart | 6 +-- pkgs/convert/lib/src/hex/decoder.dart | 22 +++++----- pkgs/convert/lib/src/hex/encoder.dart | 10 ++--- pkgs/convert/lib/src/identity_codec.dart | 4 +- pkgs/convert/lib/src/percent.dart | 6 +-- pkgs/convert/lib/src/percent/decoder.dart | 20 ++++----- pkgs/convert/lib/src/percent/encoder.dart | 8 ++-- .../lib/src/string_accumulator_sink.dart | 6 +-- pkgs/convert/lib/src/utils.dart | 2 +- pkgs/convert/pubspec.yaml | 7 +-- pkgs/convert/test/accumulator_sink_test.dart | 2 +- .../test/byte_accumulator_sink_test.dart | 2 +- pkgs/convert/test/hex_test.dart | 12 +++--- pkgs/convert/test/percent_test.dart | 12 +++--- .../test/string_accumulator_sink_test.dart | 2 +- 20 files changed, 113 insertions(+), 73 deletions(-) create mode 100644 pkgs/convert/analysis_options.yaml delete mode 100644 pkgs/convert/codereview.settings diff --git a/pkgs/convert/.travis.yml b/pkgs/convert/.travis.yml index 0e7bde85..e8ffe6de 100644 --- a/pkgs/convert/.travis.yml +++ b/pkgs/convert/.travis.yml @@ -2,16 +2,15 @@ language: dart dart: - dev - - stable + - 2.0.0 dart_task: - test: --platform vm - test: --platform chrome - - dartanalyzer - - dartfmt + - dartanalyzer: --fatal-warnings --fatal-infos . matrix: - exclude: + include: - dart: dev dart_task: dartfmt diff --git a/pkgs/convert/analysis_options.yaml b/pkgs/convert/analysis_options.yaml new file mode 100644 index 00000000..0711acad --- /dev/null +++ b/pkgs/convert/analysis_options.yaml @@ -0,0 +1,43 @@ +include: package:pedantic/analysis_options.yaml +analyzer: + strong-mode: + implicit-casts: false +linter: + rules: + - avoid_empty_else + - avoid_init_to_null + - avoid_null_checks_in_equality_operators + - avoid_unused_constructor_parameters + - await_only_futures + - camel_case_types + - cancel_subscriptions + - constant_identifier_names + - control_flow_in_finally + - directives_ordering + - empty_catches + - empty_constructor_bodies + - empty_statements + - hash_and_equals + - implementation_imports + - iterable_contains_unrelated_type + - library_names + - library_prefixes + - list_remove_unrelated_type + - non_constant_identifier_names + - overridden_fields + - package_api_docs + - package_names + - package_prefixed_library_names + - prefer_equal_for_default_values + - prefer_final_fields + - prefer_generic_function_type_aliases + - prefer_is_not_empty + - slash_for_doc_comments + - test_types_in_equals + - throw_in_finally + - type_init_formals + - unnecessary_brace_in_string_interps + - unnecessary_const + - unnecessary_new + - unrelated_type_equality_checks + - valid_regexps diff --git a/pkgs/convert/codereview.settings b/pkgs/convert/codereview.settings deleted file mode 100644 index 82376363..00000000 --- a/pkgs/convert/codereview.settings +++ /dev/null @@ -1,3 +0,0 @@ -CODE_REVIEW_SERVER: http://codereview.chromium.org/ -VIEW_VC: https://github.com/dart-lang/convert/commit/ -CC_LIST: reviews@dartlang.org \ No newline at end of file diff --git a/pkgs/convert/lib/src/accumulator_sink.dart b/pkgs/convert/lib/src/accumulator_sink.dart index ca35f7ad..d92b4a8e 100644 --- a/pkgs/convert/lib/src/accumulator_sink.dart +++ b/pkgs/convert/lib/src/accumulator_sink.dart @@ -9,7 +9,7 @@ import 'dart:collection'; /// See also [ChunkedConversionSink.withCallback]. class AccumulatorSink implements Sink { /// An unmodifiable list of events passed to this sink so far. - List get events => new UnmodifiableListView(_events); + List get events => UnmodifiableListView(_events); final _events = []; /// Whether [close] has been called. @@ -25,7 +25,7 @@ class AccumulatorSink implements Sink { void add(T event) { if (_isClosed) { - throw new StateError("Can't add to a closed sink."); + throw StateError("Can't add to a closed sink."); } _events.add(event); diff --git a/pkgs/convert/lib/src/byte_accumulator_sink.dart b/pkgs/convert/lib/src/byte_accumulator_sink.dart index 10bd8ee0..d1fab06f 100644 --- a/pkgs/convert/lib/src/byte_accumulator_sink.dart +++ b/pkgs/convert/lib/src/byte_accumulator_sink.dart @@ -15,9 +15,9 @@ class ByteAccumulatorSink extends ByteConversionSinkBase { /// /// The returned [Uint8List] is viewing a shared buffer, so it should not be /// changed and any bytes outside the view should not be accessed. - Uint8List get bytes => new Uint8List.view(_buffer.buffer, 0, _buffer.length); + Uint8List get bytes => Uint8List.view(_buffer.buffer, 0, _buffer.length); - final _buffer = new Uint8Buffer(); + final _buffer = Uint8Buffer(); /// Whether [close] has been called. bool get isClosed => _isClosed; @@ -32,7 +32,7 @@ class ByteAccumulatorSink extends ByteConversionSinkBase { void add(List bytes) { if (_isClosed) { - throw new StateError("Can't add to a closed sink."); + throw StateError("Can't add to a closed sink."); } _buffer.addAll(bytes); @@ -40,7 +40,7 @@ class ByteAccumulatorSink extends ByteConversionSinkBase { void addSlice(List chunk, int start, int end, bool isLast) { if (_isClosed) { - throw new StateError("Can't add to a closed sink."); + throw StateError("Can't add to a closed sink."); } _buffer.addAll(chunk, start, end); diff --git a/pkgs/convert/lib/src/hex.dart b/pkgs/convert/lib/src/hex.dart index ec4451e4..28e9203b 100644 --- a/pkgs/convert/lib/src/hex.dart +++ b/pkgs/convert/lib/src/hex.dart @@ -6,14 +6,14 @@ library convert.hex; import 'dart:convert'; -import 'hex/encoder.dart'; import 'hex/decoder.dart'; +import 'hex/encoder.dart'; -export 'hex/encoder.dart' hide hexEncoder; export 'hex/decoder.dart' hide hexDecoder; +export 'hex/encoder.dart' hide hexEncoder; /// The canonical instance of [HexCodec]. -const hex = const HexCodec._(); +const hex = HexCodec._(); /// A codec that converts byte arrays to and from hexadecimal strings, following /// [the Base16 spec][rfc]. diff --git a/pkgs/convert/lib/src/hex/decoder.dart b/pkgs/convert/lib/src/hex/decoder.dart index c1c8febf..e37d5c96 100644 --- a/pkgs/convert/lib/src/hex/decoder.dart +++ b/pkgs/convert/lib/src/hex/decoder.dart @@ -10,7 +10,7 @@ import 'dart:typed_data'; import '../utils.dart'; /// The canonical instance of [HexDecoder]. -const hexDecoder = const HexDecoder._(); +const hexDecoder = HexDecoder._(); /// A converter that decodes hexadecimal strings into byte arrays. /// @@ -22,17 +22,17 @@ class HexDecoder extends Converter> { List convert(String string) { if (!string.length.isEven) { - throw new FormatException( + throw FormatException( "Invalid input length, must be even.", string, string.length); } - var bytes = new Uint8List(string.length ~/ 2); + var bytes = Uint8List(string.length ~/ 2); _decode(string.codeUnits, 0, string.length, bytes, 0); return bytes; } StringConversionSink startChunkedConversion(Sink> sink) => - new _HexDecoderSink(sink); + _HexDecoderSink(sink); } /// A conversion sink for chunked hexadecimal decoding. @@ -61,11 +61,11 @@ class _HexDecoderSink extends StringConversionSinkBase { Uint8List bytes; int bytesStart; if (_lastDigit == null) { - bytes = new Uint8List((end - start) ~/ 2); + bytes = Uint8List((end - start) ~/ 2); bytesStart = 0; } else { var hexPairs = (end - start - 1) ~/ 2; - bytes = new Uint8List(1 + hexPairs); + bytes = Uint8List(1 + hexPairs); bytes[0] = _lastDigit + digitForCodeUnit(codeUnits, start); start++; bytesStart = 1; @@ -78,7 +78,7 @@ class _HexDecoderSink extends StringConversionSinkBase { } ByteConversionSink asUtf8Sink(bool allowMalformed) => - new _HexDecoderByteSink(_sink); + _HexDecoderByteSink(_sink); void close() => _close(); @@ -86,7 +86,7 @@ class _HexDecoderSink extends StringConversionSinkBase { /// if one is thrown. void _close([String string, int index]) { if (_lastDigit != null) { - throw new FormatException( + throw FormatException( "Input ended with incomplete encoded byte.", string, index); } @@ -121,11 +121,11 @@ class _HexDecoderByteSink extends ByteConversionSinkBase { Uint8List bytes; int bytesStart; if (_lastDigit == null) { - bytes = new Uint8List((end - start) ~/ 2); + bytes = Uint8List((end - start) ~/ 2); bytesStart = 0; } else { var hexPairs = (end - start - 1) ~/ 2; - bytes = new Uint8List(1 + hexPairs); + bytes = Uint8List(1 + hexPairs); bytes[0] = _lastDigit + digitForCodeUnit(chunk, start); start++; bytesStart = 1; @@ -143,7 +143,7 @@ class _HexDecoderByteSink extends ByteConversionSinkBase { /// if one is thrown. void _close([List chunk, int index]) { if (_lastDigit != null) { - throw new FormatException( + throw FormatException( "Input ended with incomplete encoded byte.", chunk, index); } diff --git a/pkgs/convert/lib/src/hex/encoder.dart b/pkgs/convert/lib/src/hex/encoder.dart index 9339cda5..3ed85c73 100644 --- a/pkgs/convert/lib/src/hex/encoder.dart +++ b/pkgs/convert/lib/src/hex/encoder.dart @@ -10,7 +10,7 @@ import 'dart:typed_data'; import 'package:charcode/ascii.dart'; /// The canonical instance of [HexEncoder]. -const hexEncoder = const HexEncoder._(); +const hexEncoder = HexEncoder._(); /// A converter that encodes byte arrays into hexadecimal strings. /// @@ -22,7 +22,7 @@ class HexEncoder extends Converter, String> { String convert(List bytes) => _convert(bytes, 0, bytes.length); ByteConversionSink startChunkedConversion(Sink sink) => - new _HexEncoderSink(sink); + _HexEncoderSink(sink); } /// A conversion sink for chunked hexadecimal encoding. @@ -51,7 +51,7 @@ String _convert(List bytes, int start, int end) { // A Uint8List is more efficient than a StringBuffer given that we know that // we're only emitting ASCII-compatible characters, and that we know the // length ahead of time. - var buffer = new Uint8List((end - start) * 2); + var buffer = Uint8List((end - start) * 2); var bufferIndex = 0; // A bitwise OR of all bytes in [bytes]. This allows us to check for @@ -69,13 +69,13 @@ String _convert(List bytes, int start, int end) { buffer[bufferIndex++] = _codeUnitForDigit(byte & 0x0F); } - if (byteOr >= 0 && byteOr <= 255) return new String.fromCharCodes(buffer); + if (byteOr >= 0 && byteOr <= 255) return String.fromCharCodes(buffer); // If there was an invalid byte, find it and throw an exception. for (var i = start; i < end; i++) { var byte = bytes[i]; if (byte >= 0 && byte <= 0xff) continue; - throw new FormatException( + throw FormatException( "Invalid byte ${byte < 0 ? "-" : ""}0x${byte.abs().toRadixString(16)}.", bytes, i); diff --git a/pkgs/convert/lib/src/identity_codec.dart b/pkgs/convert/lib/src/identity_codec.dart index 3a2d028b..9da7bca0 100644 --- a/pkgs/convert/lib/src/identity_codec.dart +++ b/pkgs/convert/lib/src/identity_codec.dart @@ -17,8 +17,8 @@ class _IdentityConverter extends Converter { class IdentityCodec extends Codec { const IdentityCodec(); - Converter get decoder => new _IdentityConverter(); - Converter get encoder => new _IdentityConverter(); + Converter get decoder => _IdentityConverter(); + Converter get encoder => _IdentityConverter(); /// Fuse with an other codec. /// diff --git a/pkgs/convert/lib/src/percent.dart b/pkgs/convert/lib/src/percent.dart index 3bb3da14..b06d08fc 100644 --- a/pkgs/convert/lib/src/percent.dart +++ b/pkgs/convert/lib/src/percent.dart @@ -6,14 +6,14 @@ library convert.percent; import 'dart:convert'; -import 'percent/encoder.dart'; import 'percent/decoder.dart'; +import 'percent/encoder.dart'; -export 'percent/encoder.dart' hide percentEncoder; export 'percent/decoder.dart' hide percentDecoder; +export 'percent/encoder.dart' hide percentEncoder; /// The canonical instance of [PercentCodec]. -const percent = const PercentCodec._(); +const percent = PercentCodec._(); // TODO(nweiz): Add flags to support generating and interpreting "+" as a space // character. Also add an option for custom sets of unreserved characters. diff --git a/pkgs/convert/lib/src/percent/decoder.dart b/pkgs/convert/lib/src/percent/decoder.dart index 334e754f..cc403ff2 100644 --- a/pkgs/convert/lib/src/percent/decoder.dart +++ b/pkgs/convert/lib/src/percent/decoder.dart @@ -12,7 +12,7 @@ import 'package:typed_data/typed_data.dart'; import '../utils.dart'; /// The canonical instance of [PercentDecoder]. -const percentDecoder = const PercentDecoder._(); +const percentDecoder = PercentDecoder._(); const _lastPercent = -1; @@ -29,11 +29,11 @@ class PercentDecoder extends Converter> { const PercentDecoder._(); List convert(String string) { - var buffer = new Uint8Buffer(); + var buffer = Uint8Buffer(); var lastDigit = _decode(string.codeUnits, 0, string.length, buffer); if (lastDigit != null) { - throw new FormatException( + throw FormatException( "Input ended with incomplete encoded byte.", string, string.length); } @@ -41,7 +41,7 @@ class PercentDecoder extends Converter> { } StringConversionSink startChunkedConversion(Sink> sink) => - new _PercentDecoderSink(sink); + _PercentDecoderSink(sink); } /// A conversion sink for chunked percent-encoded decoding. @@ -68,7 +68,7 @@ class _PercentDecoderSink extends StringConversionSinkBase { return; } - var buffer = new Uint8Buffer(); + var buffer = Uint8Buffer(); var codeUnits = string.codeUnits; if (_lastDigit == _lastPercent) { _lastDigit = 16 * digitForCodeUnit(codeUnits, start); @@ -92,7 +92,7 @@ class _PercentDecoderSink extends StringConversionSinkBase { } ByteConversionSink asUtf8Sink(bool allowMalformed) => - new _PercentDecoderByteSink(_sink); + _PercentDecoderByteSink(_sink); void close() => _close(); @@ -100,7 +100,7 @@ class _PercentDecoderSink extends StringConversionSinkBase { /// if one is thrown. void _close([String string, int index]) { if (_lastDigit != null) { - throw new FormatException( + throw FormatException( "Input ended with incomplete encoded byte.", string, index); } @@ -134,7 +134,7 @@ class _PercentDecoderByteSink extends ByteConversionSinkBase { return; } - var buffer = new Uint8Buffer(); + var buffer = Uint8Buffer(); if (_lastDigit == _lastPercent) { _lastDigit = 16 * digitForCodeUnit(chunk, start); start++; @@ -162,7 +162,7 @@ class _PercentDecoderByteSink extends ByteConversionSinkBase { /// if one is thrown. void _close([List chunk, int index]) { if (_lastDigit != null) { - throw new FormatException( + throw FormatException( "Input ended with incomplete encoded byte.", chunk, index); } @@ -235,7 +235,7 @@ void _checkForInvalidCodeUnit( for (var i = start; i < end; i++) { var codeUnit = codeUnits[i]; if (codeUnit >= 0 && codeUnit <= 0x7f) continue; - throw new FormatException( + throw FormatException( "Non-ASCII code unit " "U+${codeUnit.toRadixString(16).padLeft(4, '0')}", codeUnits, diff --git a/pkgs/convert/lib/src/percent/encoder.dart b/pkgs/convert/lib/src/percent/encoder.dart index d4419a9e..390316f5 100644 --- a/pkgs/convert/lib/src/percent/encoder.dart +++ b/pkgs/convert/lib/src/percent/encoder.dart @@ -9,7 +9,7 @@ import 'dart:convert'; import 'package:charcode/ascii.dart'; /// The canonical instance of [PercentEncoder]. -const percentEncoder = const PercentEncoder._(); +const percentEncoder = PercentEncoder._(); /// A converter that encodes byte arrays into percent-encoded strings. /// @@ -25,7 +25,7 @@ class PercentEncoder extends Converter, String> { String convert(List bytes) => _convert(bytes, 0, bytes.length); ByteConversionSink startChunkedConversion(Sink sink) => - new _PercentEncoderSink(sink); + _PercentEncoderSink(sink); } /// A conversion sink for chunked percentadecimal encoding. @@ -51,7 +51,7 @@ class _PercentEncoderSink extends ByteConversionSinkBase { } String _convert(List bytes, int start, int end) { - var buffer = new StringBuffer(); + var buffer = StringBuffer(); // A bitwise OR of all bytes in [bytes]. This allows us to check for // out-of-range bytes without adding more branches than necessary to the @@ -92,7 +92,7 @@ String _convert(List bytes, int start, int end) { for (var i = start; i < end; i++) { var byte = bytes[i]; if (byte >= 0 && byte <= 0xff) continue; - throw new FormatException( + throw FormatException( "Invalid byte ${byte < 0 ? "-" : ""}0x${byte.abs().toRadixString(16)}.", bytes, i); diff --git a/pkgs/convert/lib/src/string_accumulator_sink.dart b/pkgs/convert/lib/src/string_accumulator_sink.dart index 95e22486..c8bdf750 100644 --- a/pkgs/convert/lib/src/string_accumulator_sink.dart +++ b/pkgs/convert/lib/src/string_accumulator_sink.dart @@ -10,7 +10,7 @@ import 'dart:convert'; class StringAccumulatorSink extends StringConversionSinkBase { /// The string accumulated so far. String get string => _buffer.toString(); - final _buffer = new StringBuffer(); + final _buffer = StringBuffer(); /// Whether [close] has been called. bool get isClosed => _isClosed; @@ -25,7 +25,7 @@ class StringAccumulatorSink extends StringConversionSinkBase { void add(String chunk) { if (_isClosed) { - throw new StateError("Can't add to a closed sink."); + throw StateError("Can't add to a closed sink."); } _buffer.write(chunk); @@ -33,7 +33,7 @@ class StringAccumulatorSink extends StringConversionSinkBase { void addSlice(String chunk, int start, int end, bool isLast) { if (_isClosed) { - throw new StateError("Can't add to a closed sink."); + throw StateError("Can't add to a closed sink."); } _buffer.write(chunk.substring(start, end)); diff --git a/pkgs/convert/lib/src/utils.dart b/pkgs/convert/lib/src/utils.dart index 79907797..4001e3e3 100644 --- a/pkgs/convert/lib/src/utils.dart +++ b/pkgs/convert/lib/src/utils.dart @@ -31,7 +31,7 @@ int digitForCodeUnit(List codeUnits, int index) { if ($a <= letter && letter <= $f) return letter - $a + 10; } - throw new FormatException( + throw FormatException( "Invalid hexadecimal code unit " "U+${codeUnit.toRadixString(16).padLeft(4, '0')}.", codeUnits, diff --git a/pkgs/convert/pubspec.yaml b/pkgs/convert/pubspec.yaml index e788c487..8002b7c9 100644 --- a/pkgs/convert/pubspec.yaml +++ b/pkgs/convert/pubspec.yaml @@ -1,15 +1,16 @@ name: convert -version: 2.1.1 +version: 2.1.2-dev description: Utilities for converting between data representations. author: Dart Team homepage: https://github.com/dart-lang/convert environment: - sdk: '>=1.17.0 <3.0.0' + sdk: '>=2.0.0 <3.0.0' dependencies: charcode: ^1.1.0 typed_data: ^1.1.0 dev_dependencies: - test: '>=0.12.0 <2.0.0' + pedantic: ^1.0.0 + test: ^1.0.0 \ No newline at end of file diff --git a/pkgs/convert/test/accumulator_sink_test.dart b/pkgs/convert/test/accumulator_sink_test.dart index 81fe1db7..2c280e12 100644 --- a/pkgs/convert/test/accumulator_sink_test.dart +++ b/pkgs/convert/test/accumulator_sink_test.dart @@ -8,7 +8,7 @@ import 'package:test/test.dart'; void main() { var sink; setUp(() { - sink = new AccumulatorSink(); + sink = AccumulatorSink(); }); test("provides access to events as they're added", () { diff --git a/pkgs/convert/test/byte_accumulator_sink_test.dart b/pkgs/convert/test/byte_accumulator_sink_test.dart index 332e71ca..31ea03a4 100644 --- a/pkgs/convert/test/byte_accumulator_sink_test.dart +++ b/pkgs/convert/test/byte_accumulator_sink_test.dart @@ -8,7 +8,7 @@ import 'package:test/test.dart'; void main() { ByteAccumulatorSink sink; setUp(() { - sink = new ByteAccumulatorSink(); + sink = ByteAccumulatorSink(); }); test("provides access to the concatenated bytes", () { diff --git a/pkgs/convert/test/hex_test.dart b/pkgs/convert/test/hex_test.dart index 95f0e905..78db5fd8 100644 --- a/pkgs/convert/test/hex_test.dart +++ b/pkgs/convert/test/hex_test.dart @@ -17,7 +17,7 @@ void main() { group("with chunked conversion", () { test("converts byte arrays to hex", () { var results = []; - var controller = new StreamController(sync: true); + var controller = StreamController(sync: true); controller.stream.listen(results.add); var sink = hex.encoder.startChunkedConversion(controller.sink); @@ -30,7 +30,7 @@ void main() { test("handles empty and single-byte lists", () { var results = []; - var controller = new StreamController(sync: true); + var controller = StreamController(sync: true); controller.stream.listen(results.add); var sink = hex.encoder.startChunkedConversion(controller.sink); @@ -49,7 +49,7 @@ void main() { expect(() => hex.encode([0x100]), throwsFormatException); var sink = - hex.encoder.startChunkedConversion(new StreamController(sync: true)); + hex.encoder.startChunkedConversion(StreamController(sync: true)); expect(() => sink.add([0x100]), throwsFormatException); }); }); @@ -83,7 +83,7 @@ void main() { var sink; setUp(() { results = []; - var controller = new StreamController>(sync: true); + var controller = StreamController>(sync: true); controller.stream.listen(results.add); sink = hex.decoder.startChunkedConversion(controller.sink); }); @@ -207,8 +207,8 @@ void main() { expect(() => hex.decode("a$char"), throwsFormatException); expect(() => hex.decode("${char}a"), throwsFormatException); - var sink = hex.decoder - .startChunkedConversion(new StreamController(sync: true)); + var sink = + hex.decoder.startChunkedConversion(StreamController(sync: true)); expect(() => sink.add(char), throwsFormatException); }); } diff --git a/pkgs/convert/test/percent_test.dart b/pkgs/convert/test/percent_test.dart index c2f0a3cd..d50ef320 100644 --- a/pkgs/convert/test/percent_test.dart +++ b/pkgs/convert/test/percent_test.dart @@ -115,7 +115,7 @@ void main() { group("with chunked conversion", () { test("percent-encodes byte arrays", () { var results = []; - var controller = new StreamController(sync: true); + var controller = StreamController(sync: true); controller.stream.listen(results.add); var sink = percent.encoder.startChunkedConversion(controller.sink); @@ -128,7 +128,7 @@ void main() { test("handles empty and single-byte lists", () { var results = []; - var controller = new StreamController(sync: true); + var controller = StreamController(sync: true); controller.stream.listen(results.add); var sink = percent.encoder.startChunkedConversion(controller.sink); @@ -146,8 +146,8 @@ void main() { test("rejects non-bytes", () { expect(() => percent.encode([0x100]), throwsFormatException); - var sink = percent.encoder - .startChunkedConversion(new StreamController(sync: true)); + var sink = + percent.encoder.startChunkedConversion(StreamController(sync: true)); expect(() => sink.add([0x100]), throwsFormatException); }); }); @@ -190,7 +190,7 @@ void main() { var sink; setUp(() { results = []; - var controller = new StreamController>(sync: true); + var controller = StreamController>(sync: true); controller.stream.listen(results.add); sink = percent.decoder.startChunkedConversion(controller.sink); }); @@ -320,7 +320,7 @@ void main() { expect(() => percent.decode("${char}a"), throwsFormatException); var sink = percent.decoder - .startChunkedConversion(new StreamController(sync: true)); + .startChunkedConversion(StreamController(sync: true)); expect(() => sink.add(char), throwsFormatException); }); } diff --git a/pkgs/convert/test/string_accumulator_sink_test.dart b/pkgs/convert/test/string_accumulator_sink_test.dart index 914dd930..2bef19b9 100644 --- a/pkgs/convert/test/string_accumulator_sink_test.dart +++ b/pkgs/convert/test/string_accumulator_sink_test.dart @@ -8,7 +8,7 @@ import 'package:test/test.dart'; void main() { var sink; setUp(() { - sink = new StringAccumulatorSink(); + sink = StringAccumulatorSink(); }); test("provides access to the concatenated string", () { From 4b71f313fac03e1c33b2dc69fa0434dcacababc8 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Wed, 18 Dec 2019 13:18:00 -0800 Subject: [PATCH 021/100] Ignore substantial failing lints from latest pedantic Cleanup .gitignore --- pkgs/convert/.gitignore | 8 +------- pkgs/convert/analysis_options.yaml | 6 ++++++ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/pkgs/convert/.gitignore b/pkgs/convert/.gitignore index 25a1df33..79f51c3d 100644 --- a/pkgs/convert/.gitignore +++ b/pkgs/convert/.gitignore @@ -1,9 +1,3 @@ -.buildlog -.DS_Store -.idea -.pub/ -.settings/ -build/ -packages +.dart_tool .packages pubspec.lock diff --git a/pkgs/convert/analysis_options.yaml b/pkgs/convert/analysis_options.yaml index 0711acad..dcd46cb0 100644 --- a/pkgs/convert/analysis_options.yaml +++ b/pkgs/convert/analysis_options.yaml @@ -2,6 +2,12 @@ include: package:pedantic/analysis_options.yaml analyzer: strong-mode: implicit-casts: false + + errors: + # Ignore still failing lints from latest pkg:pedantic + annotate_overrides: ignore + prefer_single_quotes: ignore + linter: rules: - avoid_empty_else From 6fc78e5e156ca0ed76d700a269307b4404caad0d Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Fri, 13 Mar 2020 12:06:39 -0700 Subject: [PATCH 022/100] remove author from pubspec --- pkgs/convert/pubspec.yaml | 1 - 1 file changed, 1 deletion(-) diff --git a/pkgs/convert/pubspec.yaml b/pkgs/convert/pubspec.yaml index 8002b7c9..bcb0c450 100644 --- a/pkgs/convert/pubspec.yaml +++ b/pkgs/convert/pubspec.yaml @@ -1,7 +1,6 @@ name: convert version: 2.1.2-dev description: Utilities for converting between data representations. -author: Dart Team homepage: https://github.com/dart-lang/convert environment: From 685bb32f45bd58e202776f516eacea24aafefa2c Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Tue, 28 Jul 2020 20:33:05 -0700 Subject: [PATCH 023/100] Delete .test_config No longer used --- pkgs/convert/.test_config | 3 --- 1 file changed, 3 deletions(-) delete mode 100644 pkgs/convert/.test_config diff --git a/pkgs/convert/.test_config b/pkgs/convert/.test_config deleted file mode 100644 index 352d2fee..00000000 --- a/pkgs/convert/.test_config +++ /dev/null @@ -1,3 +0,0 @@ -{ - "test_package": true -} From b026bb43f939de4772a383598cc9102542d87b50 Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Wed, 5 Aug 2020 10:01:39 -0700 Subject: [PATCH 024/100] Migrate to null safety (dart-lang/convert#32) --- pkgs/convert/.travis.yml | 32 +++++++--- pkgs/convert/analysis_options.yaml | 2 + pkgs/convert/lib/src/hex/decoder.dart | 14 ++--- pkgs/convert/lib/src/percent/decoder.dart | 14 ++--- pkgs/convert/pubspec.yaml | 63 ++++++++++++++++++- .../test/byte_accumulator_sink_test.dart | 2 +- pkgs/convert/test/hex_test.dart | 2 +- pkgs/convert/test/percent_test.dart | 2 +- 8 files changed, 102 insertions(+), 29 deletions(-) diff --git a/pkgs/convert/.travis.yml b/pkgs/convert/.travis.yml index e8ffe6de..6bd2b014 100644 --- a/pkgs/convert/.travis.yml +++ b/pkgs/convert/.travis.yml @@ -2,21 +2,33 @@ language: dart dart: - dev - - 2.0.0 -dart_task: - - test: --platform vm - - test: --platform chrome - - dartanalyzer: --fatal-warnings --fatal-infos . - -matrix: +jobs: include: - - dart: dev - dart_task: dartfmt + - stage: analyze_and_format + name: "Analyze" + os: linux + script: dartanalyzer --fatal-warnings --fatal-infos . + - stage: analyze_and_format + name: "Format" + os: linux + script: dartfmt -n --set-exit-if-changed . + - stage: test + name: "Vm Tests" + os: linux + script: pub run --enable-experiment=non-nullable test -p vm + - stage: test + name: "Web Tests" + os: linux + script: pub run --enable-experiment=non-nullable test -p chrome + +stages: + - analyze_and_format + - test # Only building master means that we don't run two builds for each pull request. branches: - only: [master] + only: [master, null_safety] cache: directories: diff --git a/pkgs/convert/analysis_options.yaml b/pkgs/convert/analysis_options.yaml index dcd46cb0..14d22d8d 100644 --- a/pkgs/convert/analysis_options.yaml +++ b/pkgs/convert/analysis_options.yaml @@ -7,6 +7,8 @@ analyzer: # Ignore still failing lints from latest pkg:pedantic annotate_overrides: ignore prefer_single_quotes: ignore + enable-experiment: + - non-nullable linter: rules: diff --git a/pkgs/convert/lib/src/hex/decoder.dart b/pkgs/convert/lib/src/hex/decoder.dart index e37d5c96..9e3a122d 100644 --- a/pkgs/convert/lib/src/hex/decoder.dart +++ b/pkgs/convert/lib/src/hex/decoder.dart @@ -45,7 +45,7 @@ class _HexDecoderSink extends StringConversionSinkBase { /// This will be non-`null` if the most recent string had an odd number of /// hexadecimal digits. Since it's the most significant digit, it's always a /// multiple of 16. - int _lastDigit; + int? _lastDigit; _HexDecoderSink(this._sink); @@ -66,7 +66,7 @@ class _HexDecoderSink extends StringConversionSinkBase { } else { var hexPairs = (end - start - 1) ~/ 2; bytes = Uint8List(1 + hexPairs); - bytes[0] = _lastDigit + digitForCodeUnit(codeUnits, start); + bytes[0] = _lastDigit! + digitForCodeUnit(codeUnits, start); start++; bytesStart = 1; } @@ -84,7 +84,7 @@ class _HexDecoderSink extends StringConversionSinkBase { /// Like [close], but includes [string] and [index] in the [FormatException] /// if one is thrown. - void _close([String string, int index]) { + void _close([String? string, int? index]) { if (_lastDigit != null) { throw FormatException( "Input ended with incomplete encoded byte.", string, index); @@ -104,7 +104,7 @@ class _HexDecoderByteSink extends ByteConversionSinkBase { /// This will be non-`null` if the most recent string had an odd number of /// hexadecimal digits. Since it's the most significant digit, it's always a /// multiple of 16. - int _lastDigit; + int? _lastDigit; _HexDecoderByteSink(this._sink); @@ -126,7 +126,7 @@ class _HexDecoderByteSink extends ByteConversionSinkBase { } else { var hexPairs = (end - start - 1) ~/ 2; bytes = Uint8List(1 + hexPairs); - bytes[0] = _lastDigit + digitForCodeUnit(chunk, start); + bytes[0] = _lastDigit! + digitForCodeUnit(chunk, start); start++; bytesStart = 1; } @@ -141,7 +141,7 @@ class _HexDecoderByteSink extends ByteConversionSinkBase { /// Like [close], but includes [chunk] and [index] in the [FormatException] /// if one is thrown. - void _close([List chunk, int index]) { + void _close([List? chunk, int? index]) { if (_lastDigit != null) { throw FormatException( "Input ended with incomplete encoded byte.", chunk, index); @@ -158,7 +158,7 @@ class _HexDecoderByteSink extends ByteConversionSinkBase { /// /// If there's a leftover digit at the end of the decoding, this returns that /// digit. Otherwise it returns `null`. -int _decode(List codeUnits, int sourceStart, int sourceEnd, +int? _decode(List codeUnits, int sourceStart, int sourceEnd, List destination, int destinationStart) { var destinationIndex = destinationStart; for (var i = sourceStart; i < sourceEnd - 1; i += 2) { diff --git a/pkgs/convert/lib/src/percent/decoder.dart b/pkgs/convert/lib/src/percent/decoder.dart index cc403ff2..fee9ca9a 100644 --- a/pkgs/convert/lib/src/percent/decoder.dart +++ b/pkgs/convert/lib/src/percent/decoder.dart @@ -56,7 +56,7 @@ class _PercentDecoderSink extends StringConversionSinkBase { /// most recent string ended with `%`. Otherwise, the most recent string ended /// with a `%` followed by a hexadecimal digit, and this is that digit. Since /// it's the most significant digit, it's always a multiple of 16. - int _lastDigit; + int? _lastDigit; _PercentDecoderSink(this._sink); @@ -81,7 +81,7 @@ class _PercentDecoderSink extends StringConversionSinkBase { } if (_lastDigit != null) { - buffer.add(_lastDigit + digitForCodeUnit(codeUnits, start)); + buffer.add(_lastDigit! + digitForCodeUnit(codeUnits, start)); start++; } @@ -98,7 +98,7 @@ class _PercentDecoderSink extends StringConversionSinkBase { /// Like [close], but includes [string] and [index] in the [FormatException] /// if one is thrown. - void _close([String string, int index]) { + void _close([String? string, int? index]) { if (_lastDigit != null) { throw FormatException( "Input ended with incomplete encoded byte.", string, index); @@ -120,7 +120,7 @@ class _PercentDecoderByteSink extends ByteConversionSinkBase { /// most recent string ended with `%`. Otherwise, the most recent string ended /// with a `%` followed by a hexadecimal digit, and this is that digit. Since /// it's the most significant digit, it's always a multiple of 16. - int _lastDigit; + int? _lastDigit; _PercentDecoderByteSink(this._sink); @@ -146,7 +146,7 @@ class _PercentDecoderByteSink extends ByteConversionSinkBase { } if (_lastDigit != null) { - buffer.add(_lastDigit + digitForCodeUnit(chunk, start)); + buffer.add(_lastDigit! + digitForCodeUnit(chunk, start)); start++; } @@ -160,7 +160,7 @@ class _PercentDecoderByteSink extends ByteConversionSinkBase { /// Like [close], but includes [chunk] and [index] in the [FormatException] /// if one is thrown. - void _close([List chunk, int index]) { + void _close([List? chunk, int? index]) { if (_lastDigit != null) { throw FormatException( "Input ended with incomplete encoded byte.", chunk, index); @@ -177,7 +177,7 @@ class _PercentDecoderByteSink extends ByteConversionSinkBase { /// /// If there's a leftover digit at the end of the decoding, this returns that /// digit. Otherwise it returns `null`. -int _decode(List codeUnits, int start, int end, Uint8Buffer buffer) { +int? _decode(List codeUnits, int start, int end, Uint8Buffer buffer) { // A bitwise OR of all code units in [codeUnits]. This allows us to check for // out-of-range code units without adding more branches than necessary to the // core loop. diff --git a/pkgs/convert/pubspec.yaml b/pkgs/convert/pubspec.yaml index bcb0c450..ff0eae6a 100644 --- a/pkgs/convert/pubspec.yaml +++ b/pkgs/convert/pubspec.yaml @@ -4,7 +4,7 @@ description: Utilities for converting between data representations. homepage: https://github.com/dart-lang/convert environment: - sdk: '>=2.0.0 <3.0.0' + sdk: '>=2.10.0-2.0.dev <2.10.0' dependencies: charcode: ^1.1.0 @@ -12,4 +12,63 @@ dependencies: dev_dependencies: pedantic: ^1.0.0 - test: ^1.0.0 \ No newline at end of file + test: ^1.0.0 + +dependency_overrides: + async: + git: git://github.com/dart-lang/async.git + boolean_selector: + git: git://github.com/dart-lang/boolean_selector.git + charcode: + git: git://github.com/dart-lang/charcode.git + collection: + git: git://github.com/dart-lang/collection.git + js: + git: + url: git://github.com/dart-lang/sdk.git + ref: 2-10-pkgs + path: pkg/js + matcher: + git: git://github.com/dart-lang/matcher.git + meta: + git: + url: git://github.com/dart-lang/sdk.git + ref: 2-10-pkgs + path: pkg/meta + path: + git: git://github.com/dart-lang/path.git + pedantic: + git: git://github.com/dart-lang/pedantic.git + pool: + git: git://github.com/dart-lang/pool.git + source_maps: + git: git://github.com/dart-lang/source_maps.git + source_map_stack_trace: + git: git://github.com/dart-lang/source_map_stack_trace.git + source_span: + git: git://github.com/dart-lang/source_span.git + stack_trace: + git: git://github.com/dart-lang/stack_trace.git + stream_channel: + git: git://github.com/dart-lang/stream_channel.git + string_scanner: + git: git://github.com/dart-lang/string_scanner.git + term_glyph: + git: git://github.com/dart-lang/term_glyph.git + test_api: + git: + url: git://github.com/dart-lang/test.git + ref: null_safety + path: pkgs/test_api + test_core: + git: + url: git://github.com/dart-lang/test.git + ref: null_safety + path: pkgs/test_core + test: + git: + url: git://github.com/dart-lang/test.git + ref: null_safety + path: pkgs/test + typed_data: + git: git://github.com/dart-lang/typed_data.git diff --git a/pkgs/convert/test/byte_accumulator_sink_test.dart b/pkgs/convert/test/byte_accumulator_sink_test.dart index 31ea03a4..773a0bed 100644 --- a/pkgs/convert/test/byte_accumulator_sink_test.dart +++ b/pkgs/convert/test/byte_accumulator_sink_test.dart @@ -6,7 +6,7 @@ import 'package:convert/convert.dart'; import 'package:test/test.dart'; void main() { - ByteAccumulatorSink sink; + late ByteAccumulatorSink sink; setUp(() { sink = ByteAccumulatorSink(); }); diff --git a/pkgs/convert/test/hex_test.dart b/pkgs/convert/test/hex_test.dart index 78db5fd8..bbb18086 100644 --- a/pkgs/convert/test/hex_test.dart +++ b/pkgs/convert/test/hex_test.dart @@ -79,7 +79,7 @@ void main() { }); group("with chunked conversion", () { - List> results; + late List> results; var sink; setUp(() { results = []; diff --git a/pkgs/convert/test/percent_test.dart b/pkgs/convert/test/percent_test.dart index d50ef320..7a7bf811 100644 --- a/pkgs/convert/test/percent_test.dart +++ b/pkgs/convert/test/percent_test.dart @@ -186,7 +186,7 @@ void main() { }); group("with chunked conversion", () { - List> results; + late List> results; var sink; setUp(() { results = []; From 8b9b571e8bae9118269c025b8d1b387823213c32 Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Wed, 5 Aug 2020 10:46:50 -0700 Subject: [PATCH 025/100] Update version and add changelog for null safety (dart-lang/convert#33) --- pkgs/convert/.travis.yml | 2 +- pkgs/convert/CHANGELOG.md | 11 +++++++++++ pkgs/convert/pubspec.yaml | 2 +- 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/pkgs/convert/.travis.yml b/pkgs/convert/.travis.yml index 6bd2b014..b634f677 100644 --- a/pkgs/convert/.travis.yml +++ b/pkgs/convert/.travis.yml @@ -28,7 +28,7 @@ stages: # Only building master means that we don't run two builds for each pull request. branches: - only: [master, null_safety] + only: [master] cache: directories: diff --git a/pkgs/convert/CHANGELOG.md b/pkgs/convert/CHANGELOG.md index d3b34108..37e25fd6 100644 --- a/pkgs/convert/CHANGELOG.md +++ b/pkgs/convert/CHANGELOG.md @@ -1,3 +1,14 @@ +## 2.2.0-nullsafety + +Pre-release for the null safety migration of this package. + +Note that 2.2.0 may not be the final stable null safety release version, we +reserve the right to release it as a 3.0.0 breaking change. + +This release will be pinned to only allow pre-release sdk versions starting from +2.10.0-2.0.dev, which is the first version where this package will appear in the +null safety allow list. + ## 2.1.1 * Fixed a DDC compilation regression for consumers using the Dart 1.x SDK that was introduced in `2.1.0`. diff --git a/pkgs/convert/pubspec.yaml b/pkgs/convert/pubspec.yaml index ff0eae6a..58978106 100644 --- a/pkgs/convert/pubspec.yaml +++ b/pkgs/convert/pubspec.yaml @@ -1,5 +1,5 @@ name: convert -version: 2.1.2-dev +version: 2.2.0-nullsafety description: Utilities for converting between data representations. homepage: https://github.com/dart-lang/convert From 2db2e80c5a9e1e4d2b297cc4e4554ccfa82c1d42 Mon Sep 17 00:00:00 2001 From: "Lasse R.H. Nielsen" Date: Tue, 22 Sep 2020 18:46:02 +0200 Subject: [PATCH 026/100] Add Code Page support. (dart-lang/convert#26) * Add "Code Page" support. An easy way to define an encoding as a mapping between bytes and code points. Includes definitions for the ISO-8859 family of code pages. --- pkgs/convert/CHANGELOG.md | 2 + pkgs/convert/lib/convert.dart | 1 + pkgs/convert/lib/src/codepage.dart | 431 +++++++++++++++++++++++++++ pkgs/convert/test/codepage_test.dart | 63 ++++ 4 files changed, 497 insertions(+) create mode 100644 pkgs/convert/lib/src/codepage.dart create mode 100644 pkgs/convert/test/codepage_test.dart diff --git a/pkgs/convert/CHANGELOG.md b/pkgs/convert/CHANGELOG.md index 37e25fd6..947ff113 100644 --- a/pkgs/convert/CHANGELOG.md +++ b/pkgs/convert/CHANGELOG.md @@ -9,6 +9,8 @@ This release will be pinned to only allow pre-release sdk versions starting from 2.10.0-2.0.dev, which is the first version where this package will appear in the null safety allow list. + * Added `CodePage` class for single-byte `Encoding` implementations. + ## 2.1.1 * Fixed a DDC compilation regression for consumers using the Dart 1.x SDK that was introduced in `2.1.0`. diff --git a/pkgs/convert/lib/convert.dart b/pkgs/convert/lib/convert.dart index d745856f..53a68d85 100644 --- a/pkgs/convert/lib/convert.dart +++ b/pkgs/convert/lib/convert.dart @@ -6,6 +6,7 @@ library convert; export 'src/accumulator_sink.dart'; export 'src/byte_accumulator_sink.dart'; +export 'src/codepage.dart'; export 'src/hex.dart'; export 'src/identity_codec.dart'; export 'src/percent.dart'; diff --git a/pkgs/convert/lib/src/codepage.dart b/pkgs/convert/lib/src/codepage.dart new file mode 100644 index 00000000..2cc5fbd3 --- /dev/null +++ b/pkgs/convert/lib/src/codepage.dart @@ -0,0 +1,431 @@ +// Copyright (c) 2020, 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 "dart:convert"; +import "dart:typed_data"; + +/// The ISO-8859-2/Latin-2 (Eastern European) code page. +final CodePage latin2 = + CodePage._bmp("latin-2", "$_ascii$_noControls$_top8859_2"); + +/// The ISO-8859-3/Latin-3 (South European) code page. +final CodePage latin3 = + CodePage._bmp("latin-3", "$_ascii$_noControls$_top8859_3"); + +/// The ISO-8859-4/Latin-4 (North European) code page. +final CodePage latin4 = + CodePage._bmp("latin-4", "$_ascii$_noControls$_top8859_4"); + +/// The ISO-8859-5/Latin-Cyrillic code page. +final CodePage latinCyrillic = + CodePage._bmp("cyrillic", "$_ascii$_noControls$_top8859_5"); + +/// The ISO-8859-6/Latin-Arabic code page. +final CodePage latinArabic = + CodePage._bmp("arabic", "$_ascii$_noControls$_top8859_6"); + +/// The ISO-8859-7/Latin-Greek code page. +final CodePage latinGreek = + CodePage._bmp("greek", "$_ascii$_noControls$_top8859_7"); + +/// The ISO-8859-7/Latin-Hebrew code page. +final CodePage latinHebrew = + CodePage._bmp("hebrew", "$_ascii$_noControls$_top8859_8"); + +/// The ISO-8859-9/Latin-5 (Turkish) code page. +final CodePage latin5 = + CodePage._bmp("latin-5", "$_ascii$_noControls$_top8859_9"); + +/// The ISO-8859-10/Latin-6 (Nordic) code page. +final CodePage latin6 = + CodePage._bmp("latin-6", "$_ascii$_noControls$_top8859_10"); + +/// The ISO-8859-11/Latin-Thai code page. +final CodePage latinThai = + CodePage._bmp("tis620", "$_ascii$_noControls$_top8859_11"); + +/// The ISO-8859-13/Latin-6 (Baltic Rim) code page. +final CodePage latin7 = + CodePage._bmp("latin-7", "$_ascii$_noControls$_top8859_13"); + +/// The ISO-8859-14/Latin-8 (Celtic) code page. +final CodePage latin8 = + CodePage._bmp("latin-8", "$_ascii$_noControls$_top8859_14"); + +/// The ISO-8859-15/Latin-9 (Western European revised) code page. +final CodePage latin9 = + CodePage._bmp("latin-9", "$_ascii$_noControls$_top8859_15"); + +/// The ISO-8859-16/Latin-10 (South Eastern European) code page. +final CodePage latin10 = + CodePage._bmp("latin-10", "$_ascii$_noControls$_top8859_16"); + +/// Characters in ISO-8859-2 above the ASCII and top control characters. +const _top8859_2 = "\xa0Ą˘Ł¤ĽŚ§¨ŠŞŤŹ\xadŽŻ°ą˛ł´ľśˇ¸šşťź˝žż" + "ŔÁÂĂÄĹĆÇČÉĘËĚÍÎĎĐŃŇÓÔŐÖ×ŘŮÚŰÜÝŢß" + "ŕáâăäĺćçčéęëěíîďđńňóôőö÷řůúűüýţ˙"; + +/// Characters in ISO-8859-3 above the ASCII and top control characters. +const _top8859_3 = "\xa0Ħ˘£\uFFFD¤Ĥ§¨İŞĞĴ\xad\uFFFDŻ°ħ²³´µĥ·¸ışğĵ½\uFFFDż" + "ÀÁÂ\uFFFDÄĊĈÇÈÉÊËÌÍÎÏ\uFFFDÑÒÓÔĠÖ×ĜÙÚÛÜŬŜß" + "àáâ\uFFFDäċĉçèéêëìíîï\uFFFDñòóôġö÷ĝùúûüŭŝ˙"; + +/// Characters in ISO-8859-4 above the ASCII and top control characters. +const _top8859_4 = "\xa0ĄĸŖ¤ĨĻ§¨ŠĒĢŦ\xadŽ¯°ą˛ŗ´ĩļˇ¸šēģŧŊžŋ" + "ĀÁÂÃÄÅÆĮČÉĘËĖÍÎĪĐŅŌĶÔÕÖ×ØŲÚÛÜŨŪß" + "āáâãäåæįčéęëėíîīđņōķôõö÷øųúûüũū˙"; + +/// Characters in ISO-8859-5 above the ASCII and top control characters. +const _top8859_5 = "\xa0ЁЂЃЄЅІЇЈЉЊЋЌ\xadЎЏАБВГДЕЖЗИЙКЛМНОП" + "РСТУФХЦЧШЩЪЫЬЭЮЯабвгдежзийклмноп" + "рстуфхцчшщъыьэюя№ёђѓєѕіїјљњћќ§ўџ"; + +/// Characters in ISO-8859-6 above the ASCII and top control characters. +const _top8859_6 = "\xa0\uFFFD\uFFFD\uFFFD¤\uFFFD\uFFFD\uFFFD" + "\uFFFD\uFFFD\uFFFD\uFFFD\u060c\xad\uFFFD\uFFFD" + "\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD" + "\uFFFD\uFFFD\uFFFD\u061b\uFFFD\uFFFD\uFFFD\u061f" + "\uFFFD\u0621\u0622\u0623\u0624\u0625\u0626\u0627" + "\u0628\u0629\u062a\u062b\u062c\u062d\u062e\u062f" + "\u0630\u0631\u0632\u0633\u0634\u0635\u0636\u0637" + "\u0638\u0639\u063a\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD" + "\u0640\u0641\u0642\u0643\u0644\u0645\u0646\u0647" + "\u0648\u0649\u064a\u064b\u064c\u064d\u064e\u064f" + "\u0650\u0651\u0652\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD" + "\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD"; + +/// Characters in ISO-8859-7 above the ASCII and top control characters. +const _top8859_7 = "\xa0‘’£€₯¦§¨©ͺ«¬\xad\uFFFD―°±²³΄΅Ά·ΈΉΊ»Ό½ΎΏ" + "ΐΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡ\uFFFDΣΤΥΦΧΨΩΪΫάέήί" + "ΰαβγδεζηθικλμνξοπρςστυφχψωϊϋόύώ\uFFFD"; + +/// Characters in ISO-8859-8 above the ASCII and top control characters. +const _top8859_8 = "\xa0\uFFFD¢£¤¥¦§¨©×«¬\xad®¯°±²³´µ¶·¸¹÷»¼½¾\uFFFD" + "\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD" + "\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD" + "\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD" + "\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD‗" + "\u05d0\u05d1\u05d2\u05d3\u05d4\u05d5\u05d6\u05d7" + "\u05d8\u05d9\u05da\u05db\u05dc\u05dd\u05de\u05df" + "\u05e0\u05e1\u05e2\u05e3\u05e4\u05e5\u05e6\u05e7" + "\u05e8\u05e9\u05ea\uFFFD\uFFFD\u200e\u200f\uFFFD"; + +/// Characters in ISO-8859-9 above the ASCII and top control characters. +const _top8859_9 = "\xa0¡¢£¤¥¦§¨©ª«¬\xad®¯°±²³´µ¶·¸¹º»¼½¾¿" + "ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏĞÑÒÓÔÕÖ×ØÙÚÛÜİŞß" + "àáâãäåæçèéêëìíîïğñòóôõö÷øùúûüışÿ"; + +/// Characters in ISO-8859-10 above the ASCII and top control characters. +const _top8859_10 = "\xa0ĄĒĢĪĨĶ§ĻĐŠŦŽ\xadŪŊ°ąēģīĩķ·ļđšŧž―ūŋ" + "ĀÁÂÃÄÅÆĮČÉĘËĖÍÎÏÐŅŌÓÔÕÖŨØŲÚÛÜÝÞß" + "āáâãäåæįčéęëėíîïðņōóôõöũøųúûüýþĸ"; + +/// Characters in ISO-8859-11 above the ASCII and top control characters. +const _top8859_11 = "\xa0กขฃคฅฆงจฉชซฌญฎฏฐฑฒณดตถทธนบปผฝพฟ" + "ภมยรฤลฦวศษสหฬอฮฯะัาำิีึืฺุู\uFFFD\uFFFD\uFFFD\uFFFD฿" + "เแโใไๅๆ็่้๊๋์ํ๎๏๐๑๒๓๔๕๖๗๘๙๚๛\uFFFD\uFFFD\uFFFD\uFFFD"; + +/// Characters in ISO-8859-13 above the ASCII and top control characters. +const _top8859_13 = "\xa0”¢£¤„¦§Ø©Ŗ«¬\xad®Æ°±²³“µ¶·ø¹ŗ»¼½¾æ" + "ĄĮĀĆÄÅĘĒČÉŹĖĢĶĪĻŠŃŅÓŌÕÖ×ŲŁŚŪÜŻŽß" + "ąįāćäåęēčéźėģķīļšńņóōõö÷ųłśūüżž’"; + +/// Characters in ISO-8859-14 above the ASCII and top control characters. +const _top8859_14 = "\xa0Ḃḃ£ĊċḊ§Ẁ©ẂḋỲ\xad®ŸḞḟĠġṀṁ¶ṖẁṗẃṠỳẄẅṡ" + "ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏŴÑÒÓÔÕÖṪØÙÚÛÜÝŶß" + "àáâãäåæçèéêëìíîïŵñòóôõöṫøùúûüýŷÿ"; + +/// Characters in ISO-8859-15 above the ASCII and top control characters. +const _top8859_15 = "\xa0¡¢£€¥Š§š©ª«¬\xad®¯°±²³Žµ¶·ž¹º»ŒœŸ¿" + "ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞß" + "àáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ"; + +/// Characters in ISO-8859-16 above the ASCII and top control characters. +const _top8859_16 = "\xa0ĄąŁ€„Š§š©Ș«Ź\xadźŻ°±ČłŽ”¶·žčș»ŒœŸż" + "ÀÁÂĂÄĆÆÇÈÉÊËÌÍÎÏĐŃÒÓÔŐÖŚŰÙÚÛÜĘȚß" + "àáâăäćæçèéêëìíîïđńòóôőöśűùúûüęțÿ"; + +const _noControls = "\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD" + "\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD" + "\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD" + "\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD"; + +/// ASCII characters without control characters. Shared by many code pages. +const _ascii = "$_noControls" + r""" !"#$%&'()*+,-./0123456789:;<=>?""" + r"@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_" + "`abcdefghijklmnopqrstuvwxyz{|}~\uFFFD"; + +/// A mapping between bytes and characters. +/// +/// A code page is a way to map bytes to character. +/// As such, it can only represent 256 different characters. +class CodePage extends Encoding { + final CodePageDecoder decoder; + final String name; + CodePageEncoder? _encoder; + + /// Creates a code page with the given name and characters. + /// + /// The [characters] string must contain 256 code points (runes) + /// in the order of the bytes representing them. + /// + /// Any byte not defined by the code page should have a + /// U+FFFD (invalid character) code point at its place in + /// [characters]. + /// + /// The name is used by [Encoding.name]. + factory CodePage(String name, String characters) = CodePage._general; + + /// Creates a code page with the characters of [characters]. + /// + /// The [characters] must contain precisely 256 characters (code points). + /// + /// A U+FFFD (invalid character) entry in [character] means that the + /// corresponding byte does not have a definition in this code page. + CodePage._general(this.name, String characters) + : decoder = _createDecoder(characters); + + /// Creates a code page with characters from the basic multilingual plane. + /// + /// The basic multilingual plane (BMP) contains the first 65536 code points. + /// As such, each character can be represented by a single UTF-16 code unit, + /// which makes some operations more efficient. + /// + /// The [characters] must contain precisely 256 code points from the BMP + /// which means that it should have length 256 and not contain any surrogates. + /// + /// A U+FFFD (invalid character) entry in [character] means that the + /// corresponding byte does not have a definition in this code page. + CodePage._bmp(this.name, String characters) + : decoder = _BmpCodePageDecoder(characters); + + /// The character associated with a particular byte in this code page. + /// + /// The [byte] must be in the range 0..255. + /// The returned value should be a Unicode scalar value + /// (a non-surrogate code point). + /// + /// If a code page does not have a defined character for a particular + /// byte, it should return the Unicode invalid character (U+FFFD) + /// instad. + int operator [](int byte) => decoder._char(byte); + + /// Encodes [input] using `encoder.convert`. + Uint8List encode(String input, {int? invalidCharacter}) => + encoder.convert(input, invalidCharacter: invalidCharacter); + + /// Decodes [bytes] using `encoder.convert`. + String decode(List bytes, {bool allowInvalid = false}) => + decoder.convert(bytes, allowInvalid: allowInvalid); + + CodePageEncoder get encoder => _encoder ??= decoder._createEncoder(); +} + +/// A code page decoder, converts from bytes to characters. +/// +/// A code page assigns characters to a subset of byte values. +/// The decoder converts those bytes back to their characters. +abstract class CodePageDecoder implements Converter, String> { + /// Decodes a sequence of bytes into a string using a code page. + /// + /// The code page assigns one character to each byte. + /// Values in [input] must be bytes (integers in the range 0..255). + /// + /// If [allowInvalid] is true, non-byte values in [input], + /// or byte values not defined as a character in the code page, + /// are emitted as U+FFFD (the Unicode invalid character). + /// If not true, the bytes must be calid and defined characters. + String convert(List input, {bool allowInvalid = false}); + + CodePageEncoder _createEncoder(); + int _char(int byte); +} + +/// Creates a decoder from [characters]. +/// +/// Recognizes if [characters] contains only characters in the BMP, +/// and creates a [BmpCodePageDecoder] in that case. +CodePageDecoder _createDecoder(String characters) { + var result = Uint32List(256); + var i = 0; + var allChars = 0; + for (var char in characters.runes) { + if (i >= 256) { + throw ArgumentError.value( + characters, "characters", "Must contain 256 characters"); + } + result[i] = char; + allChars |= char; + } + if (i < 256) { + throw ArgumentError.value( + characters, "characters", "Must contain 256 characters"); + } + if (allChars <= 0xFFFF) { + // It's in the BMP. + return _BmpCodePageDecoder(characters); + } + return _NonBmpCodePageDecoder._(result); +} + +/// Code page with non-BMP characters. +class _NonBmpCodePageDecoder extends Converter, String> + implements CodePageDecoder { + final Uint32List _characters; + _NonBmpCodePageDecoder(String characters) : this._(_buildMapping(characters)); + _NonBmpCodePageDecoder._(this._characters); + + int _char(int byte) => _characters[byte]; + + static Uint32List _buildMapping(String characters) { + var result = Uint32List(256); + var i = 0; + for (var char in characters.runes) { + if (i >= 256) { + throw ArgumentError.value( + characters, "characters", "Must contain 256 characters"); + } + result[i++] = char; + } + if (i < 256) { + throw ArgumentError.value( + characters, "characters", "Must contain 256 characters"); + } + return result; + } + + CodePageEncoder _createEncoder() { + var result = {}; + for (var i = 0; i < 256; i++) { + var char = _characters[i]; + if (char != 0xFFFD) { + result[char] = i; + } + } + return CodePageEncoder._(result); + } + + String convert(List input, {bool allowInvalid = false}) { + var buffer = Uint32List(input.length); + for (var i = 0; i < input.length; i++) { + var byte = input[i]; + if (byte & 0xff != byte) throw FormatException("Not a byte", input, i); + buffer[i] = _characters[byte]; + } + return String.fromCharCodes(buffer); + } +} + +class _BmpCodePageDecoder extends Converter, String> + implements CodePageDecoder { + final String _characters; + _BmpCodePageDecoder(String characters) : _characters = characters { + if (characters.length != 256) { + throw ArgumentError.value(characters, "characters", + "Must contain 256 characters. Was ${characters.length}"); + } + } + + int _char(int byte) => _characters.codeUnitAt(byte); + + String convert(List bytes, {bool allowInvalid = false}) { + if (allowInvalid) return _convertAllowInvalid(bytes); + var count = bytes.length; + var codeUnits = Uint16List(count); + for (var i = 0; i < count; i++) { + var byte = bytes[i]; + if (byte != byte & 0xff) { + throw FormatException("Not a byte value", bytes, i); + } + var character = _characters.codeUnitAt(byte); + if (character == 0xFFFD) { + throw FormatException("Not defined in this code page", bytes, i); + } + codeUnits[i] = character; + } + return String.fromCharCodes(codeUnits); + } + + String _convertAllowInvalid(List bytes) { + var count = bytes.length; + var codeUnits = Uint16List(count); + for (var i = 0; i < count; i++) { + var byte = bytes[i]; + int character; + if (byte == byte & 0xff) { + character = _characters.codeUnitAt(byte); + } else { + character = 0xFFFD; + } + codeUnits[i] = character; + } + return String.fromCharCodes(codeUnits); + } + + CodePageEncoder _createEncoder() => CodePageEncoder._bmp(_characters); +} + +/// Encoder for a code page. +/// +/// Converts a string into bytes where each byte represents that character +/// according to the code page definition. +class CodePageEncoder extends Converter> { + final Map _encoding; + + CodePageEncoder._bmp(String characters) + : _encoding = _createBmpEncoding(characters); + + CodePageEncoder._(this._encoding); + + static Map _createBmpEncoding(String characters) { + var encoding = {}; + for (var i = 0; i < characters.length; i++) { + var char = characters.codeUnitAt(i); + if (char != 0xFFFD) encoding[characters.codeUnitAt(i)] = i; + } + return encoding; + } + + /// Converts input to the byte encoding in this code page. + /// + /// If [invalidCharacter] is supplied, it must be a byte value + /// (in the range 0..255). + /// + /// If [input] contains characters that are not available + /// in this code page, they are replaced by the [invalidCharacter] byte, + /// and then [invalidCharacter] must have been supplied. + Uint8List convert(String input, {int? invalidCharacter}) { + if (invalidCharacter != null) { + RangeError.checkValueInInterval( + invalidCharacter, 0, 255, "invalidCharacter"); + } + var count = input.length; + var result = Uint8List(count); + var j = 0; + for (var i = 0; i < count; i++) { + var char = input.codeUnitAt(i); + var byte = _encoding[char]; + nullCheck: + if (byte == null) { + // Check for surrogate. + var offset = i; + if (char & 0xFC00 == 0xD800 && i + 1 < count) { + var next = input.codeUnitAt(i + 1); + if ((next & 0xFC00) == 0xDC00) { + i = i + 1; + char = 0x10000 + ((char & 0x3ff) << 10) + (next & 0x3ff); + byte = _encoding[char]; + if (byte != null) break nullCheck; + } + } + byte = invalidCharacter ?? + (throw FormatException( + "Not a character in this code page", input, offset)); + } + result[j++] = byte; + } + return Uint8List.sublistView(result, 0, j); + } +} diff --git a/pkgs/convert/test/codepage_test.dart b/pkgs/convert/test/codepage_test.dart new file mode 100644 index 00000000..2105f27a --- /dev/null +++ b/pkgs/convert/test/codepage_test.dart @@ -0,0 +1,63 @@ +// Copyright (c) 2020, 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 'dart:typed_data'; + +import 'package:convert/convert.dart'; +import 'package:test/test.dart'; + +void main() { + var bytes = Uint8List.fromList([for (var i = 0; i < 256; i++) i]); + for (var cp in [ + latin2, + latin3, + latin4, + latin5, + latin6, + latin7, + latin8, + latin9, + latin10, + latinCyrillic, + latinGreek, + latinHebrew, + latinThai, + latinArabic + ]) { + test("${cp.name} codepage", () { + // All ASCII compatible. + for (var byte = 0x20; byte < 0x7f; byte++) { + expect(cp[byte], byte); + } + // Maps both directions. + for (var byte = 0; byte < 256; byte++) { + var char = cp[byte]; + if (char != 0xFFFD) { + var string = String.fromCharCode(char); + expect(cp.encode(string), [byte]); + expect(cp.decode([byte]), string); + } + } + expect(() => cp.decode([0xfffd]), throwsA(isA())); + // Decode works like operator[]. + expect(cp.decode(bytes, allowInvalid: true), + String.fromCharCodes([for (var i = 0; i < 256; i++) cp[i]])); + }); + } + test("latin-2 roundtrip", () { + // Data from http://www.columbia.edu/kermit/latin2.html + var latin2text = + "\xa0Ą˘Ł¤ĽŚ§¨ŠŞŤŹ\xadŽŻ°ą˛ł´ľśˇ¸šşťź˝žżŔÁÂĂÄĹĆÇČÉĘËĚÍÎĎĐŃŇÓÔŐÖ×ŘŮÚŰÜÝŢßŕáâăäĺćçčéęëěíîďđńňóôőö÷řůúűüýţ˙"; + expect(latin2.decode(latin2.encode(latin2text)), latin2text); + }); + + test("latin-3 roundtrip", () { + // Data from http://www.columbia.edu/kermit/latin3.html + var latin2text = + "\xa0Ħ˘£¤\u{FFFD}Ĥ§¨İŞĞĴ\xad\u{FFFD}Ż°ħ²³´µĥ·¸ışğĵ½\u{FFFD}żÀÁÂ\u{FFFD}ÄĊĈÇÈÉÊËÌÍÎÏ\u{FFFD}ÑÒÓÔĠÖ×ĜÙÚÛÜŬŜßàáâ\u{FFFD}äċĉçèéêëìíîï\u{FFFD}ñòóôġö÷ĝùúûüŭŝ˙"; + var encoded = latin3.encode(latin2text, invalidCharacter: 0); + var decoded = latin3.decode(encoded, allowInvalid: true); + expect(decoded, latin2text); + }); +} From beba2c41f32b295eab4124dbdf65f7830c2039f7 Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Wed, 30 Sep 2020 16:58:21 -0700 Subject: [PATCH 027/100] Allow the 2.10 stable and 2.11.0-dev SDKs (dart-lang/convert#36) --- pkgs/convert/CHANGELOG.md | 2 +- pkgs/convert/pubspec.yaml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/pkgs/convert/CHANGELOG.md b/pkgs/convert/CHANGELOG.md index 947ff113..d920ec6a 100644 --- a/pkgs/convert/CHANGELOG.md +++ b/pkgs/convert/CHANGELOG.md @@ -1,4 +1,4 @@ -## 2.2.0-nullsafety +## 2.2.0-nullsafety-dev Pre-release for the null safety migration of this package. diff --git a/pkgs/convert/pubspec.yaml b/pkgs/convert/pubspec.yaml index 58978106..03d9ff69 100644 --- a/pkgs/convert/pubspec.yaml +++ b/pkgs/convert/pubspec.yaml @@ -1,10 +1,10 @@ name: convert -version: 2.2.0-nullsafety +version: 2.2.0-nullsafety-dev description: Utilities for converting between data representations. homepage: https://github.com/dart-lang/convert environment: - sdk: '>=2.10.0-2.0.dev <2.10.0' + sdk: '>=2.10.0-2.0.dev <2.11.0' dependencies: charcode: ^1.1.0 From ea3a25fac926a1c4fccff8b02c09da7a9d35eb01 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Thu, 5 Nov 2020 15:31:01 -0800 Subject: [PATCH 028/100] Update SDK constraint to 2.12.0-0 (dart-lang/convert#38) Update dependencies and travis config --- pkgs/convert/.travis.yml | 26 +++----------- pkgs/convert/pubspec.yaml | 71 ++++----------------------------------- 2 files changed, 10 insertions(+), 87 deletions(-) diff --git a/pkgs/convert/.travis.yml b/pkgs/convert/.travis.yml index b634f677..0ae3250e 100644 --- a/pkgs/convert/.travis.yml +++ b/pkgs/convert/.travis.yml @@ -3,28 +3,10 @@ language: dart dart: - dev -jobs: - include: - - stage: analyze_and_format - name: "Analyze" - os: linux - script: dartanalyzer --fatal-warnings --fatal-infos . - - stage: analyze_and_format - name: "Format" - os: linux - script: dartfmt -n --set-exit-if-changed . - - stage: test - name: "Vm Tests" - os: linux - script: pub run --enable-experiment=non-nullable test -p vm - - stage: test - name: "Web Tests" - os: linux - script: pub run --enable-experiment=non-nullable test -p chrome - -stages: - - analyze_and_format - - test +dart_task: +- dartfmt +- dartanalyzer: --fatal-warnings --fatal-infos . +- test: -p vm,chrome # Only building master means that we don't run two builds for each pull request. branches: diff --git a/pkgs/convert/pubspec.yaml b/pkgs/convert/pubspec.yaml index 03d9ff69..06854b27 100644 --- a/pkgs/convert/pubspec.yaml +++ b/pkgs/convert/pubspec.yaml @@ -1,74 +1,15 @@ name: convert version: 2.2.0-nullsafety-dev description: Utilities for converting between data representations. -homepage: https://github.com/dart-lang/convert +repository: https://github.com/dart-lang/convert environment: - sdk: '>=2.10.0-2.0.dev <2.11.0' + sdk: '>=2.12.0-0 <3.0.0' dependencies: - charcode: ^1.1.0 - typed_data: ^1.1.0 + charcode: ^1.2.0-nullsafety.3 + typed_data: ^1.3.0-nullsafety.5 dev_dependencies: - pedantic: ^1.0.0 - test: ^1.0.0 - -dependency_overrides: - async: - git: git://github.com/dart-lang/async.git - boolean_selector: - git: git://github.com/dart-lang/boolean_selector.git - charcode: - git: git://github.com/dart-lang/charcode.git - collection: - git: git://github.com/dart-lang/collection.git - js: - git: - url: git://github.com/dart-lang/sdk.git - ref: 2-10-pkgs - path: pkg/js - matcher: - git: git://github.com/dart-lang/matcher.git - meta: - git: - url: git://github.com/dart-lang/sdk.git - ref: 2-10-pkgs - path: pkg/meta - path: - git: git://github.com/dart-lang/path.git - pedantic: - git: git://github.com/dart-lang/pedantic.git - pool: - git: git://github.com/dart-lang/pool.git - source_maps: - git: git://github.com/dart-lang/source_maps.git - source_map_stack_trace: - git: git://github.com/dart-lang/source_map_stack_trace.git - source_span: - git: git://github.com/dart-lang/source_span.git - stack_trace: - git: git://github.com/dart-lang/stack_trace.git - stream_channel: - git: git://github.com/dart-lang/stream_channel.git - string_scanner: - git: git://github.com/dart-lang/string_scanner.git - term_glyph: - git: git://github.com/dart-lang/term_glyph.git - test_api: - git: - url: git://github.com/dart-lang/test.git - ref: null_safety - path: pkgs/test_api - test_core: - git: - url: git://github.com/dart-lang/test.git - ref: null_safety - path: pkgs/test_core - test: - git: - url: git://github.com/dart-lang/test.git - ref: null_safety - path: pkgs/test - typed_data: - git: git://github.com/dart-lang/typed_data.git + pedantic: ^1.10.0-nullsafety.3 + test: ^1.16.0-nullsafety.9 From 1e972ca5ba64262f07a7c06e0ec3d6807e5faacf Mon Sep 17 00:00:00 2001 From: "Lasse R.H. Nielsen" Date: Fri, 6 Nov 2020 12:38:17 +0100 Subject: [PATCH 029/100] Make the package not depend directly on package:charcode. (dart-lang/convert#35) * Make the package not depend directly on package:charcode. The charcode package is still used a dev-dependency, but that does not affect users of the convert package. --- pkgs/convert/lib/src/charcodes.dart | 36 +++++++++++++++++++++++ pkgs/convert/lib/src/hex/encoder.dart | 2 +- pkgs/convert/lib/src/percent/decoder.dart | 2 +- pkgs/convert/lib/src/percent/encoder.dart | 2 +- pkgs/convert/lib/src/utils.dart | 2 +- pkgs/convert/pubspec.yaml | 2 +- 6 files changed, 41 insertions(+), 5 deletions(-) create mode 100644 pkgs/convert/lib/src/charcodes.dart diff --git a/pkgs/convert/lib/src/charcodes.dart b/pkgs/convert/lib/src/charcodes.dart new file mode 100644 index 00000000..fc941484 --- /dev/null +++ b/pkgs/convert/lib/src/charcodes.dart @@ -0,0 +1,36 @@ +// Copyright (c) 2020, 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. + +/// Character `%`. +const int $percent = 0x25; + +/// Character `-`. +const int $dash = 0x2d; + +/// Character `.`. +const int $dot = 0x2e; + +/// Character `0`. +const int $0 = 0x30; + +/// Character `9`. +const int $9 = 0x39; + +/// Character `A`. +const int $A = 0x41; + +/// Character `_`. +const int $underscore = 0x5f; + +/// Character `a`. +const int $a = 0x61; + +/// Character `f`. +const int $f = 0x66; + +/// Character `z`. +const int $z = 0x7a; + +/// Character `~`. +const int $tilde = 0x7e; diff --git a/pkgs/convert/lib/src/hex/encoder.dart b/pkgs/convert/lib/src/hex/encoder.dart index 3ed85c73..261a5d99 100644 --- a/pkgs/convert/lib/src/hex/encoder.dart +++ b/pkgs/convert/lib/src/hex/encoder.dart @@ -7,7 +7,7 @@ library convert.hex.encoder; import 'dart:convert'; import 'dart:typed_data'; -import 'package:charcode/ascii.dart'; +import '../charcodes.dart'; /// The canonical instance of [HexEncoder]. const hexEncoder = HexEncoder._(); diff --git a/pkgs/convert/lib/src/percent/decoder.dart b/pkgs/convert/lib/src/percent/decoder.dart index fee9ca9a..456c8883 100644 --- a/pkgs/convert/lib/src/percent/decoder.dart +++ b/pkgs/convert/lib/src/percent/decoder.dart @@ -6,9 +6,9 @@ library convert.percent.decoder; import 'dart:convert'; -import 'package:charcode/ascii.dart'; import 'package:typed_data/typed_data.dart'; +import '../charcodes.dart'; import '../utils.dart'; /// The canonical instance of [PercentDecoder]. diff --git a/pkgs/convert/lib/src/percent/encoder.dart b/pkgs/convert/lib/src/percent/encoder.dart index 390316f5..a8614689 100644 --- a/pkgs/convert/lib/src/percent/encoder.dart +++ b/pkgs/convert/lib/src/percent/encoder.dart @@ -6,7 +6,7 @@ library convert.percent.encoder; import 'dart:convert'; -import 'package:charcode/ascii.dart'; +import '../charcodes.dart'; /// The canonical instance of [PercentEncoder]. const percentEncoder = PercentEncoder._(); diff --git a/pkgs/convert/lib/src/utils.dart b/pkgs/convert/lib/src/utils.dart index 4001e3e3..ff2c2957 100644 --- a/pkgs/convert/lib/src/utils.dart +++ b/pkgs/convert/lib/src/utils.dart @@ -4,7 +4,7 @@ library convert.utils; -import 'package:charcode/ascii.dart'; +import 'charcodes.dart'; /// Returns the digit (0 through 15) corresponding to the hexadecimal code unit /// at index [i] in [codeUnits]. diff --git a/pkgs/convert/pubspec.yaml b/pkgs/convert/pubspec.yaml index 06854b27..aad3ebe3 100644 --- a/pkgs/convert/pubspec.yaml +++ b/pkgs/convert/pubspec.yaml @@ -7,9 +7,9 @@ environment: sdk: '>=2.12.0-0 <3.0.0' dependencies: - charcode: ^1.2.0-nullsafety.3 typed_data: ^1.3.0-nullsafety.5 dev_dependencies: + charcode: ^1.2.0-nullsafety.3 pedantic: ^1.10.0-nullsafety.3 test: ^1.16.0-nullsafety.9 From bf19f3b142d8fefffb0cdde69b9237ea55af741c Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Fri, 6 Nov 2020 15:14:24 -0800 Subject: [PATCH 030/100] prepare to publish convert (dart-lang/convert#39) --- pkgs/convert/CHANGELOG.md | 9 +-------- pkgs/convert/pubspec.yaml | 10 +++++++++- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/pkgs/convert/CHANGELOG.md b/pkgs/convert/CHANGELOG.md index d920ec6a..011af574 100644 --- a/pkgs/convert/CHANGELOG.md +++ b/pkgs/convert/CHANGELOG.md @@ -1,14 +1,7 @@ -## 2.2.0-nullsafety-dev +## 3.0.0-nullsafety Pre-release for the null safety migration of this package. -Note that 2.2.0 may not be the final stable null safety release version, we -reserve the right to release it as a 3.0.0 breaking change. - -This release will be pinned to only allow pre-release sdk versions starting from -2.10.0-2.0.dev, which is the first version where this package will appear in the -null safety allow list. - * Added `CodePage` class for single-byte `Encoding` implementations. ## 2.1.1 diff --git a/pkgs/convert/pubspec.yaml b/pkgs/convert/pubspec.yaml index aad3ebe3..d3cdea4d 100644 --- a/pkgs/convert/pubspec.yaml +++ b/pkgs/convert/pubspec.yaml @@ -1,5 +1,5 @@ name: convert -version: 2.2.0-nullsafety-dev +version: 3.0.0-nullsafety description: Utilities for converting between data representations. repository: https://github.com/dart-lang/convert @@ -13,3 +13,11 @@ dev_dependencies: charcode: ^1.2.0-nullsafety.3 pedantic: ^1.10.0-nullsafety.3 test: ^1.16.0-nullsafety.9 + +# Because these packages depend on the pre-v3 version of this package +dependency_overrides: + analyzer: 0.40.6 + crypto: 2.1.5 + shelf_static: 0.2.8 + test: 1.16.0-nullsafety.9 + web_socket_channel: 1.1.0 From ed5871a15385361c43f8110c4a8499616fc8fbf5 Mon Sep 17 00:00:00 2001 From: Phil Quitslund Date: Wed, 11 Nov 2020 08:21:59 -0800 Subject: [PATCH 031/100] remove redundant experiment --- pkgs/convert/analysis_options.yaml | 2 -- 1 file changed, 2 deletions(-) diff --git a/pkgs/convert/analysis_options.yaml b/pkgs/convert/analysis_options.yaml index 14d22d8d..dcd46cb0 100644 --- a/pkgs/convert/analysis_options.yaml +++ b/pkgs/convert/analysis_options.yaml @@ -7,8 +7,6 @@ analyzer: # Ignore still failing lints from latest pkg:pedantic annotate_overrides: ignore prefer_single_quotes: ignore - enable-experiment: - - non-nullable linter: rules: From d15468d98e745f8e2e8f282d2aa0f8e315564dfe Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Mon, 16 Nov 2020 13:15:22 -0800 Subject: [PATCH 032/100] Increase package description to >=60 characters and added an example (dart-lang/convert#41) Follow conventions, improve package score --- pkgs/convert/CHANGELOG.md | 2 +- pkgs/convert/example/example.dart | 20 ++++++++++++++++++++ pkgs/convert/pubspec.yaml | 6 ++++-- 3 files changed, 25 insertions(+), 3 deletions(-) create mode 100644 pkgs/convert/example/example.dart diff --git a/pkgs/convert/CHANGELOG.md b/pkgs/convert/CHANGELOG.md index 011af574..760802e8 100644 --- a/pkgs/convert/CHANGELOG.md +++ b/pkgs/convert/CHANGELOG.md @@ -1,4 +1,4 @@ -## 3.0.0-nullsafety +## 3.0.0-nullsafety.0 Pre-release for the null safety migration of this package. diff --git a/pkgs/convert/example/example.dart b/pkgs/convert/example/example.dart new file mode 100644 index 00000000..50385914 --- /dev/null +++ b/pkgs/convert/example/example.dart @@ -0,0 +1,20 @@ +// Copyright (c) 2020, 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 'dart:convert'; + +import 'package:convert/convert.dart'; + +void main(List args) { + // Creates a Codec that converts a UTF-8 strings to/from percent encoding + final fusedCodec = utf8.fuse(percent); + + final input = args.isNotEmpty ? args.first : 'ABC 123 @!('; + print(input); + final encodedMessage = fusedCodec.encode(input); + print(encodedMessage); + + final decodedMessage = fusedCodec.decode(encodedMessage); + assert(decodedMessage == input); +} diff --git a/pkgs/convert/pubspec.yaml b/pkgs/convert/pubspec.yaml index d3cdea4d..b41eb151 100644 --- a/pkgs/convert/pubspec.yaml +++ b/pkgs/convert/pubspec.yaml @@ -1,6 +1,8 @@ name: convert -version: 3.0.0-nullsafety -description: Utilities for converting between data representations. +version: 3.0.0-nullsafety.0 +description: >- + Utilities for converting between data representations. + Provides a number of Sink, Codec, Decoder, and Encoder types. repository: https://github.com/dart-lang/convert environment: From 53962173e6cf3d1f55c2a70668f73777ffcf8ac7 Mon Sep 17 00:00:00 2001 From: Alexander Thomas Date: Mon, 21 Dec 2020 22:36:17 +0100 Subject: [PATCH 033/100] Migrate to GitHub Actions (dart-lang/convert#43) * Migrate to GitHub Actions * Delete .travis.yml --- .../.github/workflows/test-package.yml | 64 +++++++++++++++++++ pkgs/convert/.travis.yml | 17 ----- 2 files changed, 64 insertions(+), 17 deletions(-) create mode 100644 pkgs/convert/.github/workflows/test-package.yml delete mode 100644 pkgs/convert/.travis.yml diff --git a/pkgs/convert/.github/workflows/test-package.yml b/pkgs/convert/.github/workflows/test-package.yml new file mode 100644 index 00000000..e55702c2 --- /dev/null +++ b/pkgs/convert/.github/workflows/test-package.yml @@ -0,0 +1,64 @@ +name: Dart CI + +on: + # Run on PRs and pushes to the default branch. + push: + branches: [ master ] + pull_request: + branches: [ master ] + schedule: + - cron: "0 0 * * 0" + +env: + PUB_ENVIRONMENT: bot.github + +jobs: + # Check code formatting and static analysis on a single OS (linux) + # against Dart dev. + analyze: + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + sdk: [dev] + steps: + - uses: actions/checkout@v2 + - uses: dart-lang/setup-dart@v0.1 + with: + channel: ${{ matrix.sdk }} + - id: install + name: Install dependencies + run: dart pub get + - name: Check formatting + run: dart format --output=none --set-exit-if-changed . + if: always() && steps.install.outcome == 'success' + - name: Analyze code + run: dart analyze --fatal-infos + if: always() && steps.install.outcome == 'success' + + # Run tests on a matrix consisting of two dimensions: + # 1. OS: ubuntu-latest, (macos-latest, windows-latest) + # 2. release channel: dev + test: + needs: analyze + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + # Add macos-latest and/or windows-latest if relevant for this package. + os: [ubuntu-latest] + sdk: [dev] + steps: + - uses: actions/checkout@v2 + - uses: dart-lang/setup-dart@v0.1 + with: + channel: ${{ matrix.sdk }} + - id: install + name: Install dependencies + run: dart pub get + - name: Run VM tests + run: dart test --platform vm + if: always() && steps.install.outcome == 'success' + - name: Run Chrome tests + run: dart test --platform chrome + if: always() && steps.install.outcome == 'success' diff --git a/pkgs/convert/.travis.yml b/pkgs/convert/.travis.yml deleted file mode 100644 index 0ae3250e..00000000 --- a/pkgs/convert/.travis.yml +++ /dev/null @@ -1,17 +0,0 @@ -language: dart - -dart: - - dev - -dart_task: -- dartfmt -- dartanalyzer: --fatal-warnings --fatal-infos . -- test: -p vm,chrome - -# Only building master means that we don't run two builds for each pull request. -branches: - only: [master] - -cache: - directories: - - $HOME/.pub-cache From 420f195b034a82a3a3bd1334f93474fa46eb52bb Mon Sep 17 00:00:00 2001 From: Jacob MacDonald Date: Fri, 5 Feb 2021 12:57:46 -0800 Subject: [PATCH 034/100] stable null safety release (dart-lang/convert#45) --- pkgs/convert/CHANGELOG.md | 4 ++++ pkgs/convert/pubspec.yaml | 16 ++++------------ 2 files changed, 8 insertions(+), 12 deletions(-) diff --git a/pkgs/convert/CHANGELOG.md b/pkgs/convert/CHANGELOG.md index 760802e8..43f4dd05 100644 --- a/pkgs/convert/CHANGELOG.md +++ b/pkgs/convert/CHANGELOG.md @@ -1,3 +1,7 @@ +## 3.0.0 + +* Stable null safety release. + ## 3.0.0-nullsafety.0 Pre-release for the null safety migration of this package. diff --git a/pkgs/convert/pubspec.yaml b/pkgs/convert/pubspec.yaml index b41eb151..f0aff73c 100644 --- a/pkgs/convert/pubspec.yaml +++ b/pkgs/convert/pubspec.yaml @@ -1,5 +1,5 @@ name: convert -version: 3.0.0-nullsafety.0 +version: 3.0.0 description: >- Utilities for converting between data representations. Provides a number of Sink, Codec, Decoder, and Encoder types. @@ -9,17 +9,9 @@ environment: sdk: '>=2.12.0-0 <3.0.0' dependencies: - typed_data: ^1.3.0-nullsafety.5 + typed_data: ^1.3.0 dev_dependencies: - charcode: ^1.2.0-nullsafety.3 - pedantic: ^1.10.0-nullsafety.3 + charcode: ^1.2.0 + pedantic: ^1.10.0 test: ^1.16.0-nullsafety.9 - -# Because these packages depend on the pre-v3 version of this package -dependency_overrides: - analyzer: 0.40.6 - crypto: 2.1.5 - shelf_static: 0.2.8 - test: 1.16.0-nullsafety.9 - web_socket_channel: 1.1.0 From d5362b24fbd4e003067af10ca2206bcafac8db2c Mon Sep 17 00:00:00 2001 From: Franklin Yow <58489007+franklinyow@users.noreply.github.com> Date: Thu, 1 Apr 2021 13:46:39 -0700 Subject: [PATCH 035/100] Update LICENSE Changes to comply with internal review --- pkgs/convert/LICENSE | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/pkgs/convert/LICENSE b/pkgs/convert/LICENSE index de31e1a0..633672ab 100644 --- a/pkgs/convert/LICENSE +++ b/pkgs/convert/LICENSE @@ -1,4 +1,5 @@ -Copyright 2015, the Dart project authors. All rights reserved. +Copyright 2015, the Dart project authors. + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: @@ -9,7 +10,7 @@ met: copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - * Neither the name of Google Inc. nor the names of its + * Neither the name of Google LLC nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. From a6541c7f956c9518c2515b474a6c7d371aa5fb3f Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Fri, 23 Apr 2021 12:43:19 -0700 Subject: [PATCH 036/100] Latest CI setup, test oldest supported SDK (dart-lang/convert#50) --- pkgs/convert/.github/workflows/test-package.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pkgs/convert/.github/workflows/test-package.yml b/pkgs/convert/.github/workflows/test-package.yml index e55702c2..35e08035 100644 --- a/pkgs/convert/.github/workflows/test-package.yml +++ b/pkgs/convert/.github/workflows/test-package.yml @@ -23,7 +23,7 @@ jobs: sdk: [dev] steps: - uses: actions/checkout@v2 - - uses: dart-lang/setup-dart@v0.1 + - uses: dart-lang/setup-dart@v1.0 with: channel: ${{ matrix.sdk }} - id: install @@ -47,12 +47,12 @@ jobs: matrix: # Add macos-latest and/or windows-latest if relevant for this package. os: [ubuntu-latest] - sdk: [dev] + sdk: [2.12.0, dev] steps: - uses: actions/checkout@v2 - - uses: dart-lang/setup-dart@v0.1 + - uses: dart-lang/setup-dart@v1.0 with: - channel: ${{ matrix.sdk }} + sdk: ${{ matrix.sdk }} - id: install name: Install dependencies run: dart pub get From 8a8a5bd36f8b2f0e13d12509d173c9dc7471b448 Mon Sep 17 00:00:00 2001 From: "Lasse R.H. Nielsen" Date: Wed, 9 Jun 2021 16:42:44 +0200 Subject: [PATCH 037/100] Remove dependency on package:charcode entirely. (dart-lang/convert#53) Removes the dev-dependency on package:charcode, and uses in a one test file. --- pkgs/convert/pubspec.yaml | 1 - pkgs/convert/test/percent_test.dart | 149 +++++----------------------- 2 files changed, 26 insertions(+), 124 deletions(-) diff --git a/pkgs/convert/pubspec.yaml b/pkgs/convert/pubspec.yaml index f0aff73c..b908be4e 100644 --- a/pkgs/convert/pubspec.yaml +++ b/pkgs/convert/pubspec.yaml @@ -12,6 +12,5 @@ dependencies: typed_data: ^1.3.0 dev_dependencies: - charcode: ^1.2.0 pedantic: ^1.10.0 test: ^1.16.0-nullsafety.9 diff --git a/pkgs/convert/test/percent_test.dart b/pkgs/convert/test/percent_test.dart index 7a7bf811..87d903c4 100644 --- a/pkgs/convert/test/percent_test.dart +++ b/pkgs/convert/test/percent_test.dart @@ -4,102 +4,20 @@ import 'dart:async'; -import 'package:charcode/ascii.dart'; import 'package:convert/convert.dart'; import 'package:test/test.dart'; void main() { group("encoder", () { test("doesn't percent-encode unreserved characters", () { - expect( - percent.encode([ - $a, - $b, - $c, - $d, - $e, - $f, - $g, - $h, - $i, - $j, - $k, - $l, - $m, - $n, - $o, - $p, - $q, - $r, - $s, - $t, - $u, - $v, - $w, - $x, - $y, - $z, - $A, - $B, - $C, - $D, - $E, - $F, - $G, - $H, - $I, - $J, - $K, - $L, - $M, - $N, - $O, - $P, - $Q, - $R, - $S, - $T, - $U, - $V, - $W, - $X, - $Y, - $Z, - $0, - $1, - $2, - $3, - $4, - $5, - $6, - $7, - $8, - $9, - $dash, - $dot, - $underscore, - $tilde - ]), - equals( - "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._~")); + var safeChars = "abcdefghijklmnopqrstuvwxyz" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "0123456789-._~"; + expect(percent.encode([...safeChars.codeUnits]), equals(safeChars)); }); test("percent-encodes reserved ASCII characters", () { - expect( - percent.encode([ - $space, - $backquote, - $open_brace, - $at, - $open_bracket, - $comma, - $division, - $caret, - $close_brace, - $del, - $nul, - $percent - ]), + expect(percent.encode([..." `{@[,/^}\x7f\x00%".codeUnits]), equals("%20%60%7B%40%5B%2C%2F%5E%7D%7F%00%25")); }); @@ -108,8 +26,7 @@ void main() { }); test("mixes encoded and unencoded characters", () { - expect( - percent.encode([$a, $plus, $b, $equal, 0x80]), equals("a%2Bb%3D%80")); + expect(percent.encode([..."a+b=\x80".codeUnits]), equals("a%2Bb%3D%80")); }); group("with chunked conversion", () { @@ -119,7 +36,7 @@ void main() { controller.stream.listen(results.add); var sink = percent.encoder.startChunkedConversion(controller.sink); - sink.add([$a, $plus, $b, $equal, 0x80]); + sink.add([..."a+b=\x80".codeUnits]); expect(results, equals(["a%2Bb%3D%80"])); sink.add([0x00, 0x01, 0xfe, 0xff]); @@ -154,35 +71,21 @@ void main() { group("decoder", () { test("converts percent-encoded strings to byte arrays", () { - expect(percent.decode("a%2Bb%3D%801"), - equals([$a, $plus, $b, $equal, 0x80, $1])); + expect( + percent.decode("a%2Bb%3D%801"), equals([..."a+b=\x801".codeUnits])); }); test("supports lowercase letters", () { - expect( - percent.decode("a%2bb%3d%80"), equals([$a, $plus, $b, $equal, 0x80])); + expect(percent.decode("a%2bb%3d%80"), equals([..."a+b=\x80".codeUnits])); }); test("supports more aggressive encoding", () { - expect(percent.decode("%61%2E%5A"), equals([$a, $dot, $Z])); + expect(percent.decode("%61%2E%5A"), equals([..."a.Z".codeUnits])); }); test("supports less aggressive encoding", () { - expect( - percent.decode(" `{@[,/^}\x7F\x00"), - equals([ - $space, - $backquote, - $open_brace, - $at, - $open_bracket, - $comma, - $division, - $caret, - $close_brace, - $del, - $nul - ])); + var chars = " `{@[,/^}\x7F\x00"; + expect(percent.decode(chars), equals([...chars.codeUnits])); }); group("with chunked conversion", () { @@ -200,14 +103,14 @@ void main() { expect( results, equals([ - [$a, $plus, $b, $equal, 0x80, $1] + [..."a+b=\x801".codeUnits] ])); sink.add("%00%01%FE%FF"); expect( results, equals([ - [$a, $plus, $b, $equal, 0x80, $1], + [..."a+b=\x801".codeUnits], [0x00, 0x01, 0xfe, 0xff] ])); }); @@ -217,31 +120,31 @@ void main() { expect( results, equals([ - [$a, $b] + [..."ab".codeUnits] ])); sink.add("2"); expect( results, equals([ - [$a, $b] + [..."ab".codeUnits] ])); sink.add("0cd%2"); expect( results, equals([ - [$a, $b], - [$space, $c, $d] + [..."ab".codeUnits], + [..." cd".codeUnits] ])); sink.add("0"); expect( results, equals(([ - [$a, $b], - [$space, $c, $d], - [$space] + [..."ab".codeUnits], + [..." cd".codeUnits], + [..." ".codeUnits] ]))); }); @@ -275,7 +178,7 @@ void main() { expect( results, equals([ - [$a, $b] + [..."ab".codeUnits] ])); expect(() => sink.close(), throwsFormatException); }); @@ -285,7 +188,7 @@ void main() { expect( results, equals([ - [$a, $b] + [..."ab".codeUnits] ])); expect(() => sink.close(), throwsFormatException); }); @@ -295,7 +198,7 @@ void main() { expect( results, equals([ - [$a, $b] + [..."ab".codeUnits] ])); expect(() => sink.addSlice("ab%", 0, 3, true), throwsFormatException); @@ -306,7 +209,7 @@ void main() { expect( results, equals([ - [$a, $b] + [..."ab".codeUnits] ])); expect(() => sink.addSlice("ab%2", 0, 3, true), throwsFormatException); From 9687a3e7cd00e3b070c2c872d68e8a457e7815fc Mon Sep 17 00:00:00 2001 From: "Lasse R.H. Nielsen" Date: Thu, 24 Jun 2021 16:21:19 +0200 Subject: [PATCH 038/100] Prepare release without dependency on package:charcode (dart-lang/convert#54) --- pkgs/convert/CHANGELOG.md | 4 ++++ pkgs/convert/pubspec.yaml | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/pkgs/convert/CHANGELOG.md b/pkgs/convert/CHANGELOG.md index 43f4dd05..8d015290 100644 --- a/pkgs/convert/CHANGELOG.md +++ b/pkgs/convert/CHANGELOG.md @@ -1,3 +1,7 @@ +## 3.0.1 + +* Dependency clean-up. + ## 3.0.0 * Stable null safety release. diff --git a/pkgs/convert/pubspec.yaml b/pkgs/convert/pubspec.yaml index b908be4e..8783bb31 100644 --- a/pkgs/convert/pubspec.yaml +++ b/pkgs/convert/pubspec.yaml @@ -1,5 +1,5 @@ name: convert -version: 3.0.0 +version: 3.0.1 description: >- Utilities for converting between data representations. Provides a number of Sink, Codec, Decoder, and Encoder types. From 1dc4a8c918631a421efd2c67d30dda9bd3caffef Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Thu, 22 Jul 2021 13:58:20 -0700 Subject: [PATCH 039/100] Move from pedantic to lints package (dart-lang/convert#55) Fix existing violations of lints: - `annotate_overrides` - `avoid_renaming_method_parameters` - `prefer_typing_uninitialized_variables` Fix setup-dart config - channel key was renamed --- .../convert/.github/workflows/test-package.yml | 4 ++-- pkgs/convert/CHANGELOG.md | 2 ++ pkgs/convert/analysis_options.yaml | 7 +------ pkgs/convert/lib/src/accumulator_sink.dart | 2 ++ .../convert/lib/src/byte_accumulator_sink.dart | 7 +++++-- pkgs/convert/lib/src/codepage.dart | 13 +++++++++++++ pkgs/convert/lib/src/hex.dart | 2 ++ pkgs/convert/lib/src/hex/decoder.dart | 18 +++++++++++++----- pkgs/convert/lib/src/hex/encoder.dart | 7 ++++++- pkgs/convert/lib/src/identity_codec.dart | 4 ++++ pkgs/convert/lib/src/percent.dart | 2 ++ pkgs/convert/lib/src/percent/decoder.dart | 14 +++++++++++--- pkgs/convert/lib/src/percent/encoder.dart | 7 ++++++- .../lib/src/string_accumulator_sink.dart | 11 +++++++---- pkgs/convert/pubspec.yaml | 8 ++++---- pkgs/convert/test/accumulator_sink_test.dart | 12 +++++++++--- pkgs/convert/test/hex_test.dart | 3 ++- pkgs/convert/test/percent_test.dart | 3 ++- .../test/string_accumulator_sink_test.dart | 2 +- 19 files changed, 94 insertions(+), 34 deletions(-) diff --git a/pkgs/convert/.github/workflows/test-package.yml b/pkgs/convert/.github/workflows/test-package.yml index 35e08035..e3bd3c06 100644 --- a/pkgs/convert/.github/workflows/test-package.yml +++ b/pkgs/convert/.github/workflows/test-package.yml @@ -25,7 +25,7 @@ jobs: - uses: actions/checkout@v2 - uses: dart-lang/setup-dart@v1.0 with: - channel: ${{ matrix.sdk }} + sdk: ${{ matrix.sdk }} - id: install name: Install dependencies run: dart pub get @@ -38,7 +38,7 @@ jobs: # Run tests on a matrix consisting of two dimensions: # 1. OS: ubuntu-latest, (macos-latest, windows-latest) - # 2. release channel: dev + # 2. release sdk: dev test: needs: analyze runs-on: ${{ matrix.os }} diff --git a/pkgs/convert/CHANGELOG.md b/pkgs/convert/CHANGELOG.md index 8d015290..4d059357 100644 --- a/pkgs/convert/CHANGELOG.md +++ b/pkgs/convert/CHANGELOG.md @@ -1,3 +1,5 @@ +## 3.0.2-dev + ## 3.0.1 * Dependency clean-up. diff --git a/pkgs/convert/analysis_options.yaml b/pkgs/convert/analysis_options.yaml index dcd46cb0..85d6c125 100644 --- a/pkgs/convert/analysis_options.yaml +++ b/pkgs/convert/analysis_options.yaml @@ -1,13 +1,8 @@ -include: package:pedantic/analysis_options.yaml +include: package:lints/recommended.yaml analyzer: strong-mode: implicit-casts: false - errors: - # Ignore still failing lints from latest pkg:pedantic - annotate_overrides: ignore - prefer_single_quotes: ignore - linter: rules: - avoid_empty_else diff --git a/pkgs/convert/lib/src/accumulator_sink.dart b/pkgs/convert/lib/src/accumulator_sink.dart index d92b4a8e..ef01a761 100644 --- a/pkgs/convert/lib/src/accumulator_sink.dart +++ b/pkgs/convert/lib/src/accumulator_sink.dart @@ -23,6 +23,7 @@ class AccumulatorSink implements Sink { _events.clear(); } + @override void add(T event) { if (_isClosed) { throw StateError("Can't add to a closed sink."); @@ -31,6 +32,7 @@ class AccumulatorSink implements Sink { _events.add(event); } + @override void close() { _isClosed = true; } diff --git a/pkgs/convert/lib/src/byte_accumulator_sink.dart b/pkgs/convert/lib/src/byte_accumulator_sink.dart index d1fab06f..44cf1784 100644 --- a/pkgs/convert/lib/src/byte_accumulator_sink.dart +++ b/pkgs/convert/lib/src/byte_accumulator_sink.dart @@ -30,14 +30,16 @@ class ByteAccumulatorSink extends ByteConversionSinkBase { _buffer.clear(); } - void add(List bytes) { + @override + void add(List chunk) { if (_isClosed) { throw StateError("Can't add to a closed sink."); } - _buffer.addAll(bytes); + _buffer.addAll(chunk); } + @override void addSlice(List chunk, int start, int end, bool isLast) { if (_isClosed) { throw StateError("Can't add to a closed sink."); @@ -47,6 +49,7 @@ class ByteAccumulatorSink extends ByteConversionSinkBase { if (isLast) _isClosed = true; } + @override void close() { _isClosed = true; } diff --git a/pkgs/convert/lib/src/codepage.dart b/pkgs/convert/lib/src/codepage.dart index 2cc5fbd3..376a9ecd 100644 --- a/pkgs/convert/lib/src/codepage.dart +++ b/pkgs/convert/lib/src/codepage.dart @@ -162,7 +162,9 @@ const _ascii = "$_noControls" /// A code page is a way to map bytes to character. /// As such, it can only represent 256 different characters. class CodePage extends Encoding { + @override final CodePageDecoder decoder; + @override final String name; CodePageEncoder? _encoder; @@ -213,13 +215,16 @@ class CodePage extends Encoding { int operator [](int byte) => decoder._char(byte); /// Encodes [input] using `encoder.convert`. + @override Uint8List encode(String input, {int? invalidCharacter}) => encoder.convert(input, invalidCharacter: invalidCharacter); /// Decodes [bytes] using `encoder.convert`. + @override String decode(List bytes, {bool allowInvalid = false}) => decoder.convert(bytes, allowInvalid: allowInvalid); + @override CodePageEncoder get encoder => _encoder ??= decoder._createEncoder(); } @@ -237,6 +242,7 @@ abstract class CodePageDecoder implements Converter, String> { /// or byte values not defined as a character in the code page, /// are emitted as U+FFFD (the Unicode invalid character). /// If not true, the bytes must be calid and defined characters. + @override String convert(List input, {bool allowInvalid = false}); CodePageEncoder _createEncoder(); @@ -277,6 +283,7 @@ class _NonBmpCodePageDecoder extends Converter, String> _NonBmpCodePageDecoder(String characters) : this._(_buildMapping(characters)); _NonBmpCodePageDecoder._(this._characters); + @override int _char(int byte) => _characters[byte]; static Uint32List _buildMapping(String characters) { @@ -296,6 +303,7 @@ class _NonBmpCodePageDecoder extends Converter, String> return result; } + @override CodePageEncoder _createEncoder() { var result = {}; for (var i = 0; i < 256; i++) { @@ -307,6 +315,7 @@ class _NonBmpCodePageDecoder extends Converter, String> return CodePageEncoder._(result); } + @override String convert(List input, {bool allowInvalid = false}) { var buffer = Uint32List(input.length); for (var i = 0; i < input.length; i++) { @@ -328,8 +337,10 @@ class _BmpCodePageDecoder extends Converter, String> } } + @override int _char(int byte) => _characters.codeUnitAt(byte); + @override String convert(List bytes, {bool allowInvalid = false}) { if (allowInvalid) return _convertAllowInvalid(bytes); var count = bytes.length; @@ -364,6 +375,7 @@ class _BmpCodePageDecoder extends Converter, String> return String.fromCharCodes(codeUnits); } + @override CodePageEncoder _createEncoder() => CodePageEncoder._bmp(_characters); } @@ -396,6 +408,7 @@ class CodePageEncoder extends Converter> { /// If [input] contains characters that are not available /// in this code page, they are replaced by the [invalidCharacter] byte, /// and then [invalidCharacter] must have been supplied. + @override Uint8List convert(String input, {int? invalidCharacter}) { if (invalidCharacter != null) { RangeError.checkValueInInterval( diff --git a/pkgs/convert/lib/src/hex.dart b/pkgs/convert/lib/src/hex.dart index 28e9203b..9de28edb 100644 --- a/pkgs/convert/lib/src/hex.dart +++ b/pkgs/convert/lib/src/hex.dart @@ -22,7 +22,9 @@ const hex = HexCodec._(); /// /// This should be used via the [hex] field. class HexCodec extends Codec, String> { + @override HexEncoder get encoder => hexEncoder; + @override HexDecoder get decoder => hexDecoder; const HexCodec._(); diff --git a/pkgs/convert/lib/src/hex/decoder.dart b/pkgs/convert/lib/src/hex/decoder.dart index 9e3a122d..0a65f45b 100644 --- a/pkgs/convert/lib/src/hex/decoder.dart +++ b/pkgs/convert/lib/src/hex/decoder.dart @@ -20,17 +20,19 @@ const hexDecoder = HexDecoder._(); class HexDecoder extends Converter> { const HexDecoder._(); - List convert(String string) { - if (!string.length.isEven) { + @override + List convert(String input) { + if (!input.length.isEven) { throw FormatException( - "Invalid input length, must be even.", string, string.length); + "Invalid input length, must be even.", input, input.length); } - var bytes = Uint8List(string.length ~/ 2); - _decode(string.codeUnits, 0, string.length, bytes, 0); + var bytes = Uint8List(input.length ~/ 2); + _decode(input.codeUnits, 0, input.length, bytes, 0); return bytes; } + @override StringConversionSink startChunkedConversion(Sink> sink) => _HexDecoderSink(sink); } @@ -49,6 +51,7 @@ class _HexDecoderSink extends StringConversionSinkBase { _HexDecoderSink(this._sink); + @override void addSlice(String string, int start, int end, bool isLast) { RangeError.checkValidRange(start, end, string.length); @@ -77,9 +80,11 @@ class _HexDecoderSink extends StringConversionSinkBase { if (isLast) _close(string, end); } + @override ByteConversionSink asUtf8Sink(bool allowMalformed) => _HexDecoderByteSink(_sink); + @override void close() => _close(); /// Like [close], but includes [string] and [index] in the [FormatException] @@ -108,8 +113,10 @@ class _HexDecoderByteSink extends ByteConversionSinkBase { _HexDecoderByteSink(this._sink); + @override void add(List chunk) => addSlice(chunk, 0, chunk.length, false); + @override void addSlice(List chunk, int start, int end, bool isLast) { RangeError.checkValidRange(start, end, chunk.length); @@ -137,6 +144,7 @@ class _HexDecoderByteSink extends ByteConversionSinkBase { if (isLast) _close(chunk, end); } + @override void close() => _close(); /// Like [close], but includes [chunk] and [index] in the [FormatException] diff --git a/pkgs/convert/lib/src/hex/encoder.dart b/pkgs/convert/lib/src/hex/encoder.dart index 261a5d99..c45884f1 100644 --- a/pkgs/convert/lib/src/hex/encoder.dart +++ b/pkgs/convert/lib/src/hex/encoder.dart @@ -19,8 +19,10 @@ const hexEncoder = HexEncoder._(); class HexEncoder extends Converter, String> { const HexEncoder._(); - String convert(List bytes) => _convert(bytes, 0, bytes.length); + @override + String convert(List input) => _convert(input, 0, input.length); + @override ByteConversionSink startChunkedConversion(Sink sink) => _HexEncoderSink(sink); } @@ -32,16 +34,19 @@ class _HexEncoderSink extends ByteConversionSinkBase { _HexEncoderSink(this._sink); + @override void add(List chunk) { _sink.add(_convert(chunk, 0, chunk.length)); } + @override void addSlice(List chunk, int start, int end, bool isLast) { RangeError.checkValidRange(start, end, chunk.length); _sink.add(_convert(chunk, start, end)); if (isLast) _sink.close(); } + @override void close() { _sink.close(); } diff --git a/pkgs/convert/lib/src/identity_codec.dart b/pkgs/convert/lib/src/identity_codec.dart index 9da7bca0..2df6144f 100644 --- a/pkgs/convert/lib/src/identity_codec.dart +++ b/pkgs/convert/lib/src/identity_codec.dart @@ -2,6 +2,7 @@ import 'dart:convert'; class _IdentityConverter extends Converter { _IdentityConverter(); + @override T convert(T input) => input; } @@ -17,12 +18,15 @@ class _IdentityConverter extends Converter { class IdentityCodec extends Codec { const IdentityCodec(); + @override Converter get decoder => _IdentityConverter(); + @override Converter get encoder => _IdentityConverter(); /// Fuse with an other codec. /// /// Fusing with the identify converter is a no-op, so this always return /// [other]. + @override Codec fuse(Codec other) => other; } diff --git a/pkgs/convert/lib/src/percent.dart b/pkgs/convert/lib/src/percent.dart index b06d08fc..4a2f3770 100644 --- a/pkgs/convert/lib/src/percent.dart +++ b/pkgs/convert/lib/src/percent.dart @@ -31,7 +31,9 @@ const percent = PercentCodec._(); /// interprets `+` as `0x2B` rather than `0x20` as emitted by /// [Uri.encodeQueryComponent]. class PercentCodec extends Codec, String> { + @override PercentEncoder get encoder => percentEncoder; + @override PercentDecoder get decoder => percentDecoder; const PercentCodec._(); diff --git a/pkgs/convert/lib/src/percent/decoder.dart b/pkgs/convert/lib/src/percent/decoder.dart index 456c8883..d74ae9ce 100644 --- a/pkgs/convert/lib/src/percent/decoder.dart +++ b/pkgs/convert/lib/src/percent/decoder.dart @@ -28,18 +28,20 @@ const _lastPercent = -1; class PercentDecoder extends Converter> { const PercentDecoder._(); - List convert(String string) { + @override + List convert(String input) { var buffer = Uint8Buffer(); - var lastDigit = _decode(string.codeUnits, 0, string.length, buffer); + var lastDigit = _decode(input.codeUnits, 0, input.length, buffer); if (lastDigit != null) { throw FormatException( - "Input ended with incomplete encoded byte.", string, string.length); + "Input ended with incomplete encoded byte.", input, input.length); } return buffer.buffer.asUint8List(0, buffer.length); } + @override StringConversionSink startChunkedConversion(Sink> sink) => _PercentDecoderSink(sink); } @@ -60,6 +62,7 @@ class _PercentDecoderSink extends StringConversionSinkBase { _PercentDecoderSink(this._sink); + @override void addSlice(String string, int start, int end, bool isLast) { RangeError.checkValidRange(start, end, string.length); @@ -91,9 +94,11 @@ class _PercentDecoderSink extends StringConversionSinkBase { if (isLast) _close(string, end); } + @override ByteConversionSink asUtf8Sink(bool allowMalformed) => _PercentDecoderByteSink(_sink); + @override void close() => _close(); /// Like [close], but includes [string] and [index] in the [FormatException] @@ -124,8 +129,10 @@ class _PercentDecoderByteSink extends ByteConversionSinkBase { _PercentDecoderByteSink(this._sink); + @override void add(List chunk) => addSlice(chunk, 0, chunk.length, false); + @override void addSlice(List chunk, int start, int end, bool isLast) { RangeError.checkValidRange(start, end, chunk.length); @@ -156,6 +163,7 @@ class _PercentDecoderByteSink extends ByteConversionSinkBase { if (isLast) _close(chunk, end); } + @override void close() => _close(); /// Like [close], but includes [chunk] and [index] in the [FormatException] diff --git a/pkgs/convert/lib/src/percent/encoder.dart b/pkgs/convert/lib/src/percent/encoder.dart index a8614689..7f14fc93 100644 --- a/pkgs/convert/lib/src/percent/encoder.dart +++ b/pkgs/convert/lib/src/percent/encoder.dart @@ -22,8 +22,10 @@ const percentEncoder = PercentEncoder._(); class PercentEncoder extends Converter, String> { const PercentEncoder._(); - String convert(List bytes) => _convert(bytes, 0, bytes.length); + @override + String convert(List input) => _convert(input, 0, input.length); + @override ByteConversionSink startChunkedConversion(Sink sink) => _PercentEncoderSink(sink); } @@ -35,16 +37,19 @@ class _PercentEncoderSink extends ByteConversionSinkBase { _PercentEncoderSink(this._sink); + @override void add(List chunk) { _sink.add(_convert(chunk, 0, chunk.length)); } + @override void addSlice(List chunk, int start, int end, bool isLast) { RangeError.checkValidRange(start, end, chunk.length); _sink.add(_convert(chunk, start, end)); if (isLast) _sink.close(); } + @override void close() { _sink.close(); } diff --git a/pkgs/convert/lib/src/string_accumulator_sink.dart b/pkgs/convert/lib/src/string_accumulator_sink.dart index c8bdf750..98b476eb 100644 --- a/pkgs/convert/lib/src/string_accumulator_sink.dart +++ b/pkgs/convert/lib/src/string_accumulator_sink.dart @@ -23,23 +23,26 @@ class StringAccumulatorSink extends StringConversionSinkBase { _buffer.clear(); } - void add(String chunk) { + @override + void add(String str) { if (_isClosed) { throw StateError("Can't add to a closed sink."); } - _buffer.write(chunk); + _buffer.write(str); } - void addSlice(String chunk, int start, int end, bool isLast) { + @override + void addSlice(String str, int start, int end, bool isLast) { if (_isClosed) { throw StateError("Can't add to a closed sink."); } - _buffer.write(chunk.substring(start, end)); + _buffer.write(str.substring(start, end)); if (isLast) _isClosed = true; } + @override void close() { _isClosed = true; } diff --git a/pkgs/convert/pubspec.yaml b/pkgs/convert/pubspec.yaml index 8783bb31..11bf4234 100644 --- a/pkgs/convert/pubspec.yaml +++ b/pkgs/convert/pubspec.yaml @@ -1,16 +1,16 @@ name: convert -version: 3.0.1 +version: 3.0.2-dev description: >- Utilities for converting between data representations. Provides a number of Sink, Codec, Decoder, and Encoder types. repository: https://github.com/dart-lang/convert environment: - sdk: '>=2.12.0-0 <3.0.0' + sdk: '>=2.12.0 <3.0.0' dependencies: typed_data: ^1.3.0 dev_dependencies: - pedantic: ^1.10.0 - test: ^1.16.0-nullsafety.9 + lints: ^1.0.0 + test: ^1.16.0 diff --git a/pkgs/convert/test/accumulator_sink_test.dart b/pkgs/convert/test/accumulator_sink_test.dart index 2c280e12..1f0b2041 100644 --- a/pkgs/convert/test/accumulator_sink_test.dart +++ b/pkgs/convert/test/accumulator_sink_test.dart @@ -6,7 +6,7 @@ import 'package:convert/convert.dart'; import 'package:test/test.dart'; void main() { - var sink; + late AccumulatorSink sink; setUp(() { sink = AccumulatorSink(); }); @@ -25,13 +25,19 @@ void main() { }); test("clear() clears the events", () { - sink..add(1)..add(2)..add(3); + sink + ..add(1) + ..add(2) + ..add(3); expect(sink.events, equals([1, 2, 3])); sink.clear(); expect(sink.events, isEmpty); - sink..add(4)..add(5)..add(6); + sink + ..add(4) + ..add(5) + ..add(6); expect(sink.events, equals([4, 5, 6])); }); diff --git a/pkgs/convert/test/hex_test.dart b/pkgs/convert/test/hex_test.dart index bbb18086..5e8fa28e 100644 --- a/pkgs/convert/test/hex_test.dart +++ b/pkgs/convert/test/hex_test.dart @@ -3,6 +3,7 @@ // BSD-style license that can be found in the LICENSE file. import 'dart:async'; +import 'dart:convert'; import 'package:convert/convert.dart'; import 'package:test/test.dart'; @@ -80,7 +81,7 @@ void main() { group("with chunked conversion", () { late List> results; - var sink; + late StringConversionSink sink; setUp(() { results = []; var controller = StreamController>(sync: true); diff --git a/pkgs/convert/test/percent_test.dart b/pkgs/convert/test/percent_test.dart index 87d903c4..9075ea11 100644 --- a/pkgs/convert/test/percent_test.dart +++ b/pkgs/convert/test/percent_test.dart @@ -3,6 +3,7 @@ // BSD-style license that can be found in the LICENSE file. import 'dart:async'; +import 'dart:convert'; import 'package:convert/convert.dart'; import 'package:test/test.dart'; @@ -90,7 +91,7 @@ void main() { group("with chunked conversion", () { late List> results; - var sink; + late StringConversionSink sink; setUp(() { results = []; var controller = StreamController>(sync: true); diff --git a/pkgs/convert/test/string_accumulator_sink_test.dart b/pkgs/convert/test/string_accumulator_sink_test.dart index 2bef19b9..6c5b9faa 100644 --- a/pkgs/convert/test/string_accumulator_sink_test.dart +++ b/pkgs/convert/test/string_accumulator_sink_test.dart @@ -6,7 +6,7 @@ import 'package:convert/convert.dart'; import 'package:test/test.dart'; void main() { - var sink; + late StringAccumulatorSink sink; setUp(() { sink = StringAccumulatorSink(); }); From 2963df6ed5e6a1ac4b568d0fecca79dac0ac4303 Mon Sep 17 00:00:00 2001 From: "Lasse R.H. Nielsen" Date: Mon, 30 May 2022 13:25:09 +0200 Subject: [PATCH 040/100] Add missing increment to custom code-page decoder. (dart-lang/convert#62) * Add missing increment to custom code-page decoder. Fixes dart-lang/convert#47. --- pkgs/convert/CHANGELOG.md | 4 +++- pkgs/convert/lib/src/codepage.dart | 2 +- pkgs/convert/pubspec.yaml | 2 +- pkgs/convert/test/codepage_test.dart | 11 +++++++++++ 4 files changed, 16 insertions(+), 3 deletions(-) diff --git a/pkgs/convert/CHANGELOG.md b/pkgs/convert/CHANGELOG.md index 4d059357..797ea917 100644 --- a/pkgs/convert/CHANGELOG.md +++ b/pkgs/convert/CHANGELOG.md @@ -1,4 +1,6 @@ -## 3.0.2-dev +## 3.0.2 + +* Fix bug in `CodePage` class. See issue [#47](https://github.com/dart-lang/convert/issues/47). ## 3.0.1 diff --git a/pkgs/convert/lib/src/codepage.dart b/pkgs/convert/lib/src/codepage.dart index 376a9ecd..cfc58db3 100644 --- a/pkgs/convert/lib/src/codepage.dart +++ b/pkgs/convert/lib/src/codepage.dart @@ -262,7 +262,7 @@ CodePageDecoder _createDecoder(String characters) { throw ArgumentError.value( characters, "characters", "Must contain 256 characters"); } - result[i] = char; + result[i++] = char; allChars |= char; } if (i < 256) { diff --git a/pkgs/convert/pubspec.yaml b/pkgs/convert/pubspec.yaml index 11bf4234..ad683aeb 100644 --- a/pkgs/convert/pubspec.yaml +++ b/pkgs/convert/pubspec.yaml @@ -1,5 +1,5 @@ name: convert -version: 3.0.2-dev +version: 3.0.2 description: >- Utilities for converting between data representations. Provides a number of Sink, Codec, Decoder, and Encoder types. diff --git a/pkgs/convert/test/codepage_test.dart b/pkgs/convert/test/codepage_test.dart index 2105f27a..e93ef30b 100644 --- a/pkgs/convert/test/codepage_test.dart +++ b/pkgs/convert/test/codepage_test.dart @@ -60,4 +60,15 @@ void main() { var decoded = latin3.decode(encoded, allowInvalid: true); expect(decoded, latin2text); }); + + test("Custom code page", () { + var cp = CodePage("custom", "ABCDEF" + "\uFFFD" * 250); + var result = cp.encode("BADCAFE"); + expect(result, [1, 0, 3, 2, 0, 5, 4]); + expect(() => cp.encode("GAD"), throwsFormatException); + expect(cp.encode("GAD", invalidCharacter: 0x3F), [0x3F, 0, 3]); + expect(cp.decode([1, 0, 3, 2, 0, 5, 4]), "BADCAFE"); + expect(() => cp.decode([6, 1, 255]), throwsFormatException); + expect(cp.decode([6, 1, 255], allowInvalid: true), "\u{FFFD}B\u{FFFD}"); + }); } From 0a0700e8fd33e2a3e85e7caaba11ab158696469e Mon Sep 17 00:00:00 2001 From: Devon Carew Date: Mon, 6 Jun 2022 19:19:09 +0000 Subject: [PATCH 041/100] add markdown badges to the readme --- pkgs/convert/CHANGELOG.md | 3 +++ pkgs/convert/README.md | 11 ++++++++++- pkgs/convert/analysis_options.yaml | 1 + pkgs/convert/pubspec.yaml | 2 +- 4 files changed, 15 insertions(+), 2 deletions(-) diff --git a/pkgs/convert/CHANGELOG.md b/pkgs/convert/CHANGELOG.md index 797ea917..c4120a08 100644 --- a/pkgs/convert/CHANGELOG.md +++ b/pkgs/convert/CHANGELOG.md @@ -1,3 +1,6 @@ +## 3.0.3-dev + + ## 3.0.2 * Fix bug in `CodePage` class. See issue [#47](https://github.com/dart-lang/convert/issues/47). diff --git a/pkgs/convert/README.md b/pkgs/convert/README.md index 9a832fda..47392cb6 100644 --- a/pkgs/convert/README.md +++ b/pkgs/convert/README.md @@ -1,6 +1,15 @@ -# Conversion utilities package +[![Dart CI](https://github.com/dart-lang/convert/actions/workflows/test-package.yml/badge.svg)](https://github.com/dart-lang/convert/actions/workflows/test-package.yml) +[![pub package](https://img.shields.io/pub/v/convert.svg)](https://pub.dev/packages/convert) +[![package publisher](https://img.shields.io/pub/publisher/convert.svg)](https://pub.dev/packages/convert/publisher) + +Utilities for converting between data representations. + +## Conversion utilities package This package contains encoders and decoders for converting between different data representations. It's the external counterpart of the `dart:convert` core library, and contains less-central APIs and APIs that need more flexible versioning. + +See also +[api.dart.dev/dart-convert](https://api.dart.dev/stable/dart-convert/dart-convert-library.html). diff --git a/pkgs/convert/analysis_options.yaml b/pkgs/convert/analysis_options.yaml index 85d6c125..162fc088 100644 --- a/pkgs/convert/analysis_options.yaml +++ b/pkgs/convert/analysis_options.yaml @@ -1,4 +1,5 @@ include: package:lints/recommended.yaml + analyzer: strong-mode: implicit-casts: false diff --git a/pkgs/convert/pubspec.yaml b/pkgs/convert/pubspec.yaml index ad683aeb..d3997a7a 100644 --- a/pkgs/convert/pubspec.yaml +++ b/pkgs/convert/pubspec.yaml @@ -1,5 +1,5 @@ name: convert -version: 3.0.2 +version: 3.0.3-dev description: >- Utilities for converting between data representations. Provides a number of Sink, Codec, Decoder, and Encoder types. From 01582d3e874b9b48050c120ad309f1bb5522ad9c Mon Sep 17 00:00:00 2001 From: moritz Date: Tue, 27 Sep 2022 08:50:24 +0000 Subject: [PATCH 042/100] add license --- pkgs/convert/lib/src/identity_codec.dart | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/pkgs/convert/lib/src/identity_codec.dart b/pkgs/convert/lib/src/identity_codec.dart index 2df6144f..0a2a0b52 100644 --- a/pkgs/convert/lib/src/identity_codec.dart +++ b/pkgs/convert/lib/src/identity_codec.dart @@ -1,3 +1,7 @@ +// Copyright (c) 2022, 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 'dart:convert'; class _IdentityConverter extends Converter { From c1b6966c07c86b59a5157ce3099e1151caa29414 Mon Sep 17 00:00:00 2001 From: moritz Date: Tue, 27 Sep 2022 09:34:36 +0000 Subject: [PATCH 043/100] Add fixed datetime parser/formatter --- pkgs/convert/lib/convert.dart | 1 + .../lib/src/fixed_datetime_parser.dart | 152 ++++++++++++++++++ .../test/fixed_datetime_parser_test.dart | 51 ++++++ 3 files changed, 204 insertions(+) create mode 100644 pkgs/convert/lib/src/fixed_datetime_parser.dart create mode 100644 pkgs/convert/test/fixed_datetime_parser_test.dart diff --git a/pkgs/convert/lib/convert.dart b/pkgs/convert/lib/convert.dart index 53a68d85..ce10f7f7 100644 --- a/pkgs/convert/lib/convert.dart +++ b/pkgs/convert/lib/convert.dart @@ -7,6 +7,7 @@ library convert; export 'src/accumulator_sink.dart'; export 'src/byte_accumulator_sink.dart'; export 'src/codepage.dart'; +export 'src/fixed_datetime_parser.dart'; export 'src/hex.dart'; export 'src/identity_codec.dart'; export 'src/percent.dart'; diff --git a/pkgs/convert/lib/src/fixed_datetime_parser.dart b/pkgs/convert/lib/src/fixed_datetime_parser.dart new file mode 100644 index 00000000..4e3cb40a --- /dev/null +++ b/pkgs/convert/lib/src/fixed_datetime_parser.dart @@ -0,0 +1,152 @@ +// 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. + +/// A class for parsing dates for a fixed format string. For example, calling +/// `DateParser('YYYYMMDDhhmmss').parseToLocal('19960425050322')` has the same +/// result as calling `DateTime(1996, 4, 25, 5, 3, 22)`. +/// +/// The allowed characters are +/// * Y a digit used in the time scale component “calendar year” +/// * M a digit used in the time scale component “calendar month” +/// * D a digit used in the time scale component “calendar day” +/// * E a digit used in the time scale component “decade” +/// * C a digit used in the time scale component “century” +/// * h a digit used in the time scale component “clock hour” +/// * m a digit used in the time scale component “clock minute” +/// * s a digit used in the time scale component “clock second” +/// as specified in the ISO 8601 standard. +/// +/// Non-allowed characters in the format _pattern are ignored, therefore +/// `YYYY kiwi MM` is the same format string as `YYYY------MM`. +/// +/// Note: this class differs from [DateFormat] in that here, the characters are +/// treated literally, i.e. the format string `YYY` matching `996` would result in +/// the same as calling `DateTime(996)`. [DateFormat] on the other hand uses the +/// specification in https://www.unicode.org/reports/tr35/tr35-dates.html#Date_Field_Symbol_Table, +/// the format string (or "skeleton") `YYY` specifies only the padding, so +/// `1996` would be a valid match. This limits is use to format strings +/// containing delimiters, as the parser would not know how many digits to take +/// otherwise. +/// +/// Also, this parser does not know about locales and parses to the current +/// locale only. +class FixedDateTimeParser { + static const _validChars = ['Y', 'M', 'D', 'E', 'C', 'h', 'm', 's']; + + final String _pattern; + final _occurences = {}; + + FixedDateTimeParser(this._pattern) { + String current = ''; + for (var i = 0; i < _pattern.length; i++) { + var char = _pattern[i]; + if (!_validChars.contains(char)) { + current = ''; + continue; + } + var newChar = current != char; + if (newChar) { + var hasNotSeenBefore = !_occurences.containsKey(char); + if (hasNotSeenBefore) { + _occurences[char] = _Range(i, i); + } else { + throw Exception( + 'The _pattern string "$_pattern" contains multiple instances of the formatting char block $char, both at position ${_occurences[char]!.from} and $i'); + } + } + current = char; + _occurences.update(current, (value) => _Range(value.from, value.to + 1)); + } + } + + /// Convert a datetime to a string exactly as specified by the [_pattern]. + String format(DateTime dt) { + var startingPoints = + _occurences.map((key, value) => MapEntry(value.from, key)); + var sb = StringBuffer(); + for (var i = 0; i < _pattern.length; i++) { + if (startingPoints.containsKey(i)) { + var key = startingPoints[i]; + var length = _occurences[key]!.length; + var number = _extractNumFromDateTime(key, dt); + var numAsString = number.toString(); + if (numAsString.length > length) { + throw Exception( + "The datetime $dt cannot be parsed as $number is longer than the _pattern $key allows"); + } else { + sb.write(numAsString.padLeft(length, '0')); + } + i += length - 1; + } else { + sb.write(_pattern[i]); + } + } + return sb.toString(); + } + + int _extractNumFromDateTime(String? key, DateTime dt) { + switch (key) { + case 'Y': + return dt.year; + case 'C': + return (dt.year / 100).floor(); + case 'E': + return (dt.year / 10).floor(); + case 'M': + return dt.month; + case 'D': + return dt.day; + case 'h': + return dt.hour; + case 'm': + return dt.minute; + case 's': + return dt.second; + } + throw ArgumentError.value(key); + } + + /// Parse a string [dateTimeStr] to a local [DateTime] as specified in the + /// [_pattern]. Throws an exception on failure. + DateTime parseToLocal(String dateTimeStr) { + int? year = _extractDateTimeFromStr(dateTimeStr, 'Y') ?? 1; + int? century = _extractDateTimeFromStr(dateTimeStr, 'C') ?? 0; + int? decade = _extractDateTimeFromStr(dateTimeStr, 'E') ?? 0; + var totalYear = year + 100 * century + 10 * decade; + int? month = _extractDateTimeFromStr(dateTimeStr, 'M') ?? 1; + int? day = _extractDateTimeFromStr(dateTimeStr, 'D') ?? 1; + int? hour = _extractDateTimeFromStr(dateTimeStr, 'h') ?? 0; + int? minute = _extractDateTimeFromStr(dateTimeStr, 'm') ?? 0; + int? second = _extractDateTimeFromStr(dateTimeStr, 's') ?? 0; + return DateTime(totalYear, month, day, hour, minute, second, 0, 0); + } + + /// Same as [parseToLocal], but returns null if the string could not be + /// parsed. + DateTime? tryParseToLocal(String dateTimeStr) { + try { + return parseToLocal(dateTimeStr); + } catch (_) { + return null; + } + } + + int? _extractDateTimeFromStr(String s, String id) { + var pos = _occurences[id]; + if (pos != null) { + return int.parse(s.substring(pos.from, pos.to)); + } else { + return null; + } + } +} + +class _Range { + final int from; + final int to; + + _Range(this.from, this.to); + + int get length => to - from; +} diff --git a/pkgs/convert/test/fixed_datetime_parser_test.dart b/pkgs/convert/test/fixed_datetime_parser_test.dart new file mode 100644 index 00000000..8b29aa65 --- /dev/null +++ b/pkgs/convert/test/fixed_datetime_parser_test.dart @@ -0,0 +1,51 @@ +import 'package:convert/src/fixed_datetime_parser.dart'; +import 'package:test/test.dart'; + +void main() { + test('Parse only year', () { + var time = FixedDateTimeParser('YYYY').parseToLocal('1996'); + expect(time, DateTime(1996)); + }); + test('Escaped chars are ignored', () { + var time = FixedDateTimeParser('YYYY kiwi MM').parseToLocal('1996 rnad 01'); + expect(time, DateTime(1996, 1)); + }); + test('Parse two years throws', () { + expect(() => FixedDateTimeParser('YYYY YYYY'), throwsException); + }); + test('Parse year and century', () { + var time = FixedDateTimeParser('CCYY').parseToLocal('1996'); + expect(time, DateTime(1996)); + }); + test('Parse year, decade and century', () { + var time = FixedDateTimeParser('CCEY').parseToLocal('1996'); + expect(time, DateTime(1996)); + }); + test('Parse year, century, month', () { + var time = FixedDateTimeParser('CCYY MM').parseToLocal('1996 04'); + expect(time, DateTime(1996, 4)); + }); + test('Parse year, century, month, day', () { + var time = FixedDateTimeParser('CCYY MM-DD').parseToLocal('1996 04-25'); + expect(time, DateTime(1996, 4, 25)); + }); + test('Parse year, century, month, day, hour, minute, second', () { + var time = FixedDateTimeParser('CCYY MM-DD hh:mm:ss') + .parseToLocal('1996 04-25 05:03:22'); + expect(time, DateTime(1996, 4, 25, 5, 3, 22)); + }); + test('Parse YYYYMMDDhhmmss', () { + var time = + FixedDateTimeParser('YYYYMMDDhhmmss').parseToLocal('19960425050322'); + expect(time, DateTime(1996, 4, 25, 5, 3, 22)); + }); + test('Format simple', () { + var time = DateTime(1996, 1); + expect('1996 kiwi 01', FixedDateTimeParser('YYYY kiwi MM').format(time)); + }); + test('Format YYYYMMDDhhmmss', () { + var str = FixedDateTimeParser('YYYYMMDDhhmmss') + .format(DateTime(1996, 4, 25, 5, 3, 22)); + expect('19960425050322', str); + }); +} From 135bfa5ec44d56d6b50585923ea70194e5238adf Mon Sep 17 00:00:00 2001 From: moritz Date: Tue, 27 Sep 2022 09:37:07 +0000 Subject: [PATCH 044/100] rename --- pkgs/convert/lib/convert.dart | 2 +- ..._parser.dart => fixed_datetime_codec.dart} | 23 +++++++-------- ...st.dart => fixed_datetime_codec_test.dart} | 28 +++++++++---------- 3 files changed, 27 insertions(+), 26 deletions(-) rename pkgs/convert/lib/src/{fixed_datetime_parser.dart => fixed_datetime_codec.dart} (88%) rename pkgs/convert/test/{fixed_datetime_parser_test.dart => fixed_datetime_codec_test.dart} (54%) diff --git a/pkgs/convert/lib/convert.dart b/pkgs/convert/lib/convert.dart index ce10f7f7..afe0e99a 100644 --- a/pkgs/convert/lib/convert.dart +++ b/pkgs/convert/lib/convert.dart @@ -7,7 +7,7 @@ library convert; export 'src/accumulator_sink.dart'; export 'src/byte_accumulator_sink.dart'; export 'src/codepage.dart'; -export 'src/fixed_datetime_parser.dart'; +export 'src/fixed_datetime_codec.dart'; export 'src/hex.dart'; export 'src/identity_codec.dart'; export 'src/percent.dart'; diff --git a/pkgs/convert/lib/src/fixed_datetime_parser.dart b/pkgs/convert/lib/src/fixed_datetime_codec.dart similarity index 88% rename from pkgs/convert/lib/src/fixed_datetime_parser.dart rename to pkgs/convert/lib/src/fixed_datetime_codec.dart index 4e3cb40a..dd1776c9 100644 --- a/pkgs/convert/lib/src/fixed_datetime_parser.dart +++ b/pkgs/convert/lib/src/fixed_datetime_codec.dart @@ -2,9 +2,10 @@ // 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. -/// A class for parsing dates for a fixed format string. For example, calling -/// `DateParser('YYYYMMDDhhmmss').parseToLocal('19960425050322')` has the same -/// result as calling `DateTime(1996, 4, 25, 5, 3, 22)`. +/// A class for parsing and formatting dates for a fixed format string. For +/// example, calling +/// `FixedDateTimeCodec('YYYYMMDDhhmmss').decodeToLocal('19960425050322')` has +/// the same result as calling `DateTime(1996, 4, 25, 5, 3, 22)`. /// /// The allowed characters are /// * Y a digit used in the time scale component “calendar year” @@ -17,7 +18,7 @@ /// * s a digit used in the time scale component “clock second” /// as specified in the ISO 8601 standard. /// -/// Non-allowed characters in the format _pattern are ignored, therefore +/// Non-allowed characters in the format [_pattern] are ignored, therefore /// `YYYY kiwi MM` is the same format string as `YYYY------MM`. /// /// Note: this class differs from [DateFormat] in that here, the characters are @@ -31,13 +32,13 @@ /// /// Also, this parser does not know about locales and parses to the current /// locale only. -class FixedDateTimeParser { +class FixedDateTimeCodec { static const _validChars = ['Y', 'M', 'D', 'E', 'C', 'h', 'm', 's']; final String _pattern; final _occurences = {}; - FixedDateTimeParser(this._pattern) { + FixedDateTimeCodec(this._pattern) { String current = ''; for (var i = 0; i < _pattern.length; i++) { var char = _pattern[i]; @@ -61,7 +62,7 @@ class FixedDateTimeParser { } /// Convert a datetime to a string exactly as specified by the [_pattern]. - String format(DateTime dt) { + String encode(DateTime dt) { var startingPoints = _occurences.map((key, value) => MapEntry(value.from, key)); var sb = StringBuffer(); @@ -109,7 +110,7 @@ class FixedDateTimeParser { /// Parse a string [dateTimeStr] to a local [DateTime] as specified in the /// [_pattern]. Throws an exception on failure. - DateTime parseToLocal(String dateTimeStr) { + DateTime decodeToLocal(String dateTimeStr) { int? year = _extractDateTimeFromStr(dateTimeStr, 'Y') ?? 1; int? century = _extractDateTimeFromStr(dateTimeStr, 'C') ?? 0; int? decade = _extractDateTimeFromStr(dateTimeStr, 'E') ?? 0; @@ -122,11 +123,11 @@ class FixedDateTimeParser { return DateTime(totalYear, month, day, hour, minute, second, 0, 0); } - /// Same as [parseToLocal], but returns null if the string could not be + /// Same as [decodeToLocal], but returns null if the string could not be /// parsed. - DateTime? tryParseToLocal(String dateTimeStr) { + DateTime? tryDecodeToLocal(String dateTimeStr) { try { - return parseToLocal(dateTimeStr); + return decodeToLocal(dateTimeStr); } catch (_) { return null; } diff --git a/pkgs/convert/test/fixed_datetime_parser_test.dart b/pkgs/convert/test/fixed_datetime_codec_test.dart similarity index 54% rename from pkgs/convert/test/fixed_datetime_parser_test.dart rename to pkgs/convert/test/fixed_datetime_codec_test.dart index 8b29aa65..63b5176b 100644 --- a/pkgs/convert/test/fixed_datetime_parser_test.dart +++ b/pkgs/convert/test/fixed_datetime_codec_test.dart @@ -1,51 +1,51 @@ -import 'package:convert/src/fixed_datetime_parser.dart'; +import 'package:convert/src/fixed_datetime_codec.dart'; import 'package:test/test.dart'; void main() { test('Parse only year', () { - var time = FixedDateTimeParser('YYYY').parseToLocal('1996'); + var time = FixedDateTimeCodec('YYYY').decodeToLocal('1996'); expect(time, DateTime(1996)); }); test('Escaped chars are ignored', () { - var time = FixedDateTimeParser('YYYY kiwi MM').parseToLocal('1996 rnad 01'); + var time = FixedDateTimeCodec('YYYY kiwi MM').decodeToLocal('1996 rnad 01'); expect(time, DateTime(1996, 1)); }); test('Parse two years throws', () { - expect(() => FixedDateTimeParser('YYYY YYYY'), throwsException); + expect(() => FixedDateTimeCodec('YYYY YYYY'), throwsException); }); test('Parse year and century', () { - var time = FixedDateTimeParser('CCYY').parseToLocal('1996'); + var time = FixedDateTimeCodec('CCYY').decodeToLocal('1996'); expect(time, DateTime(1996)); }); test('Parse year, decade and century', () { - var time = FixedDateTimeParser('CCEY').parseToLocal('1996'); + var time = FixedDateTimeCodec('CCEY').decodeToLocal('1996'); expect(time, DateTime(1996)); }); test('Parse year, century, month', () { - var time = FixedDateTimeParser('CCYY MM').parseToLocal('1996 04'); + var time = FixedDateTimeCodec('CCYY MM').decodeToLocal('1996 04'); expect(time, DateTime(1996, 4)); }); test('Parse year, century, month, day', () { - var time = FixedDateTimeParser('CCYY MM-DD').parseToLocal('1996 04-25'); + var time = FixedDateTimeCodec('CCYY MM-DD').decodeToLocal('1996 04-25'); expect(time, DateTime(1996, 4, 25)); }); test('Parse year, century, month, day, hour, minute, second', () { - var time = FixedDateTimeParser('CCYY MM-DD hh:mm:ss') - .parseToLocal('1996 04-25 05:03:22'); + var time = FixedDateTimeCodec('CCYY MM-DD hh:mm:ss') + .decodeToLocal('1996 04-25 05:03:22'); expect(time, DateTime(1996, 4, 25, 5, 3, 22)); }); test('Parse YYYYMMDDhhmmss', () { var time = - FixedDateTimeParser('YYYYMMDDhhmmss').parseToLocal('19960425050322'); + FixedDateTimeCodec('YYYYMMDDhhmmss').decodeToLocal('19960425050322'); expect(time, DateTime(1996, 4, 25, 5, 3, 22)); }); test('Format simple', () { var time = DateTime(1996, 1); - expect('1996 kiwi 01', FixedDateTimeParser('YYYY kiwi MM').format(time)); + expect('1996 kiwi 01', FixedDateTimeCodec('YYYY kiwi MM').encode(time)); }); test('Format YYYYMMDDhhmmss', () { - var str = FixedDateTimeParser('YYYYMMDDhhmmss') - .format(DateTime(1996, 4, 25, 5, 3, 22)); + var str = FixedDateTimeCodec('YYYYMMDDhhmmss') + .encode(DateTime(1996, 4, 25, 5, 3, 22)); expect('19960425050322', str); }); } From ce84dc8888e5d08b0a6edfada43ca5ed5004b632 Mon Sep 17 00:00:00 2001 From: moritz Date: Tue, 27 Sep 2022 09:44:40 +0000 Subject: [PATCH 045/100] add licenses --- pkgs/convert/lib/src/fixed_datetime_codec.dart | 2 +- pkgs/convert/test/fixed_datetime_codec_test.dart | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/pkgs/convert/lib/src/fixed_datetime_codec.dart b/pkgs/convert/lib/src/fixed_datetime_codec.dart index dd1776c9..1ab78127 100644 --- a/pkgs/convert/lib/src/fixed_datetime_codec.dart +++ b/pkgs/convert/lib/src/fixed_datetime_codec.dart @@ -1,4 +1,4 @@ -// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file +// Copyright (c) 2022, 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. diff --git a/pkgs/convert/test/fixed_datetime_codec_test.dart b/pkgs/convert/test/fixed_datetime_codec_test.dart index 63b5176b..2f3d3037 100644 --- a/pkgs/convert/test/fixed_datetime_codec_test.dart +++ b/pkgs/convert/test/fixed_datetime_codec_test.dart @@ -1,3 +1,7 @@ +// Copyright (c) 2022, 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:convert/src/fixed_datetime_codec.dart'; import 'package:test/test.dart'; From bb2aff9b9bd85a4214991b86f71edb2964eff4a4 Mon Sep 17 00:00:00 2001 From: moritz Date: Tue, 27 Sep 2022 13:56:18 +0000 Subject: [PATCH 046/100] add more changes as per review --- .../convert/lib/src/fixed_datetime_codec.dart | 187 ++++++++++-------- .../test/fixed_datetime_codec_test.dart | 32 +-- 2 files changed, 129 insertions(+), 90 deletions(-) diff --git a/pkgs/convert/lib/src/fixed_datetime_codec.dart b/pkgs/convert/lib/src/fixed_datetime_codec.dart index 1ab78127..8ab184ad 100644 --- a/pkgs/convert/lib/src/fixed_datetime_codec.dart +++ b/pkgs/convert/lib/src/fixed_datetime_codec.dart @@ -2,24 +2,28 @@ // 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 'dart:collection'; + /// A class for parsing and formatting dates for a fixed format string. For /// example, calling /// `FixedDateTimeCodec('YYYYMMDDhhmmss').decodeToLocal('19960425050322')` has /// the same result as calling `DateTime(1996, 4, 25, 5, 3, 22)`. /// /// The allowed characters are -/// * Y a digit used in the time scale component “calendar year” -/// * M a digit used in the time scale component “calendar month” -/// * D a digit used in the time scale component “calendar day” -/// * E a digit used in the time scale component “decade” -/// * C a digit used in the time scale component “century” -/// * h a digit used in the time scale component “clock hour” -/// * m a digit used in the time scale component “clock minute” -/// * s a digit used in the time scale component “clock second” +/// * `Y` a digit used in the time scale component “calendar year” +/// * `M` a digit used in the time scale component “calendar month” +/// * `D` a digit used in the time scale component “calendar day” +/// * `E` a digit used in the time scale component “decade” +/// * `C` a digit used in the time scale component “century” +/// * `h` a digit used in the time scale component “clock hour” +/// * `m` a digit used in the time scale component “clock minute” +/// * `s` a digit used in the time scale component “clock second” /// as specified in the ISO 8601 standard. /// -/// Non-allowed characters in the format [_pattern] are ignored, therefore -/// `YYYY kiwi MM` is the same format string as `YYYY------MM`. +/// Non-allowed characters in the format [pattern] are ignored when decoding a +/// string, in this case `YYYY kiwi MM` is the same format string as +/// `YYYY------MM`. When encoding a datetime, the non-format characters are in +/// the output verbatim. /// /// Note: this class differs from [DateFormat] in that here, the characters are /// treated literally, i.e. the format string `YYY` matching `996` would result in @@ -29,61 +33,75 @@ /// `1996` would be a valid match. This limits is use to format strings /// containing delimiters, as the parser would not know how many digits to take /// otherwise. -/// -/// Also, this parser does not know about locales and parses to the current -/// locale only. -class FixedDateTimeCodec { - static const _validChars = ['Y', 'M', 'D', 'E', 'C', 'h', 'm', 's']; +class FixedDateTimeFormatter { + static const _validFormatCharacters = 'YMDEChms'; - final String _pattern; - final _occurences = {}; + final String pattern; + // ignore: prefer_collection_literals + final _occurences = LinkedHashMap(); - FixedDateTimeCodec(this._pattern) { - String current = ''; - for (var i = 0; i < _pattern.length; i++) { - var char = _pattern[i]; - if (!_validChars.contains(char)) { - current = ''; - continue; - } - var newChar = current != char; - if (newChar) { - var hasNotSeenBefore = !_occurences.containsKey(char); - if (hasNotSeenBefore) { - _occurences[char] = _Range(i, i); + /// Creates a new [FixedDateTimeFormatter] with the provided [pattern]. + /// + /// The [pattern] interprets the characters mentioned in + /// [FixedDateTimeFormatter] to represent fields of a `DateTime` value. Other + /// characters are not special. + /// + /// There must at most be one sequence of each special character to ensure a + /// single source of truth when constructing the [DateTime], so a pattern of + /// `"CCCC-MM-DD, CC"` is invalid, because it has two separate `C` sequences. + FixedDateTimeFormatter(this.pattern) { + String? current; + var start = 0; + for (var i = 0; i < pattern.length; i++) { + var char = pattern[i]; + if (current != char) { + _saveFormatBlock(current, start, i); + if (_validFormatCharacters.contains(char)) { + var hasSeenBefore = _occurences.containsKey(char); + if (hasSeenBefore) { + throw FormatException( + "Pattern contains more than one '$char' block.\n" + "Previous occurrence at position ${_occurences[char]!.from}", + pattern, + i); + } else { + start = i; + current = char; + } } else { - throw Exception( - 'The _pattern string "$_pattern" contains multiple instances of the formatting char block $char, both at position ${_occurences[char]!.from} and $i'); + current = null; } } - current = char; - _occurences.update(current, (value) => _Range(value.from, value.to + 1)); } + _saveFormatBlock(current, start, pattern.length); } - /// Convert a datetime to a string exactly as specified by the [_pattern]. - String encode(DateTime dt) { - var startingPoints = - _occurences.map((key, value) => MapEntry(value.from, key)); - var sb = StringBuffer(); - for (var i = 0; i < _pattern.length; i++) { - if (startingPoints.containsKey(i)) { - var key = startingPoints[i]; - var length = _occurences[key]!.length; - var number = _extractNumFromDateTime(key, dt); - var numAsString = number.toString(); - if (numAsString.length > length) { - throw Exception( - "The datetime $dt cannot be parsed as $number is longer than the _pattern $key allows"); - } else { - sb.write(numAsString.padLeft(length, '0')); - } - i += length - 1; - } else { - sb.write(_pattern[i]); + void _saveFormatBlock(String? current, int start, int i) { + if (current != null) _occurences[current] = _Range(start, i); + } + + /// Convert [DateTime] to a [String] exactly as specified by the [pattern]. + String encode(DateTime datetime) { + var buffer = StringBuffer(); + var previousEnd = 0; + _occurences.forEach((key, value) { + if (previousEnd < value.from) { + buffer.write(pattern.substring(previousEnd, value.from)); } + var number = _extractNumFromDateTime(key, datetime).toString(); + var length = value.length; + if (number.length > length) { + number = number.substring(number.length - length); + } else if (number.length < length) { + number = number.padLeft(length, '0'); + } + buffer.write(number); + previousEnd = value.to; + }); + if (previousEnd < pattern.length) { + buffer.write(pattern.substring(previousEnd, pattern.length)); } - return sb.toString(); + return buffer.toString(); } int _extractNumFromDateTime(String? key, DateTime dt) { @@ -105,38 +123,51 @@ class FixedDateTimeCodec { case 's': return dt.second; } - throw ArgumentError.value(key); + throw AssertionError("Unreachable, the key is checked in the constructor"); } - /// Parse a string [dateTimeStr] to a local [DateTime] as specified in the - /// [_pattern]. Throws an exception on failure. - DateTime decodeToLocal(String dateTimeStr) { - int? year = _extractDateTimeFromStr(dateTimeStr, 'Y') ?? 1; - int? century = _extractDateTimeFromStr(dateTimeStr, 'C') ?? 0; - int? decade = _extractDateTimeFromStr(dateTimeStr, 'E') ?? 0; - var totalYear = year + 100 * century + 10 * decade; - int? month = _extractDateTimeFromStr(dateTimeStr, 'M') ?? 1; - int? day = _extractDateTimeFromStr(dateTimeStr, 'D') ?? 1; - int? hour = _extractDateTimeFromStr(dateTimeStr, 'h') ?? 0; - int? minute = _extractDateTimeFromStr(dateTimeStr, 'm') ?? 0; - int? second = _extractDateTimeFromStr(dateTimeStr, 's') ?? 0; - return DateTime(totalYear, month, day, hour, minute, second, 0, 0); + /// Parse a string [formattedDateTime] to a local [DateTime] as specified in the + /// [pattern], substituting missing values with a default. Throws an exception + /// on failure to parse. + DateTime decode(String formattedDateTime, [bool isUtc = false]) { + return _decode(formattedDateTime, isUtc, int.parse); } - /// Same as [decodeToLocal], but returns null if the string could not be - /// parsed. - DateTime? tryDecodeToLocal(String dateTimeStr) { - try { - return decodeToLocal(dateTimeStr); - } catch (_) { - return null; + /// Same as [decode], but will not throw on parsing erros, instead using + /// the default value as if the format char was not present in the [pattern]. + DateTime tryDecode(String formattedDateTime, [bool isUtc = false]) { + return _decode(formattedDateTime, isUtc, int.tryParse); + } + + DateTime _decode( + String formattedDateTime, + bool isUtc, + int? Function(String) parser, + ) { + var year = _extractDateTimeFromStr(formattedDateTime, 'Y', parser) ?? 0; + var century = _extractDateTimeFromStr(formattedDateTime, 'C', parser) ?? 0; + var decade = _extractDateTimeFromStr(formattedDateTime, 'E', parser) ?? 0; + var totalYear = year + 100 * century + 10 * decade; + var month = _extractDateTimeFromStr(formattedDateTime, 'M', parser) ?? 1; + var day = _extractDateTimeFromStr(formattedDateTime, 'D', parser) ?? 1; + var hour = _extractDateTimeFromStr(formattedDateTime, 'h', parser) ?? 0; + var minute = _extractDateTimeFromStr(formattedDateTime, 'm', parser) ?? 0; + var second = _extractDateTimeFromStr(formattedDateTime, 's', parser) ?? 0; + if (isUtc) { + return DateTime.utc(totalYear, month, day, hour, minute, second, 0, 0); + } else { + return DateTime(totalYear, month, day, hour, minute, second, 0, 0); } } - int? _extractDateTimeFromStr(String s, String id) { + int? _extractDateTimeFromStr( + String s, + String id, + int? Function(String) parser, + ) { var pos = _occurences[id]; if (pos != null) { - return int.parse(s.substring(pos.from, pos.to)); + return parser.call(s.substring(pos.from, pos.to)); } else { return null; } diff --git a/pkgs/convert/test/fixed_datetime_codec_test.dart b/pkgs/convert/test/fixed_datetime_codec_test.dart index 2f3d3037..bb892d1d 100644 --- a/pkgs/convert/test/fixed_datetime_codec_test.dart +++ b/pkgs/convert/test/fixed_datetime_codec_test.dart @@ -7,49 +7,57 @@ import 'package:test/test.dart'; void main() { test('Parse only year', () { - var time = FixedDateTimeCodec('YYYY').decodeToLocal('1996'); + var time = FixedDateTimeFormatter('YYYY').decode('1996'); expect(time, DateTime(1996)); }); test('Escaped chars are ignored', () { - var time = FixedDateTimeCodec('YYYY kiwi MM').decodeToLocal('1996 rnad 01'); + var time = FixedDateTimeFormatter('YYYY kiwi MM').decode('1996 rnad 01'); expect(time, DateTime(1996, 1)); }); test('Parse two years throws', () { - expect(() => FixedDateTimeCodec('YYYY YYYY'), throwsException); + expect(() => FixedDateTimeFormatter('YYYY YYYY'), throwsException); }); test('Parse year and century', () { - var time = FixedDateTimeCodec('CCYY').decodeToLocal('1996'); + var time = FixedDateTimeFormatter('CCYY').decode('1996'); expect(time, DateTime(1996)); }); test('Parse year, decade and century', () { - var time = FixedDateTimeCodec('CCEY').decodeToLocal('1996'); + var time = FixedDateTimeFormatter('CCEY').decode('1996'); expect(time, DateTime(1996)); }); test('Parse year, century, month', () { - var time = FixedDateTimeCodec('CCYY MM').decodeToLocal('1996 04'); + var time = FixedDateTimeFormatter('CCYY MM').decode('1996 04'); expect(time, DateTime(1996, 4)); }); test('Parse year, century, month, day', () { - var time = FixedDateTimeCodec('CCYY MM-DD').decodeToLocal('1996 04-25'); + var time = FixedDateTimeFormatter('CCYY MM-DD').decode('1996 04-25'); expect(time, DateTime(1996, 4, 25)); }); test('Parse year, century, month, day, hour, minute, second', () { - var time = FixedDateTimeCodec('CCYY MM-DD hh:mm:ss') - .decodeToLocal('1996 04-25 05:03:22'); + var time = FixedDateTimeFormatter('CCYY MM-DD hh:mm:ss') + .decode('1996 04-25 05:03:22'); expect(time, DateTime(1996, 4, 25, 5, 3, 22)); }); test('Parse YYYYMMDDhhmmss', () { var time = - FixedDateTimeCodec('YYYYMMDDhhmmss').decodeToLocal('19960425050322'); + FixedDateTimeFormatter('YYYYMMDDhhmmss').decode('19960425050322'); expect(time, DateTime(1996, 4, 25, 5, 3, 22)); }); test('Format simple', () { var time = DateTime(1996, 1); - expect('1996 kiwi 01', FixedDateTimeCodec('YYYY kiwi MM').encode(time)); + expect('1996 kiwi 01', FixedDateTimeFormatter('YYYY kiwi MM').encode(time)); }); test('Format YYYYMMDDhhmmss', () { - var str = FixedDateTimeCodec('YYYYMMDDhhmmss') + var str = FixedDateTimeFormatter('YYYYMMDDhhmmss') .encode(DateTime(1996, 4, 25, 5, 3, 22)); expect('19960425050322', str); }); + test('Format CCEY-MM', () { + var str = FixedDateTimeFormatter('CCEY-MM').encode(DateTime(1996, 4)); + expect('1996-04', str); + }); + test('Format XCCEY-MMX', () { + var str = FixedDateTimeFormatter('XCCEY-MMX').encode(DateTime(1996, 4)); + expect('X1996-04X', str); + }); } From e6b38a9f9cdc78fc3809dd9148d9c60cee6a92f1 Mon Sep 17 00:00:00 2001 From: moritz Date: Tue, 27 Sep 2022 13:59:24 +0000 Subject: [PATCH 047/100] small name change --- pkgs/convert/lib/src/fixed_datetime_codec.dart | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/pkgs/convert/lib/src/fixed_datetime_codec.dart b/pkgs/convert/lib/src/fixed_datetime_codec.dart index 8ab184ad..a8477fbb 100644 --- a/pkgs/convert/lib/src/fixed_datetime_codec.dart +++ b/pkgs/convert/lib/src/fixed_datetime_codec.dart @@ -144,15 +144,15 @@ class FixedDateTimeFormatter { bool isUtc, int? Function(String) parser, ) { - var year = _extractDateTimeFromStr(formattedDateTime, 'Y', parser) ?? 0; - var century = _extractDateTimeFromStr(formattedDateTime, 'C', parser) ?? 0; - var decade = _extractDateTimeFromStr(formattedDateTime, 'E', parser) ?? 0; + var year = _extractNumFromString(formattedDateTime, 'Y', parser) ?? 0; + var century = _extractNumFromString(formattedDateTime, 'C', parser) ?? 0; + var decade = _extractNumFromString(formattedDateTime, 'E', parser) ?? 0; var totalYear = year + 100 * century + 10 * decade; - var month = _extractDateTimeFromStr(formattedDateTime, 'M', parser) ?? 1; - var day = _extractDateTimeFromStr(formattedDateTime, 'D', parser) ?? 1; - var hour = _extractDateTimeFromStr(formattedDateTime, 'h', parser) ?? 0; - var minute = _extractDateTimeFromStr(formattedDateTime, 'm', parser) ?? 0; - var second = _extractDateTimeFromStr(formattedDateTime, 's', parser) ?? 0; + var month = _extractNumFromString(formattedDateTime, 'M', parser) ?? 1; + var day = _extractNumFromString(formattedDateTime, 'D', parser) ?? 1; + var hour = _extractNumFromString(formattedDateTime, 'h', parser) ?? 0; + var minute = _extractNumFromString(formattedDateTime, 'm', parser) ?? 0; + var second = _extractNumFromString(formattedDateTime, 's', parser) ?? 0; if (isUtc) { return DateTime.utc(totalYear, month, day, hour, minute, second, 0, 0); } else { @@ -160,7 +160,7 @@ class FixedDateTimeFormatter { } } - int? _extractDateTimeFromStr( + int? _extractNumFromString( String s, String id, int? Function(String) parser, From afed53ae9232607df60c52ea33ddadf2301271c8 Mon Sep 17 00:00:00 2001 From: moritz Date: Tue, 27 Sep 2022 14:00:23 +0000 Subject: [PATCH 048/100] rename files --- pkgs/convert/lib/convert.dart | 2 +- ...{fixed_datetime_codec.dart => fixed_datetime_formatter.dart} | 0 ...etime_codec_test.dart => fixed_datetime_formatter_test.dart} | 2 +- 3 files changed, 2 insertions(+), 2 deletions(-) rename pkgs/convert/lib/src/{fixed_datetime_codec.dart => fixed_datetime_formatter.dart} (100%) rename pkgs/convert/test/{fixed_datetime_codec_test.dart => fixed_datetime_formatter_test.dart} (97%) diff --git a/pkgs/convert/lib/convert.dart b/pkgs/convert/lib/convert.dart index afe0e99a..4d869813 100644 --- a/pkgs/convert/lib/convert.dart +++ b/pkgs/convert/lib/convert.dart @@ -7,7 +7,7 @@ library convert; export 'src/accumulator_sink.dart'; export 'src/byte_accumulator_sink.dart'; export 'src/codepage.dart'; -export 'src/fixed_datetime_codec.dart'; +export 'src/fixed_datetime_formatter.dart'; export 'src/hex.dart'; export 'src/identity_codec.dart'; export 'src/percent.dart'; diff --git a/pkgs/convert/lib/src/fixed_datetime_codec.dart b/pkgs/convert/lib/src/fixed_datetime_formatter.dart similarity index 100% rename from pkgs/convert/lib/src/fixed_datetime_codec.dart rename to pkgs/convert/lib/src/fixed_datetime_formatter.dart diff --git a/pkgs/convert/test/fixed_datetime_codec_test.dart b/pkgs/convert/test/fixed_datetime_formatter_test.dart similarity index 97% rename from pkgs/convert/test/fixed_datetime_codec_test.dart rename to pkgs/convert/test/fixed_datetime_formatter_test.dart index bb892d1d..fda038d1 100644 --- a/pkgs/convert/test/fixed_datetime_codec_test.dart +++ b/pkgs/convert/test/fixed_datetime_formatter_test.dart @@ -2,7 +2,7 @@ // 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:convert/src/fixed_datetime_codec.dart'; +import 'package:convert/src/fixed_datetime_formatter.dart'; import 'package:test/test.dart'; void main() { From b7059d64c010e89e222c4086c8a4cc30451db365 Mon Sep 17 00:00:00 2001 From: moritz Date: Wed, 28 Sep 2022 08:10:23 +0000 Subject: [PATCH 049/100] apply changes as per review, convert to SOA --- .../fixed_datetime_formatter_benchmark.dart | 31 +++ .../lib/src/fixed_datetime_formatter.dart | 182 +++++++++++------- pkgs/convert/pubspec.yaml | 1 + .../test/fixed_datetime_formatter_test.dart | 21 ++ 4 files changed, 164 insertions(+), 71 deletions(-) create mode 100644 pkgs/convert/benchmark/fixed_datetime_formatter_benchmark.dart diff --git a/pkgs/convert/benchmark/fixed_datetime_formatter_benchmark.dart b/pkgs/convert/benchmark/fixed_datetime_formatter_benchmark.dart new file mode 100644 index 00000000..86b931a6 --- /dev/null +++ b/pkgs/convert/benchmark/fixed_datetime_formatter_benchmark.dart @@ -0,0 +1,31 @@ +// Copyright (c) 2022, 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:benchmark_harness/benchmark_harness.dart'; +import 'package:convert/convert.dart'; + +/// This class tests the implementation speed of +/// _DateFormatPatternField::nextInteger, which is assumed to be called often and +/// thus being performance-critical. +class NewMethod extends BenchmarkBase { + late String result; + late FixedDateTimeFormatter fixedDateTimeFormatter; + NewMethod() : super('Parse a million strings to datetime'); + + @override + void setup() { + fixedDateTimeFormatter = FixedDateTimeFormatter("YYYYMMDDhhmmss"); + } + + @override + void run() { + for (var i = 0; i < 1000000; i++) { + var decode = fixedDateTimeFormatter.decode('19960425050322'); + } + } +} + +void main() { + NewMethod().report(); +} diff --git a/pkgs/convert/lib/src/fixed_datetime_formatter.dart b/pkgs/convert/lib/src/fixed_datetime_formatter.dart index a8477fbb..3f7334e5 100644 --- a/pkgs/convert/lib/src/fixed_datetime_formatter.dart +++ b/pkgs/convert/lib/src/fixed_datetime_formatter.dart @@ -2,10 +2,9 @@ // 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 'dart:collection'; - -/// A class for parsing and formatting dates for a fixed format string. For -/// example, calling +/// A formatter and parser for [DateTime] in a fixed format [String] pattern. +/// +/// For example, calling /// `FixedDateTimeCodec('YYYYMMDDhhmmss').decodeToLocal('19960425050322')` has /// the same result as calling `DateTime(1996, 4, 25, 5, 3, 22)`. /// @@ -30,15 +29,23 @@ import 'dart:collection'; /// the same as calling `DateTime(996)`. [DateFormat] on the other hand uses the /// specification in https://www.unicode.org/reports/tr35/tr35-dates.html#Date_Field_Symbol_Table, /// the format string (or "skeleton") `YYY` specifies only the padding, so -/// `1996` would be a valid match. This limits is use to format strings +/// `1996` would be a valid match. This limits it's use to format strings /// containing delimiters, as the parser would not know how many digits to take /// otherwise. class FixedDateTimeFormatter { - static const _validFormatCharacters = 'YMDEChms'; + static final _validFormatCharacters = 'YMDEChms'.codeUnits; + static final yearCode = 'Y'.codeUnitAt(0); + static final monthCode = 'M'.codeUnitAt(0); + static final dayCode = 'D'.codeUnitAt(0); + static final decadeCode = 'E'.codeUnitAt(0); + static final centuryCode = 'C'.codeUnitAt(0); + static final hourCode = 'h'.codeUnitAt(0); + static final minuteCode = 'm'.codeUnitAt(0); + static final secondCode = 's'.codeUnitAt(0); + static RegExp nonDigits = RegExp(r'\D'); final String pattern; - // ignore: prefer_collection_literals - final _occurences = LinkedHashMap(); + final _parsed = _ParsedPattern(); /// Creates a new [FixedDateTimeFormatter] with the provided [pattern]. /// @@ -50,18 +57,19 @@ class FixedDateTimeFormatter { /// single source of truth when constructing the [DateTime], so a pattern of /// `"CCCC-MM-DD, CC"` is invalid, because it has two separate `C` sequences. FixedDateTimeFormatter(this.pattern) { - String? current; + int? current; var start = 0; - for (var i = 0; i < pattern.length; i++) { - var char = pattern[i]; + var characters = pattern.codeUnits; + for (var i = 0; i < characters.length; i++) { + var char = characters[i]; if (current != char) { - _saveFormatBlock(current, start, i); + _parsed.saveBlock(current, start, i); if (_validFormatCharacters.contains(char)) { - var hasSeenBefore = _occurences.containsKey(char); - if (hasSeenBefore) { + var hasSeenBefore = _parsed.chars.indexOf(char); + if (hasSeenBefore > -1) { throw FormatException( "Pattern contains more than one '$char' block.\n" - "Previous occurrence at position ${_occurences[char]!.from}", + "Previous occurrence at index ${_parsed.starts[hasSeenBefore]}", pattern, i); } else { @@ -73,55 +81,56 @@ class FixedDateTimeFormatter { } } } - _saveFormatBlock(current, start, pattern.length); - } - - void _saveFormatBlock(String? current, int start, int i) { - if (current != null) _occurences[current] = _Range(start, i); + _parsed.saveBlock(current, start, pattern.length); } /// Convert [DateTime] to a [String] exactly as specified by the [pattern]. String encode(DateTime datetime) { var buffer = StringBuffer(); - var previousEnd = 0; - _occurences.forEach((key, value) { - if (previousEnd < value.from) { - buffer.write(pattern.substring(previousEnd, value.from)); + for (var i = 0; i < _parsed.length; i++) { + var start = _parsed.starts[i]; + var end = _parsed.ends[i]; + var length = end - start; + + var previousEnd = i > 0 ? _parsed.ends[i - 1] : 0; + if (previousEnd < start) { + buffer.write(pattern.substring(previousEnd, start)); } - var number = _extractNumFromDateTime(key, datetime).toString(); - var length = value.length; + var number = + _extractNumFromDateTime(_parsed.chars[i], datetime).toString(); if (number.length > length) { number = number.substring(number.length - length); } else if (number.length < length) { number = number.padLeft(length, '0'); } buffer.write(number); - previousEnd = value.to; - }); - if (previousEnd < pattern.length) { - buffer.write(pattern.substring(previousEnd, pattern.length)); + } + if (_parsed.length > 0) { + var lastEnd = _parsed.ends.last; + if (lastEnd < pattern.length) { + buffer.write(pattern.substring(lastEnd, pattern.length)); + } } return buffer.toString(); } - int _extractNumFromDateTime(String? key, DateTime dt) { - switch (key) { - case 'Y': - return dt.year; - case 'C': - return (dt.year / 100).floor(); - case 'E': - return (dt.year / 10).floor(); - case 'M': - return dt.month; - case 'D': - return dt.day; - case 'h': - return dt.hour; - case 'm': - return dt.minute; - case 's': - return dt.second; + int _extractNumFromDateTime(int? key, DateTime dt) { + if (key == yearCode) { + return dt.year; + } else if (key == centuryCode) { + return (dt.year / 100).floor(); + } else if (key == decadeCode) { + return (dt.year / 10).floor(); + } else if (key == monthCode) { + return dt.month; + } else if (key == dayCode) { + return dt.day; + } else if (key == hourCode) { + return dt.hour; + } else if (key == minuteCode) { + return dt.minute; + } else if (key == secondCode) { + return dt.second; } throw AssertionError("Unreachable, the key is checked in the constructor"); } @@ -129,30 +138,47 @@ class FixedDateTimeFormatter { /// Parse a string [formattedDateTime] to a local [DateTime] as specified in the /// [pattern], substituting missing values with a default. Throws an exception /// on failure to parse. - DateTime decode(String formattedDateTime, [bool isUtc = false]) { - return _decode(formattedDateTime, isUtc, int.parse); + DateTime decode(String formattedDateTime, {bool isUtc = false}) { + return _decode(formattedDateTime, isUtc, int.parse, true); } /// Same as [decode], but will not throw on parsing erros, instead using /// the default value as if the format char was not present in the [pattern]. - DateTime tryDecode(String formattedDateTime, [bool isUtc = false]) { - return _decode(formattedDateTime, isUtc, int.tryParse); + DateTime tryDecode(String formattedDateTime, {bool isUtc = false}) { + return _decode(formattedDateTime, isUtc, int.tryParse, false); } DateTime _decode( String formattedDateTime, bool isUtc, int? Function(String) parser, + bool throwOnError, ) { - var year = _extractNumFromString(formattedDateTime, 'Y', parser) ?? 0; - var century = _extractNumFromString(formattedDateTime, 'C', parser) ?? 0; - var decade = _extractNumFromString(formattedDateTime, 'E', parser) ?? 0; + var year = _extractNumFromString( + formattedDateTime, yearCode, parser, throwOnError) ?? + 0; + var century = _extractNumFromString( + formattedDateTime, centuryCode, parser, throwOnError) ?? + 0; + var decade = _extractNumFromString( + formattedDateTime, decadeCode, parser, throwOnError) ?? + 0; var totalYear = year + 100 * century + 10 * decade; - var month = _extractNumFromString(formattedDateTime, 'M', parser) ?? 1; - var day = _extractNumFromString(formattedDateTime, 'D', parser) ?? 1; - var hour = _extractNumFromString(formattedDateTime, 'h', parser) ?? 0; - var minute = _extractNumFromString(formattedDateTime, 'm', parser) ?? 0; - var second = _extractNumFromString(formattedDateTime, 's', parser) ?? 0; + var month = _extractNumFromString( + formattedDateTime, monthCode, parser, throwOnError) ?? + 1; + var day = _extractNumFromString( + formattedDateTime, dayCode, parser, throwOnError) ?? + 1; + var hour = _extractNumFromString( + formattedDateTime, hourCode, parser, throwOnError) ?? + 0; + var minute = _extractNumFromString( + formattedDateTime, minuteCode, parser, throwOnError) ?? + 0; + var second = _extractNumFromString( + formattedDateTime, secondCode, parser, throwOnError) ?? + 0; if (isUtc) { return DateTime.utc(totalYear, month, day, hour, minute, second, 0, 0); } else { @@ -162,23 +188,37 @@ class FixedDateTimeFormatter { int? _extractNumFromString( String s, - String id, + int id, int? Function(String) parser, + bool throwOnError, ) { - var pos = _occurences[id]; - if (pos != null) { - return parser.call(s.substring(pos.from, pos.to)); - } else { - return null; + var index = _parsed.chars.indexOf(id); + if (index > -1) { + var block = s.substring(_parsed.starts[index], _parsed.ends[index]); + if (!nonDigits.hasMatch(block)) { + return parser(block); + } else if (throwOnError) { + throw FormatException('$block should only contain digits'); + } } + return null; } } -class _Range { - final int from; - final int to; +class _ParsedPattern { + final starts = []; + final ends = []; + final chars = []; - _Range(this.from, this.to); + _ParsedPattern(); - int get length => to - from; + int get length => chars.length; + + void saveBlock(int? char, int start, int end) { + if (char != null) { + chars.add(char); + starts.add(start); + ends.add(end); + } + } } diff --git a/pkgs/convert/pubspec.yaml b/pkgs/convert/pubspec.yaml index d3997a7a..4e92df0d 100644 --- a/pkgs/convert/pubspec.yaml +++ b/pkgs/convert/pubspec.yaml @@ -14,3 +14,4 @@ dependencies: dev_dependencies: lints: ^1.0.0 test: ^1.16.0 + benchmark_harness: ^2.2.0 diff --git a/pkgs/convert/test/fixed_datetime_formatter_test.dart b/pkgs/convert/test/fixed_datetime_formatter_test.dart index fda038d1..2dd883aa 100644 --- a/pkgs/convert/test/fixed_datetime_formatter_test.dart +++ b/pkgs/convert/test/fixed_datetime_formatter_test.dart @@ -6,6 +6,7 @@ import 'package:convert/src/fixed_datetime_formatter.dart'; import 'package:test/test.dart'; void main() { + //decode test('Parse only year', () { var time = FixedDateTimeFormatter('YYYY').decode('1996'); expect(time, DateTime(1996)); @@ -43,6 +44,26 @@ void main() { FixedDateTimeFormatter('YYYYMMDDhhmmss').decode('19960425050322'); expect(time, DateTime(1996, 4, 25, 5, 3, 22)); }); + test('Parse hex year throws', () { + expect( + () => FixedDateTimeFormatter('YYYY').decode('0xAB'), + throwsFormatException, + ); + }); + //tryDecode + test('Try parse year', () { + var time = FixedDateTimeFormatter('YYYY').tryDecode('1996'); + expect(time, DateTime(1996)); + }); + test('Try parse hex year return default', () { + var time = FixedDateTimeFormatter('YYYY').tryDecode('0xAB'); + expect(time, DateTime(0)); + }); + test('Try parse invalid returns default', () { + var time = FixedDateTimeFormatter('YYYY').tryDecode('1x96'); + expect(time, DateTime(0)); + }); + //encode test('Format simple', () { var time = DateTime(1996, 1); expect('1996 kiwi 01', FixedDateTimeFormatter('YYYY kiwi MM').encode(time)); From 1e1e5695f9ff11d4c7ccd152095b1d78530e12dc Mon Sep 17 00:00:00 2001 From: moritz Date: Wed, 28 Sep 2022 08:58:30 +0000 Subject: [PATCH 050/100] fix some stuff --- .../lib/src/fixed_datetime_formatter.dart | 75 +++++++++---------- 1 file changed, 36 insertions(+), 39 deletions(-) diff --git a/pkgs/convert/lib/src/fixed_datetime_formatter.dart b/pkgs/convert/lib/src/fixed_datetime_formatter.dart index 3f7334e5..33bc133d 100644 --- a/pkgs/convert/lib/src/fixed_datetime_formatter.dart +++ b/pkgs/convert/lib/src/fixed_datetime_formatter.dart @@ -42,7 +42,6 @@ class FixedDateTimeFormatter { static final hourCode = 'h'.codeUnitAt(0); static final minuteCode = 'm'.codeUnitAt(0); static final secondCode = 's'.codeUnitAt(0); - static RegExp nonDigits = RegExp(r'\D'); final String pattern; final _parsed = _ParsedPattern(); @@ -139,46 +138,34 @@ class FixedDateTimeFormatter { /// [pattern], substituting missing values with a default. Throws an exception /// on failure to parse. DateTime decode(String formattedDateTime, {bool isUtc = false}) { - return _decode(formattedDateTime, isUtc, int.parse, true); + return _decode(formattedDateTime, isUtc, true); } /// Same as [decode], but will not throw on parsing erros, instead using /// the default value as if the format char was not present in the [pattern]. DateTime tryDecode(String formattedDateTime, {bool isUtc = false}) { - return _decode(formattedDateTime, isUtc, int.tryParse, false); + return _decode(formattedDateTime, isUtc, false); } DateTime _decode( String formattedDateTime, bool isUtc, - int? Function(String) parser, bool throwOnError, ) { - var year = _extractNumFromString( - formattedDateTime, yearCode, parser, throwOnError) ?? - 0; - var century = _extractNumFromString( - formattedDateTime, centuryCode, parser, throwOnError) ?? - 0; - var decade = _extractNumFromString( - formattedDateTime, decadeCode, parser, throwOnError) ?? - 0; + List characters = formattedDateTime.codeUnits; + var year = _extractNumFromString(characters, yearCode, throwOnError) ?? 0; + var century = + _extractNumFromString(characters, centuryCode, throwOnError) ?? 0; + var decade = + _extractNumFromString(characters, decadeCode, throwOnError) ?? 0; var totalYear = year + 100 * century + 10 * decade; - var month = _extractNumFromString( - formattedDateTime, monthCode, parser, throwOnError) ?? - 1; - var day = _extractNumFromString( - formattedDateTime, dayCode, parser, throwOnError) ?? - 1; - var hour = _extractNumFromString( - formattedDateTime, hourCode, parser, throwOnError) ?? - 0; - var minute = _extractNumFromString( - formattedDateTime, minuteCode, parser, throwOnError) ?? - 0; - var second = _extractNumFromString( - formattedDateTime, secondCode, parser, throwOnError) ?? - 0; + var month = _extractNumFromString(characters, monthCode, throwOnError) ?? 1; + var day = _extractNumFromString(characters, dayCode, throwOnError) ?? 1; + var hour = _extractNumFromString(characters, hourCode, throwOnError) ?? 0; + var minute = + _extractNumFromString(characters, minuteCode, throwOnError) ?? 0; + var second = + _extractNumFromString(characters, secondCode, throwOnError) ?? 0; if (isUtc) { return DateTime.utc(totalYear, month, day, hour, minute, second, 0, 0); } else { @@ -186,23 +173,33 @@ class FixedDateTimeFormatter { } } - int? _extractNumFromString( - String s, - int id, - int? Function(String) parser, - bool throwOnError, - ) { + int? _extractNumFromString(List characters, int id, bool throwOnError) { var index = _parsed.chars.indexOf(id); if (index > -1) { - var block = s.substring(_parsed.starts[index], _parsed.ends[index]); - if (!nonDigits.hasMatch(block)) { - return parser(block); - } else if (throwOnError) { - throw FormatException('$block should only contain digits'); + var parsed = + tryParse(characters, _parsed.starts[index], _parsed.ends[index]); + if (parsed == null && throwOnError) { + throw FormatException( + '${String.fromCharCodes(characters)} should only contain digits'); } + return parsed; } return null; } + + static final zeroCode = '0'.codeUnitAt(0); + int? tryParse(List characters, int start, int end) { + int result = 0; + for (var i = start; i < end; i++) { + var character = characters[i]; + if (character >= zeroCode && character < zeroCode + 10) { + result = result * 10 + (character - zeroCode); + } else { + return null; + } + } + return result; + } } class _ParsedPattern { From 0bab0cf074e1942a1c6077eb02918dbbcf9f8612 Mon Sep 17 00:00:00 2001 From: moritz Date: Wed, 28 Sep 2022 08:59:02 +0000 Subject: [PATCH 051/100] even faster --- .../lib/src/fixed_datetime_formatter.dart | 64 ++++++++++++------- 1 file changed, 40 insertions(+), 24 deletions(-) diff --git a/pkgs/convert/lib/src/fixed_datetime_formatter.dart b/pkgs/convert/lib/src/fixed_datetime_formatter.dart index 33bc133d..76be52b9 100644 --- a/pkgs/convert/lib/src/fixed_datetime_formatter.dart +++ b/pkgs/convert/lib/src/fixed_datetime_formatter.dart @@ -152,20 +152,39 @@ class FixedDateTimeFormatter { bool isUtc, bool throwOnError, ) { - List characters = formattedDateTime.codeUnits; - var year = _extractNumFromString(characters, yearCode, throwOnError) ?? 0; - var century = - _extractNumFromString(characters, centuryCode, throwOnError) ?? 0; - var decade = - _extractNumFromString(characters, decadeCode, throwOnError) ?? 0; + var characters = formattedDateTime.codeUnits; + var year = 0; + var century = 0; + var decade = 0; + var month = 1; + var day = 1; + var hour = 0; + var minute = 0; + var second = 0; + for (int i = 0; i < _parsed.chars.length; i++) { + var char = _parsed.chars[i]; + var num = _extractNumFromString(characters, i, throwOnError); + if (num != null) { + if (char == yearCode) { + year = num; + } else if (char == centuryCode) { + century = num; + } else if (char == decadeCode) { + decade = num; + } else if (char == monthCode) { + month = num; + } else if (char == dayCode) { + day = num; + } else if (char == hourCode) { + hour = num; + } else if (char == minuteCode) { + minute = num; + } else if (char == secondCode) { + second = num; + } + } + } var totalYear = year + 100 * century + 10 * decade; - var month = _extractNumFromString(characters, monthCode, throwOnError) ?? 1; - var day = _extractNumFromString(characters, dayCode, throwOnError) ?? 1; - var hour = _extractNumFromString(characters, hourCode, throwOnError) ?? 0; - var minute = - _extractNumFromString(characters, minuteCode, throwOnError) ?? 0; - var second = - _extractNumFromString(characters, secondCode, throwOnError) ?? 0; if (isUtc) { return DateTime.utc(totalYear, month, day, hour, minute, second, 0, 0); } else { @@ -173,18 +192,15 @@ class FixedDateTimeFormatter { } } - int? _extractNumFromString(List characters, int id, bool throwOnError) { - var index = _parsed.chars.indexOf(id); - if (index > -1) { - var parsed = - tryParse(characters, _parsed.starts[index], _parsed.ends[index]); - if (parsed == null && throwOnError) { - throw FormatException( - '${String.fromCharCodes(characters)} should only contain digits'); - } - return parsed; + int? _extractNumFromString( + List characters, int index, bool throwOnError) { + var parsed = + tryParse(characters, _parsed.starts[index], _parsed.ends[index]); + if (parsed == null && throwOnError) { + throw FormatException( + '${String.fromCharCodes(characters)} should only contain digits'); } - return null; + return parsed; } static final zeroCode = '0'.codeUnitAt(0); From c585ffef325f4d38a4cf03f2f3325a777fd2ad97 Mon Sep 17 00:00:00 2001 From: moritz Date: Wed, 28 Sep 2022 10:01:48 +0000 Subject: [PATCH 052/100] renaming --- .../lib/src/fixed_datetime_formatter.dart | 62 ++++++++++--------- 1 file changed, 32 insertions(+), 30 deletions(-) diff --git a/pkgs/convert/lib/src/fixed_datetime_formatter.dart b/pkgs/convert/lib/src/fixed_datetime_formatter.dart index 76be52b9..d1bd7cb9 100644 --- a/pkgs/convert/lib/src/fixed_datetime_formatter.dart +++ b/pkgs/convert/lib/src/fixed_datetime_formatter.dart @@ -44,7 +44,7 @@ class FixedDateTimeFormatter { static final secondCode = 's'.codeUnitAt(0); final String pattern; - final _parsed = _ParsedPattern(); + final _blocks = _ParsedFormatBlocks(); /// Creates a new [FixedDateTimeFormatter] with the provided [pattern]. /// @@ -62,13 +62,13 @@ class FixedDateTimeFormatter { for (var i = 0; i < characters.length; i++) { var char = characters[i]; if (current != char) { - _parsed.saveBlock(current, start, i); + _blocks.saveBlock(current, start, i); if (_validFormatCharacters.contains(char)) { - var hasSeenBefore = _parsed.chars.indexOf(char); + var hasSeenBefore = _blocks.formatCharacters.indexOf(char); if (hasSeenBefore > -1) { throw FormatException( "Pattern contains more than one '$char' block.\n" - "Previous occurrence at index ${_parsed.starts[hasSeenBefore]}", + "Previous occurrence at index ${_blocks.starts[hasSeenBefore]}", pattern, i); } else { @@ -80,23 +80,25 @@ class FixedDateTimeFormatter { } } } - _parsed.saveBlock(current, start, pattern.length); + _blocks.saveBlock(current, start, pattern.length); } /// Convert [DateTime] to a [String] exactly as specified by the [pattern]. String encode(DateTime datetime) { var buffer = StringBuffer(); - for (var i = 0; i < _parsed.length; i++) { - var start = _parsed.starts[i]; - var end = _parsed.ends[i]; + for (var i = 0; i < _blocks.length; i++) { + var start = _blocks.starts[i]; + var end = _blocks.ends[i]; var length = end - start; - var previousEnd = i > 0 ? _parsed.ends[i - 1] : 0; + var previousEnd = i > 0 ? _blocks.ends[i - 1] : 0; if (previousEnd < start) { buffer.write(pattern.substring(previousEnd, start)); } - var number = - _extractNumFromDateTime(_parsed.chars[i], datetime).toString(); + var number = _extractNumFromDateTime( + _blocks.formatCharacters[i], + datetime, + ).toString(); if (number.length > length) { number = number.substring(number.length - length); } else if (number.length < length) { @@ -104,8 +106,8 @@ class FixedDateTimeFormatter { } buffer.write(number); } - if (_parsed.length > 0) { - var lastEnd = _parsed.ends.last; + if (_blocks.length > 0) { + var lastEnd = _blocks.ends.last; if (lastEnd < pattern.length) { buffer.write(pattern.substring(lastEnd, pattern.length)); } @@ -113,22 +115,22 @@ class FixedDateTimeFormatter { return buffer.toString(); } - int _extractNumFromDateTime(int? key, DateTime dt) { - if (key == yearCode) { + int _extractNumFromDateTime(int? formatChar, DateTime dt) { + if (formatChar == yearCode) { return dt.year; - } else if (key == centuryCode) { + } else if (formatChar == centuryCode) { return (dt.year / 100).floor(); - } else if (key == decadeCode) { + } else if (formatChar == decadeCode) { return (dt.year / 10).floor(); - } else if (key == monthCode) { + } else if (formatChar == monthCode) { return dt.month; - } else if (key == dayCode) { + } else if (formatChar == dayCode) { return dt.day; - } else if (key == hourCode) { + } else if (formatChar == hourCode) { return dt.hour; - } else if (key == minuteCode) { + } else if (formatChar == minuteCode) { return dt.minute; - } else if (key == secondCode) { + } else if (formatChar == secondCode) { return dt.second; } throw AssertionError("Unreachable, the key is checked in the constructor"); @@ -161,8 +163,8 @@ class FixedDateTimeFormatter { var hour = 0; var minute = 0; var second = 0; - for (int i = 0; i < _parsed.chars.length; i++) { - var char = _parsed.chars[i]; + for (int i = 0; i < _blocks.length; i++) { + var char = _blocks.formatCharacters[i]; var num = _extractNumFromString(characters, i, throwOnError); if (num != null) { if (char == yearCode) { @@ -195,7 +197,7 @@ class FixedDateTimeFormatter { int? _extractNumFromString( List characters, int index, bool throwOnError) { var parsed = - tryParse(characters, _parsed.starts[index], _parsed.ends[index]); + tryParse(characters, _blocks.starts[index], _blocks.ends[index]); if (parsed == null && throwOnError) { throw FormatException( '${String.fromCharCodes(characters)} should only contain digits'); @@ -218,18 +220,18 @@ class FixedDateTimeFormatter { } } -class _ParsedPattern { +class _ParsedFormatBlocks { + final formatCharacters = []; final starts = []; final ends = []; - final chars = []; - _ParsedPattern(); + _ParsedFormatBlocks(); - int get length => chars.length; + int get length => formatCharacters.length; void saveBlock(int? char, int start, int end) { if (char != null) { - chars.add(char); + formatCharacters.add(char); starts.add(start); ends.add(end); } From 9a16288488decd4560dafbb1fed0365f0a5423a8 Mon Sep 17 00:00:00 2001 From: moritz Date: Wed, 28 Sep 2022 10:04:07 +0000 Subject: [PATCH 053/100] Remove unused variable --- pkgs/convert/benchmark/fixed_datetime_formatter_benchmark.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/convert/benchmark/fixed_datetime_formatter_benchmark.dart b/pkgs/convert/benchmark/fixed_datetime_formatter_benchmark.dart index 86b931a6..7ac4a2b6 100644 --- a/pkgs/convert/benchmark/fixed_datetime_formatter_benchmark.dart +++ b/pkgs/convert/benchmark/fixed_datetime_formatter_benchmark.dart @@ -21,7 +21,7 @@ class NewMethod extends BenchmarkBase { @override void run() { for (var i = 0; i < 1000000; i++) { - var decode = fixedDateTimeFormatter.decode('19960425050322'); + fixedDateTimeFormatter.decode('19960425050322'); } } } From 1cca6f4083be103126bef8e400b088a7521acdb8 Mon Sep 17 00:00:00 2001 From: moritz Date: Wed, 28 Sep 2022 15:12:19 +0000 Subject: [PATCH 054/100] changes as per review --- .../fixed_datetime_formatter_benchmark.dart | 6 +- .../lib/src/fixed_datetime_formatter.dart | 203 ++++++++++++------ .../test/fixed_datetime_formatter_test.dart | 54 +++-- 3 files changed, 175 insertions(+), 88 deletions(-) diff --git a/pkgs/convert/benchmark/fixed_datetime_formatter_benchmark.dart b/pkgs/convert/benchmark/fixed_datetime_formatter_benchmark.dart index 7ac4a2b6..89b34a11 100644 --- a/pkgs/convert/benchmark/fixed_datetime_formatter_benchmark.dart +++ b/pkgs/convert/benchmark/fixed_datetime_formatter_benchmark.dart @@ -8,10 +8,10 @@ import 'package:convert/convert.dart'; /// This class tests the implementation speed of /// _DateFormatPatternField::nextInteger, which is assumed to be called often and /// thus being performance-critical. -class NewMethod extends BenchmarkBase { +class DecodeBenchmark extends BenchmarkBase { late String result; late FixedDateTimeFormatter fixedDateTimeFormatter; - NewMethod() : super('Parse a million strings to datetime'); + DecodeBenchmark() : super('Parse a million strings to datetime'); @override void setup() { @@ -27,5 +27,5 @@ class NewMethod extends BenchmarkBase { } void main() { - NewMethod().report(); + DecodeBenchmark().report(); } diff --git a/pkgs/convert/lib/src/fixed_datetime_formatter.dart b/pkgs/convert/lib/src/fixed_datetime_formatter.dart index d1bd7cb9..04b97002 100644 --- a/pkgs/convert/lib/src/fixed_datetime_formatter.dart +++ b/pkgs/convert/lib/src/fixed_datetime_formatter.dart @@ -9,15 +9,15 @@ /// the same result as calling `DateTime(1996, 4, 25, 5, 3, 22)`. /// /// The allowed characters are -/// * `Y` a digit used in the time scale component “calendar year” -/// * `M` a digit used in the time scale component “calendar month” -/// * `D` a digit used in the time scale component “calendar day” -/// * `E` a digit used in the time scale component “decade” -/// * `C` a digit used in the time scale component “century” -/// * `h` a digit used in the time scale component “clock hour” -/// * `m` a digit used in the time scale component “clock minute” -/// * `s` a digit used in the time scale component “clock second” -/// as specified in the ISO 8601 standard. +/// * `Y` for “calendar year” +/// * `M` for “calendar month” +/// * `D` for “calendar day” +/// * `E` for “decade” +/// * `C` for “century” +/// * `h` for “clock hour” +/// * `m` for “clock minute” +/// * `s` for “clock second” +/// * `S` for “fractional clock second” /// /// Non-allowed characters in the format [pattern] are ignored when decoding a /// string, in this case `YYYY kiwi MM` is the same format string as @@ -33,29 +33,46 @@ /// containing delimiters, as the parser would not know how many digits to take /// otherwise. class FixedDateTimeFormatter { - static final _validFormatCharacters = 'YMDEChms'.codeUnits; - static final yearCode = 'Y'.codeUnitAt(0); - static final monthCode = 'M'.codeUnitAt(0); - static final dayCode = 'D'.codeUnitAt(0); - static final decadeCode = 'E'.codeUnitAt(0); - static final centuryCode = 'C'.codeUnitAt(0); - static final hourCode = 'h'.codeUnitAt(0); - static final minuteCode = 'm'.codeUnitAt(0); - static final secondCode = 's'.codeUnitAt(0); + static const _powersOfTen = [0, 1, 10, 100, 1000, 10000, 100000]; + static const _validFormatCharacters = [ + _yearCode, + _monthCode, + _dayCode, + _decadeCode, + _centuryCode, + _hourCode, + _minuteCode, + _secondCode, + _fractionSecondCode, + ]; + static const _yearCode = 0x59; /*Y*/ + static const _monthCode = 0x4D; /*M*/ + static const _dayCode = 0x44; /*D*/ + static const _decadeCode = 0x45; /*E*/ + static const _centuryCode = 0x43; /*C*/ + static const _hourCode = 0x68; /*H*/ + static const _minuteCode = 0x6D; /*m*/ + static const _secondCode = 0x73; /*s*/ + static const _fractionSecondCode = 0x53; /*S*/ + ///Store publicly in case the user wants to retrieve it final String pattern; + + ///Whether to use UTC or the local time zone + final bool isUtc; final _blocks = _ParsedFormatBlocks(); /// Creates a new [FixedDateTimeFormatter] with the provided [pattern]. /// /// The [pattern] interprets the characters mentioned in /// [FixedDateTimeFormatter] to represent fields of a `DateTime` value. Other - /// characters are not special. + /// characters are not special. If [isUtc] is set to false, the DateTime is + /// constructed with respect to the local timezone. /// /// There must at most be one sequence of each special character to ensure a /// single source of truth when constructing the [DateTime], so a pattern of /// `"CCCC-MM-DD, CC"` is invalid, because it has two separate `C` sequences. - FixedDateTimeFormatter(this.pattern) { + FixedDateTimeFormatter(this.pattern, {this.isUtc = true}) { int? current; var start = 0; var characters = pattern.codeUnits; @@ -95,12 +112,18 @@ class FixedDateTimeFormatter { if (previousEnd < start) { buffer.write(pattern.substring(previousEnd, start)); } + var formatCharacter = _blocks.formatCharacters[i]; var number = _extractNumFromDateTime( - _blocks.formatCharacters[i], + formatCharacter, datetime, ).toString(); if (number.length > length) { - number = number.substring(number.length - length); + if (formatCharacter == _fractionSecondCode) { + //Special case, as we want fractional seconds to be the leading digits + number = number.substring(length); + } else { + number = number.substring(number.length - length); + } } else if (number.length < length) { number = number.padLeft(length, '0'); } @@ -115,23 +138,26 @@ class FixedDateTimeFormatter { return buffer.toString(); } - int _extractNumFromDateTime(int? formatChar, DateTime dt) { - if (formatChar == yearCode) { - return dt.year; - } else if (formatChar == centuryCode) { - return (dt.year / 100).floor(); - } else if (formatChar == decadeCode) { - return (dt.year / 10).floor(); - } else if (formatChar == monthCode) { - return dt.month; - } else if (formatChar == dayCode) { - return dt.day; - } else if (formatChar == hourCode) { - return dt.hour; - } else if (formatChar == minuteCode) { - return dt.minute; - } else if (formatChar == secondCode) { - return dt.second; + int _extractNumFromDateTime(int? formatChar, DateTime dateTime) { + switch (formatChar) { + case _yearCode: + return dateTime.year; + case _centuryCode: + return (dateTime.year / 100).floor(); + case _decadeCode: + return (dateTime.year / 10).floor(); + case _monthCode: + return dateTime.month; + case _dayCode: + return dateTime.day; + case _hourCode: + return dateTime.hour; + case _minuteCode: + return dateTime.minute; + case _secondCode: + return dateTime.second; + case _fractionSecondCode: + return dateTime.microsecond; } throw AssertionError("Unreachable, the key is checked in the constructor"); } @@ -139,13 +165,13 @@ class FixedDateTimeFormatter { /// Parse a string [formattedDateTime] to a local [DateTime] as specified in the /// [pattern], substituting missing values with a default. Throws an exception /// on failure to parse. - DateTime decode(String formattedDateTime, {bool isUtc = false}) { + DateTime decode(String formattedDateTime) { return _decode(formattedDateTime, isUtc, true); } /// Same as [decode], but will not throw on parsing erros, instead using /// the default value as if the format char was not present in the [pattern]. - DateTime tryDecode(String formattedDateTime, {bool isUtc = false}) { + DateTime tryDecode(String formattedDateTime) { return _decode(formattedDateTime, isUtc, false); } @@ -163,41 +189,83 @@ class FixedDateTimeFormatter { var hour = 0; var minute = 0; var second = 0; + var microsecond = 0; for (int i = 0; i < _blocks.length; i++) { var char = _blocks.formatCharacters[i]; - var num = _extractNumFromString(characters, i, throwOnError); - if (num != null) { - if (char == yearCode) { - year = num; - } else if (char == centuryCode) { - century = num; - } else if (char == decadeCode) { - decade = num; - } else if (char == monthCode) { - month = num; - } else if (char == dayCode) { - day = num; - } else if (char == hourCode) { - hour = num; - } else if (char == minuteCode) { - minute = num; - } else if (char == secondCode) { - second = num; + var number = _extractNumFromString(characters, i, throwOnError); + if (number != null) { + if (char == _fractionSecondCode) { + //Special case, as we want fractional seconds to be the leading digits + var numberLength = _blocks.ends[i] - _blocks.starts[i]; + number *= _powersOfTen[6 - numberLength + 1]; + } + switch (char) { + case _yearCode: + year = number; + break; + case _centuryCode: + century = number; + break; + case _decadeCode: + decade = number; + break; + case _monthCode: + month = number; + break; + case _dayCode: + day = number; + break; + case _hourCode: + hour = number; + break; + case _minuteCode: + minute = number; + break; + case _secondCode: + second = number; + break; + case _fractionSecondCode: + microsecond = number; + break; } } } var totalYear = year + 100 * century + 10 * decade; if (isUtc) { - return DateTime.utc(totalYear, month, day, hour, minute, second, 0, 0); + return DateTime.utc( + totalYear, + month, + day, + hour, + minute, + second, + 0, + microsecond, + ); } else { - return DateTime(totalYear, month, day, hour, minute, second, 0, 0); + return DateTime( + totalYear, + month, + day, + hour, + minute, + second, + 0, + microsecond, + ); } } int? _extractNumFromString( - List characters, int index, bool throwOnError) { - var parsed = - tryParse(characters, _blocks.starts[index], _blocks.ends[index]); + List characters, + int index, + bool throwOnError, + ) { + var parsed = tryParse( + characters, + _blocks.starts[index], + _blocks.ends[index], + ); if (parsed == null && throwOnError) { throw FormatException( '${String.fromCharCodes(characters)} should only contain digits'); @@ -205,13 +273,12 @@ class FixedDateTimeFormatter { return parsed; } - static final zeroCode = '0'.codeUnitAt(0); int? tryParse(List characters, int start, int end) { int result = 0; for (var i = start; i < end; i++) { - var character = characters[i]; - if (character >= zeroCode && character < zeroCode + 10) { - result = result * 10 + (character - zeroCode); + var digit = characters[i] ^ 0x30; + if (digit <= 9) { + result = result * 10 + digit; } else { return null; } diff --git a/pkgs/convert/test/fixed_datetime_formatter_test.dart b/pkgs/convert/test/fixed_datetime_formatter_test.dart index 2dd883aa..7c7f0a51 100644 --- a/pkgs/convert/test/fixed_datetime_formatter_test.dart +++ b/pkgs/convert/test/fixed_datetime_formatter_test.dart @@ -9,40 +9,60 @@ void main() { //decode test('Parse only year', () { var time = FixedDateTimeFormatter('YYYY').decode('1996'); - expect(time, DateTime(1996)); + expect(time, DateTime.utc(1996)); }); test('Escaped chars are ignored', () { var time = FixedDateTimeFormatter('YYYY kiwi MM').decode('1996 rnad 01'); - expect(time, DateTime(1996, 1)); + expect(time, DateTime.utc(1996, 1)); }); test('Parse two years throws', () { expect(() => FixedDateTimeFormatter('YYYY YYYY'), throwsException); }); test('Parse year and century', () { var time = FixedDateTimeFormatter('CCYY').decode('1996'); - expect(time, DateTime(1996)); + expect(time, DateTime.utc(1996)); }); test('Parse year, decade and century', () { var time = FixedDateTimeFormatter('CCEY').decode('1996'); - expect(time, DateTime(1996)); + expect(time, DateTime.utc(1996)); }); test('Parse year, century, month', () { var time = FixedDateTimeFormatter('CCYY MM').decode('1996 04'); - expect(time, DateTime(1996, 4)); + expect(time, DateTime.utc(1996, 4)); }); test('Parse year, century, month, day', () { var time = FixedDateTimeFormatter('CCYY MM-DD').decode('1996 04-25'); - expect(time, DateTime(1996, 4, 25)); + expect(time, DateTime.utc(1996, 4, 25)); }); test('Parse year, century, month, day, hour, minute, second', () { var time = FixedDateTimeFormatter('CCYY MM-DD hh:mm:ss') .decode('1996 04-25 05:03:22'); - expect(time, DateTime(1996, 4, 25, 5, 3, 22)); + expect(time, DateTime.utc(1996, 4, 25, 5, 3, 22)); }); - test('Parse YYYYMMDDhhmmss', () { + test('Parse YYYYMMDDhhmmssSSS', () { var time = - FixedDateTimeFormatter('YYYYMMDDhhmmss').decode('19960425050322'); - expect(time, DateTime(1996, 4, 25, 5, 3, 22)); + FixedDateTimeFormatter('YYYYMMDDhhmmssSSS').decode('19960425050322533'); + expect(time, DateTime.utc(1996, 4, 25, 5, 3, 22, 533)); + }); + test('Parse S', () { + var time = FixedDateTimeFormatter('S').decode('1'); + expect(time, DateTime.utc(0, 1, 1, 0, 0, 0, 100, 0)); + }); + test('Parse SS', () { + var time = FixedDateTimeFormatter('SS').decode('01'); + expect(time, DateTime.utc(0, 1, 1, 0, 0, 0, 10, 0)); + }); + test('Parse SSS', () { + var time = FixedDateTimeFormatter('SSS').decode('001'); + expect(time, DateTime.utc(0, 1, 1, 0, 0, 0, 1, 0)); + }); + test('Parse SSSSSS', () { + var time = FixedDateTimeFormatter('SSSSSS').decode('000001'); + expect(time, DateTime.utc(0, 1, 1, 0, 0, 0, 0, 1)); + }); + test('Parse SSSSSS 2', () { + var time = FixedDateTimeFormatter('SSSSSS').decode('001000'); + expect(time, DateTime.utc(0, 1, 1, 0, 0, 0, 1, 0)); }); test('Parse hex year throws', () { expect( @@ -53,32 +73,32 @@ void main() { //tryDecode test('Try parse year', () { var time = FixedDateTimeFormatter('YYYY').tryDecode('1996'); - expect(time, DateTime(1996)); + expect(time, DateTime.utc(1996)); }); test('Try parse hex year return default', () { var time = FixedDateTimeFormatter('YYYY').tryDecode('0xAB'); - expect(time, DateTime(0)); + expect(time, DateTime.utc(0)); }); test('Try parse invalid returns default', () { var time = FixedDateTimeFormatter('YYYY').tryDecode('1x96'); - expect(time, DateTime(0)); + expect(time, DateTime.utc(0)); }); //encode test('Format simple', () { - var time = DateTime(1996, 1); + var time = DateTime.utc(1996, 1); expect('1996 kiwi 01', FixedDateTimeFormatter('YYYY kiwi MM').encode(time)); }); test('Format YYYYMMDDhhmmss', () { var str = FixedDateTimeFormatter('YYYYMMDDhhmmss') - .encode(DateTime(1996, 4, 25, 5, 3, 22)); + .encode(DateTime.utc(1996, 4, 25, 5, 3, 22)); expect('19960425050322', str); }); test('Format CCEY-MM', () { - var str = FixedDateTimeFormatter('CCEY-MM').encode(DateTime(1996, 4)); + var str = FixedDateTimeFormatter('CCEY-MM').encode(DateTime.utc(1996, 4)); expect('1996-04', str); }); test('Format XCCEY-MMX', () { - var str = FixedDateTimeFormatter('XCCEY-MMX').encode(DateTime(1996, 4)); + var str = FixedDateTimeFormatter('XCCEY-MMX').encode(DateTime.utc(1996, 4)); expect('X1996-04X', str); }); } From 79156fc1c10d72064ff5e532f0a7043542cb1535 Mon Sep 17 00:00:00 2001 From: moritz Date: Wed, 5 Oct 2022 09:06:14 +0000 Subject: [PATCH 055/100] changes as per review --- .../lib/src/fixed_datetime_formatter.dart | 126 ++++++++++------ .../test/fixed_datetime_formatter_test.dart | 141 +++++++++++++++--- 2 files changed, 195 insertions(+), 72 deletions(-) diff --git a/pkgs/convert/lib/src/fixed_datetime_formatter.dart b/pkgs/convert/lib/src/fixed_datetime_formatter.dart index 04b97002..78399e2a 100644 --- a/pkgs/convert/lib/src/fixed_datetime_formatter.dart +++ b/pkgs/convert/lib/src/fixed_datetime_formatter.dart @@ -19,21 +19,16 @@ /// * `s` for “clock second” /// * `S` for “fractional clock second” /// -/// Non-allowed characters in the format [pattern] are ignored when decoding a +/// Non-allowed characters in the format [pattern] are included when decoding a /// string, in this case `YYYY kiwi MM` is the same format string as /// `YYYY------MM`. When encoding a datetime, the non-format characters are in /// the output verbatim. /// /// Note: this class differs from [DateFormat] in that here, the characters are -/// treated literally, i.e. the format string `YYY` matching `996` would result in -/// the same as calling `DateTime(996)`. [DateFormat] on the other hand uses the -/// specification in https://www.unicode.org/reports/tr35/tr35-dates.html#Date_Field_Symbol_Table, -/// the format string (or "skeleton") `YYY` specifies only the padding, so -/// `1996` would be a valid match. This limits it's use to format strings -/// containing delimiters, as the parser would not know how many digits to take -/// otherwise. +/// treated literally, i.e., the format string `YYY` matching `996` would result +/// in the same as calling `DateTime(996)`. class FixedDateTimeFormatter { - static const _powersOfTen = [0, 1, 10, 100, 1000, 10000, 100000]; + static const _powersOfTen = [1, 10, 100, 1000, 10000, 100000]; static const _validFormatCharacters = [ _yearCode, _monthCode, @@ -55,11 +50,15 @@ class FixedDateTimeFormatter { static const _secondCode = 0x73; /*s*/ static const _fractionSecondCode = 0x53; /*S*/ - ///Store publicly in case the user wants to retrieve it + /// The format pattern string of this formatter, stored publicly in case the + /// user wants to retrieve it. final String pattern; - ///Whether to use UTC or the local time zone + /// Whether to create UTC [DateTime] objects when parsing. + /// + /// If not, the created [DateTime] objects are in the local time zone. final bool isUtc; + final _blocks = _ParsedFormatBlocks(); /// Creates a new [FixedDateTimeFormatter] with the provided [pattern]. @@ -73,35 +72,40 @@ class FixedDateTimeFormatter { /// single source of truth when constructing the [DateTime], so a pattern of /// `"CCCC-MM-DD, CC"` is invalid, because it has two separate `C` sequences. FixedDateTimeFormatter(this.pattern, {this.isUtc = true}) { - int? current; + int? currentCharacter; var start = 0; var characters = pattern.codeUnits; for (var i = 0; i < characters.length; i++) { - var char = characters[i]; - if (current != char) { - _blocks.saveBlock(current, start, i); - if (_validFormatCharacters.contains(char)) { - var hasSeenBefore = _blocks.formatCharacters.indexOf(char); + var formatCharacter = characters[i]; + if (currentCharacter != formatCharacter) { + _blocks.saveBlock(currentCharacter, start, i); + if (_validFormatCharacters.contains(formatCharacter)) { + var hasSeenBefore = _blocks.formatCharacters.indexOf(formatCharacter); if (hasSeenBefore > -1) { throw FormatException( - "Pattern contains more than one '$char' block.\n" + "Pattern contains more than one '$formatCharacter' block.\n" "Previous occurrence at index ${_blocks.starts[hasSeenBefore]}", pattern, i); } else { start = i; - current = char; + currentCharacter = formatCharacter; } } else { - current = null; + currentCharacter = null; } } } - _blocks.saveBlock(current, start, pattern.length); + _blocks.saveBlock(currentCharacter, start, pattern.length); } - /// Convert [DateTime] to a [String] exactly as specified by the [pattern]. + /// Converts a [DateTime] to a [String] as specified by the [pattern]. + /// + /// Throws a [FormatException] if trying to encode a negative year. String encode(DateTime datetime) { + if (datetime.year < 0) { + throw FormatException("Cannot handle negative years."); + } var buffer = StringBuffer(); for (var i = 0; i < _blocks.length; i++) { var start = _blocks.starts[i]; @@ -113,18 +117,22 @@ class FixedDateTimeFormatter { buffer.write(pattern.substring(previousEnd, start)); } var formatCharacter = _blocks.formatCharacters[i]; - var number = _extractNumFromDateTime( - formatCharacter, - datetime, - ).toString(); - if (number.length > length) { - if (formatCharacter == _fractionSecondCode) { - //Special case, as we want fractional seconds to be the leading digits - number = number.substring(length); + var number = + _extractNumFromDateTime(formatCharacter, datetime).toString(); + if (formatCharacter == _fractionSecondCode) { + // Special case, as we want fractional seconds to be the leading + // digits. + if (6 > number.length) { + number = number.padLeft(6, '0'); + } + if (number.length > length) { + number = number.substring(0, length); } else { - number = number.substring(number.length - length); + number = number.padRight(length, '0'); } - } else if (number.length < length) { + } else if (number.length > length) { + number = number.substring(number.length - length); + } else if (length > number.length) { number = number.padLeft(length, '0'); } buffer.write(number); @@ -143,9 +151,9 @@ class FixedDateTimeFormatter { case _yearCode: return dateTime.year; case _centuryCode: - return (dateTime.year / 100).floor(); + return dateTime.year ~/ 100; case _decadeCode: - return (dateTime.year / 10).floor(); + return dateTime.year ~/ 10; case _monthCode: return dateTime.month; case _dayCode: @@ -157,25 +165,34 @@ class FixedDateTimeFormatter { case _secondCode: return dateTime.second; case _fractionSecondCode: - return dateTime.microsecond; + return dateTime.microsecond + dateTime.millisecond * 1000; } throw AssertionError("Unreachable, the key is checked in the constructor"); } - /// Parse a string [formattedDateTime] to a local [DateTime] as specified in the - /// [pattern], substituting missing values with a default. Throws an exception - /// on failure to parse. + /// Parses [formattedDateTime] to a [DateTime] as specified by the [pattern]. + /// + /// Parts of a [DateTime] which are not mentioned in the pattern default to a + /// value of zero for time parts and year, and a value of 1 for day and month. + /// + /// Throws a [FormatException] if the [formattedDateTime] does not match the + /// [pattern]. DateTime decode(String formattedDateTime) { - return _decode(formattedDateTime, isUtc, true); + return _decode(formattedDateTime, isUtc, true)!; } - /// Same as [decode], but will not throw on parsing erros, instead using - /// the default value as if the format char was not present in the [pattern]. - DateTime tryDecode(String formattedDateTime) { + /// Parses [formattedDateTime] to a [DateTime] as specified by the [pattern]. + /// + /// Parts of a [DateTime] which are not mentioned in the pattern default to a + /// value of zero for time parts and year, and a value of 1 for day and month. + /// + /// Returns the parsed value, or `null` if the [formattedDateTime] does not + /// match the [pattern]. + DateTime? tryDecode(String formattedDateTime) { return _decode(formattedDateTime, isUtc, false); } - DateTime _decode( + DateTime? _decode( String formattedDateTime, bool isUtc, bool throwOnError, @@ -190,16 +207,25 @@ class FixedDateTimeFormatter { var minute = 0; var second = 0; var microsecond = 0; - for (int i = 0; i < _blocks.length; i++) { - var char = _blocks.formatCharacters[i]; + for (var i = 0; i < _blocks.length; i++) { + var formatCharacter = _blocks.formatCharacters[i]; var number = _extractNumFromString(characters, i, throwOnError); if (number != null) { - if (char == _fractionSecondCode) { - //Special case, as we want fractional seconds to be the leading digits + if (formatCharacter == _fractionSecondCode) { + // Special case, as we want fractional seconds to be the leading + // digits. var numberLength = _blocks.ends[i] - _blocks.starts[i]; - number *= _powersOfTen[6 - numberLength + 1]; + if (numberLength > 6) { + if (throwOnError) { + throw FormatException( + 'Fractional seconds can only be specified up to microseconds'); + } else { + return null; + } + } + number *= _powersOfTen[6 - numberLength]; } - switch (char) { + switch (formatCharacter) { case _yearCode: year = number; break; @@ -228,6 +254,8 @@ class FixedDateTimeFormatter { microsecond = number; break; } + } else { + return null; } } var totalYear = year + 100 * century + 10 * decade; diff --git a/pkgs/convert/test/fixed_datetime_formatter_test.dart b/pkgs/convert/test/fixed_datetime_formatter_test.dart index 7c7f0a51..98d99d76 100644 --- a/pkgs/convert/test/fixed_datetime_formatter_test.dart +++ b/pkgs/convert/test/fixed_datetime_formatter_test.dart @@ -6,7 +6,8 @@ import 'package:convert/src/fixed_datetime_formatter.dart'; import 'package:test/test.dart'; void main() { - //decode + DateTime noFractionalSeconds = DateTime.utc(0, 1, 1, 0, 0, 0); + // Testing `decode`. test('Parse only year', () { var time = FixedDateTimeFormatter('YYYY').decode('1996'); expect(time, DateTime.utc(1996)); @@ -44,25 +45,49 @@ void main() { FixedDateTimeFormatter('YYYYMMDDhhmmssSSS').decode('19960425050322533'); expect(time, DateTime.utc(1996, 4, 25, 5, 3, 22, 533)); }); - test('Parse S', () { + test('Parse S 1/10 of a second', () { var time = FixedDateTimeFormatter('S').decode('1'); - expect(time, DateTime.utc(0, 1, 1, 0, 0, 0, 100, 0)); + expect(time, noFractionalSeconds.add(Duration(milliseconds: 100))); }); - test('Parse SS', () { + test('Parse SS 1/100 of a second', () { var time = FixedDateTimeFormatter('SS').decode('01'); - expect(time, DateTime.utc(0, 1, 1, 0, 0, 0, 10, 0)); + expect(time, noFractionalSeconds.add(Duration(milliseconds: 10))); }); - test('Parse SSS', () { + test('Parse SSS a millisecond', () { var time = FixedDateTimeFormatter('SSS').decode('001'); - expect(time, DateTime.utc(0, 1, 1, 0, 0, 0, 1, 0)); + expect(time, noFractionalSeconds.add(Duration(milliseconds: 1))); }); - test('Parse SSSSSS', () { + test('Parse SSSSSS a microsecond', () { var time = FixedDateTimeFormatter('SSSSSS').decode('000001'); - expect(time, DateTime.utc(0, 1, 1, 0, 0, 0, 0, 1)); + expect(time, noFractionalSeconds.add(Duration(microseconds: 1))); }); - test('Parse SSSSSS 2', () { + test('Parse SSSSSS a millisecond', () { var time = FixedDateTimeFormatter('SSSSSS').decode('001000'); - expect(time, DateTime.utc(0, 1, 1, 0, 0, 0, 1, 0)); + expect(time, noFractionalSeconds.add(Duration(milliseconds: 1))); + }); + test('Parse SSSSSS a millisecond and a microsecond', () { + var time = FixedDateTimeFormatter('SSSSSS').decode('001001'); + expect( + time, + noFractionalSeconds.add(Duration( + milliseconds: 1, + microseconds: 1, + ))); + }); + test('Parse ssSSSSSS a second and a microsecond', () { + var time = FixedDateTimeFormatter('ssSSSSSS').decode('01000001'); + expect( + time, + noFractionalSeconds.add(Duration( + seconds: 1, + microseconds: 1, + ))); + }); + test('Parse 7 S throws', () { + expect( + () => FixedDateTimeFormatter('SSSSSSS').decode('0000010'), + throwsFormatException, + ); }); test('Parse hex year throws', () { expect( @@ -70,35 +95,105 @@ void main() { throwsFormatException, ); }); - //tryDecode + // Testing `tryDecode`. test('Try parse year', () { var time = FixedDateTimeFormatter('YYYY').tryDecode('1996'); expect(time, DateTime.utc(1996)); }); - test('Try parse hex year return default', () { + test('Try parse hex year returns null', () { var time = FixedDateTimeFormatter('YYYY').tryDecode('0xAB'); - expect(time, DateTime.utc(0)); + expect(time, null); }); - test('Try parse invalid returns default', () { + test('Try parse invalid returns null', () { var time = FixedDateTimeFormatter('YYYY').tryDecode('1x96'); - expect(time, DateTime.utc(0)); + expect(time, null); }); - //encode + // Testing `encode`. test('Format simple', () { var time = DateTime.utc(1996, 1); - expect('1996 kiwi 01', FixedDateTimeFormatter('YYYY kiwi MM').encode(time)); + expect(FixedDateTimeFormatter('YYYY kiwi MM').encode(time), '1996 kiwi 01'); }); test('Format YYYYMMDDhhmmss', () { - var str = FixedDateTimeFormatter('YYYYMMDDhhmmss') - .encode(DateTime.utc(1996, 4, 25, 5, 3, 22)); - expect('19960425050322', str); + var time = DateTime.utc(1996, 4, 25, 5, 3, 22); + expect( + FixedDateTimeFormatter('YYYYMMDDhhmmss').encode(time), + '19960425050322', + ); }); test('Format CCEY-MM', () { var str = FixedDateTimeFormatter('CCEY-MM').encode(DateTime.utc(1996, 4)); - expect('1996-04', str); + expect(str, '1996-04'); }); test('Format XCCEY-MMX', () { var str = FixedDateTimeFormatter('XCCEY-MMX').encode(DateTime.utc(1996, 4)); - expect('X1996-04X', str); + expect(str, 'X1996-04X'); + }); + test('Format SSSS no fractions', () { + var str = FixedDateTimeFormatter('SSSS').encode(noFractionalSeconds); + expect(str, '0000'); + }); + test('Format SSSSSS no fractions', () { + var str = FixedDateTimeFormatter('SSSSSS').encode(noFractionalSeconds); + expect(str, '000000'); + }); + test('Format SSSS 1/10 of a second', () { + var str = FixedDateTimeFormatter('SSSS') + .encode(noFractionalSeconds.add(Duration(milliseconds: 100))); + expect(str, '1000'); + }); + test('Format SSSS 1/100 of a second', () { + var str = FixedDateTimeFormatter('SSSS') + .encode(noFractionalSeconds.add(Duration(milliseconds: 10))); + expect(str, '0100'); + }); + test('Format SSSS a millisecond', () { + var str = FixedDateTimeFormatter('SSSS') + .encode(noFractionalSeconds.add(Duration(milliseconds: 1))); + expect(str, '0010'); + }); + test('Format SSSSSS a microsecond', () { + var str = FixedDateTimeFormatter('SSSSSS') + .encode(noFractionalSeconds.add(Duration(microseconds: 1))); + expect(str, '000001'); + }); + test('Format SSSSSS a millisecond and a microsecond', () { + var dateTime = noFractionalSeconds.add(Duration( + milliseconds: 1, + microseconds: 1, + )); + var str = FixedDateTimeFormatter('SSSSSS').encode(dateTime); + expect(str, '001001'); + }); + test('Format SSSSSSS a microsecond', () { + var str = FixedDateTimeFormatter('SSSSSSS') + .encode(noFractionalSeconds.add(Duration(microseconds: 1))); + expect(str, '0000010'); + }); + test('Format SSSSSSS 1/10 of a second', () { + var str = FixedDateTimeFormatter('SSSSSSS') + .encode(noFractionalSeconds.add(Duration(milliseconds: 100))); + expect(str, '1000000'); + }); + test('Parse ssSSSSSS a second and a microsecond', () { + var dateTime = noFractionalSeconds.add(Duration( + seconds: 1, + microseconds: 1, + )); + var str = FixedDateTimeFormatter('ssSSSSSS').encode(dateTime); + expect(str, '01000001'); + }); + test('Parse ssSSSSSSS a second and a microsecond', () { + var dateTime = noFractionalSeconds.add(Duration( + seconds: 1, + microseconds: 1, + )); + var str = FixedDateTimeFormatter('ssSSSSSSS').encode(dateTime); + expect(str, '010000010'); + }); + test('Parse negative year throws', () { + expect( + () => FixedDateTimeFormatter('YYYY').encode(DateTime(-1)), + throwsFormatException, + ); }); } From 85efafc44954fa201a7aac1983ba5d01d28b9656 Mon Sep 17 00:00:00 2001 From: moritz Date: Wed, 5 Oct 2022 09:14:06 +0000 Subject: [PATCH 056/100] Duration to DateTime --- pkgs/convert/test/fixed_datetime_formatter_test.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/convert/test/fixed_datetime_formatter_test.dart b/pkgs/convert/test/fixed_datetime_formatter_test.dart index 98d99d76..367ca0af 100644 --- a/pkgs/convert/test/fixed_datetime_formatter_test.dart +++ b/pkgs/convert/test/fixed_datetime_formatter_test.dart @@ -153,7 +153,7 @@ void main() { }); test('Format SSSSSS a microsecond', () { var str = FixedDateTimeFormatter('SSSSSS') - .encode(noFractionalSeconds.add(Duration(microseconds: 1))); + .encode(DateTime.utc(0, 1, 1, 0, 0, 0, 0, 1)); expect(str, '000001'); }); test('Format SSSSSS a millisecond and a microsecond', () { From 477c062793f492ac3d239f167bf56cac92b6e3a4 Mon Sep 17 00:00:00 2001 From: moritz Date: Wed, 5 Oct 2022 09:18:40 +0000 Subject: [PATCH 057/100] Add test to check for microseconds --- pkgs/convert/test/fixed_datetime_formatter_test.dart | 3 +++ 1 file changed, 3 insertions(+) diff --git a/pkgs/convert/test/fixed_datetime_formatter_test.dart b/pkgs/convert/test/fixed_datetime_formatter_test.dart index 367ca0af..c7455593 100644 --- a/pkgs/convert/test/fixed_datetime_formatter_test.dart +++ b/pkgs/convert/test/fixed_datetime_formatter_test.dart @@ -156,6 +156,9 @@ void main() { .encode(DateTime.utc(0, 1, 1, 0, 0, 0, 0, 1)); expect(str, '000001'); }); + test('Browsers know microseconds', () { + expect(DateTime.utc(0, 1, 1, 0, 0, 0, 0, 1).microsecond, 1); + }); test('Format SSSSSS a millisecond and a microsecond', () { var dateTime = noFractionalSeconds.add(Duration( milliseconds: 1, From 153a0e55a3f57c8ea14bdf37cf0dba3226cf5321 Mon Sep 17 00:00:00 2001 From: moritz Date: Wed, 5 Oct 2022 09:35:19 +0000 Subject: [PATCH 058/100] skip microsecond tests on web --- .../test/fixed_datetime_formatter_test.dart | 23 ++++++++++--------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/pkgs/convert/test/fixed_datetime_formatter_test.dart b/pkgs/convert/test/fixed_datetime_formatter_test.dart index c7455593..98505846 100644 --- a/pkgs/convert/test/fixed_datetime_formatter_test.dart +++ b/pkgs/convert/test/fixed_datetime_formatter_test.dart @@ -7,6 +7,10 @@ import 'package:test/test.dart'; void main() { DateTime noFractionalSeconds = DateTime.utc(0, 1, 1, 0, 0, 0); + Map skipWeb = { + 'js': Skip( + 'Web does not support microseconds (see https://github.com/dart-lang/sdk/issues/44876)') + }; // Testing `decode`. test('Parse only year', () { var time = FixedDateTimeFormatter('YYYY').decode('1996'); @@ -60,7 +64,7 @@ void main() { test('Parse SSSSSS a microsecond', () { var time = FixedDateTimeFormatter('SSSSSS').decode('000001'); expect(time, noFractionalSeconds.add(Duration(microseconds: 1))); - }); + }, onPlatform: skipWeb); test('Parse SSSSSS a millisecond', () { var time = FixedDateTimeFormatter('SSSSSS').decode('001000'); expect(time, noFractionalSeconds.add(Duration(milliseconds: 1))); @@ -73,7 +77,7 @@ void main() { milliseconds: 1, microseconds: 1, ))); - }); + }, onPlatform: skipWeb); test('Parse ssSSSSSS a second and a microsecond', () { var time = FixedDateTimeFormatter('ssSSSSSS').decode('01000001'); expect( @@ -82,7 +86,7 @@ void main() { seconds: 1, microseconds: 1, ))); - }); + }, onPlatform: skipWeb); test('Parse 7 S throws', () { expect( () => FixedDateTimeFormatter('SSSSSSS').decode('0000010'), @@ -155,10 +159,7 @@ void main() { var str = FixedDateTimeFormatter('SSSSSS') .encode(DateTime.utc(0, 1, 1, 0, 0, 0, 0, 1)); expect(str, '000001'); - }); - test('Browsers know microseconds', () { - expect(DateTime.utc(0, 1, 1, 0, 0, 0, 0, 1).microsecond, 1); - }); + }, onPlatform: skipWeb); test('Format SSSSSS a millisecond and a microsecond', () { var dateTime = noFractionalSeconds.add(Duration( milliseconds: 1, @@ -166,12 +167,12 @@ void main() { )); var str = FixedDateTimeFormatter('SSSSSS').encode(dateTime); expect(str, '001001'); - }); + }, onPlatform: skipWeb); test('Format SSSSSSS a microsecond', () { var str = FixedDateTimeFormatter('SSSSSSS') .encode(noFractionalSeconds.add(Duration(microseconds: 1))); expect(str, '0000010'); - }); + }, onPlatform: skipWeb); test('Format SSSSSSS 1/10 of a second', () { var str = FixedDateTimeFormatter('SSSSSSS') .encode(noFractionalSeconds.add(Duration(milliseconds: 100))); @@ -184,7 +185,7 @@ void main() { )); var str = FixedDateTimeFormatter('ssSSSSSS').encode(dateTime); expect(str, '01000001'); - }); + }, onPlatform: skipWeb); test('Parse ssSSSSSSS a second and a microsecond', () { var dateTime = noFractionalSeconds.add(Duration( seconds: 1, @@ -192,7 +193,7 @@ void main() { )); var str = FixedDateTimeFormatter('ssSSSSSSS').encode(dateTime); expect(str, '010000010'); - }); + }, onPlatform: skipWeb); test('Parse negative year throws', () { expect( () => FixedDateTimeFormatter('YYYY').encode(DateTime(-1)), From b1cfee011dbd94af4d1e793b4da2ce674ff4d6f5 Mon Sep 17 00:00:00 2001 From: moritz Date: Wed, 5 Oct 2022 09:41:49 +0000 Subject: [PATCH 059/100] add documentation --- pkgs/convert/lib/src/fixed_datetime_formatter.dart | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pkgs/convert/lib/src/fixed_datetime_formatter.dart b/pkgs/convert/lib/src/fixed_datetime_formatter.dart index 78399e2a..985c37b6 100644 --- a/pkgs/convert/lib/src/fixed_datetime_formatter.dart +++ b/pkgs/convert/lib/src/fixed_datetime_formatter.dart @@ -19,6 +19,8 @@ /// * `s` for “clock second” /// * `S` for “fractional clock second” /// +/// Note: Negative years are not supported. +/// /// Non-allowed characters in the format [pattern] are included when decoding a /// string, in this case `YYYY kiwi MM` is the same format string as /// `YYYY------MM`. When encoding a datetime, the non-format characters are in From 4549c3228f06306edbe5b183092dad2b26231b8b Mon Sep 17 00:00:00 2001 From: moritz Date: Wed, 5 Oct 2022 12:06:53 +0000 Subject: [PATCH 060/100] Apply simple changes as per review --- .../fixed_datetime_formatter_benchmark.dart | 16 ++--- .../lib/src/fixed_datetime_formatter.dart | 59 ++++++++++--------- 2 files changed, 35 insertions(+), 40 deletions(-) diff --git a/pkgs/convert/benchmark/fixed_datetime_formatter_benchmark.dart b/pkgs/convert/benchmark/fixed_datetime_formatter_benchmark.dart index 89b34a11..eb2f9238 100644 --- a/pkgs/convert/benchmark/fixed_datetime_formatter_benchmark.dart +++ b/pkgs/convert/benchmark/fixed_datetime_formatter_benchmark.dart @@ -5,22 +5,14 @@ import 'package:benchmark_harness/benchmark_harness.dart'; import 'package:convert/convert.dart'; -/// This class tests the implementation speed of -/// _DateFormatPatternField::nextInteger, which is assumed to be called often and -/// thus being performance-critical. +/// test the performance of [FixedDateTimeFormatter.decode] class DecodeBenchmark extends BenchmarkBase { - late String result; - late FixedDateTimeFormatter fixedDateTimeFormatter; - DecodeBenchmark() : super('Parse a million strings to datetime'); - - @override - void setup() { - fixedDateTimeFormatter = FixedDateTimeFormatter("YYYYMMDDhhmmss"); - } + final fixedDateTimeFormatter = FixedDateTimeFormatter("YYYYMMDDhhmmss"); + DecodeBenchmark() : super('Parse a million strings to DateTime'); @override void run() { - for (var i = 0; i < 1000000; i++) { + for (var i = 0; i < 100000; i++) { fixedDateTimeFormatter.decode('19960425050322'); } } diff --git a/pkgs/convert/lib/src/fixed_datetime_formatter.dart b/pkgs/convert/lib/src/fixed_datetime_formatter.dart index 985c37b6..f0c48fdc 100644 --- a/pkgs/convert/lib/src/fixed_datetime_formatter.dart +++ b/pkgs/convert/lib/src/fixed_datetime_formatter.dart @@ -23,7 +23,7 @@ /// /// Non-allowed characters in the format [pattern] are included when decoding a /// string, in this case `YYYY kiwi MM` is the same format string as -/// `YYYY------MM`. When encoding a datetime, the non-format characters are in +/// `YYYY------MM`. When encoding a [DateTime], the non-format characters are in /// the output verbatim. /// /// Note: this class differs from [DateFormat] in that here, the characters are @@ -52,8 +52,7 @@ class FixedDateTimeFormatter { static const _secondCode = 0x73; /*s*/ static const _fractionSecondCode = 0x53; /*S*/ - /// The format pattern string of this formatter, stored publicly in case the - /// user wants to retrieve it. + /// The format pattern string of this formatter final String pattern; /// Whether to create UTC [DateTime] objects when parsing. @@ -76,9 +75,8 @@ class FixedDateTimeFormatter { FixedDateTimeFormatter(this.pattern, {this.isUtc = true}) { int? currentCharacter; var start = 0; - var characters = pattern.codeUnits; - for (var i = 0; i < characters.length; i++) { - var formatCharacter = characters[i]; + for (var i = 0; i < pattern.length; i++) { + var formatCharacter = pattern.codeUnitAt(i); if (currentCharacter != formatCharacter) { _blocks.saveBlock(currentCharacter, start, i); if (_validFormatCharacters.contains(formatCharacter)) { @@ -104,8 +102,8 @@ class FixedDateTimeFormatter { /// Converts a [DateTime] to a [String] as specified by the [pattern]. /// /// Throws a [FormatException] if trying to encode a negative year. - String encode(DateTime datetime) { - if (datetime.year < 0) { + String encode(DateTime dateTime) { + if (dateTime.year < 0) { throw FormatException("Cannot handle negative years."); } var buffer = StringBuffer(); @@ -120,7 +118,7 @@ class FixedDateTimeFormatter { } var formatCharacter = _blocks.formatCharacters[i]; var number = - _extractNumFromDateTime(formatCharacter, datetime).toString(); + _extractNumberFromDateTime(formatCharacter, dateTime).toString(); if (formatCharacter == _fractionSecondCode) { // Special case, as we want fractional seconds to be the leading // digits. @@ -148,7 +146,7 @@ class FixedDateTimeFormatter { return buffer.toString(); } - int _extractNumFromDateTime(int? formatChar, DateTime dateTime) { + int _extractNumberFromDateTime(int? formatChar, DateTime dateTime) { switch (formatChar) { case _yearCode: return dateTime.year; @@ -199,10 +197,7 @@ class FixedDateTimeFormatter { bool isUtc, bool throwOnError, ) { - var characters = formattedDateTime.codeUnits; var year = 0; - var century = 0; - var decade = 0; var month = 1; var day = 1; var hour = 0; @@ -211,7 +206,7 @@ class FixedDateTimeFormatter { var microsecond = 0; for (var i = 0; i < _blocks.length; i++) { var formatCharacter = _blocks.formatCharacters[i]; - var number = _extractNumFromString(characters, i, throwOnError); + var number = _extractNumberFromString(formattedDateTime, i, throwOnError); if (number != null) { if (formatCharacter == _fractionSecondCode) { // Special case, as we want fractional seconds to be the leading @@ -220,7 +215,10 @@ class FixedDateTimeFormatter { if (numberLength > 6) { if (throwOnError) { throw FormatException( - 'Fractional seconds can only be specified up to microseconds'); + 'Fractional seconds can only be specified up to microseconds', + pattern, + _blocks.starts[i], + ); } else { return null; } @@ -229,13 +227,13 @@ class FixedDateTimeFormatter { } switch (formatCharacter) { case _yearCode: - year = number; + year += number; break; case _centuryCode: - century = number; + year += number * 100; break; case _decadeCode: - decade = number; + year += number * 10; break; case _monthCode: month = number; @@ -260,10 +258,9 @@ class FixedDateTimeFormatter { return null; } } - var totalYear = year + 100 * century + 10 * decade; if (isUtc) { return DateTime.utc( - totalYear, + year, month, day, hour, @@ -274,7 +271,7 @@ class FixedDateTimeFormatter { ); } else { return DateTime( - totalYear, + year, month, day, hour, @@ -286,27 +283,33 @@ class FixedDateTimeFormatter { } } - int? _extractNumFromString( - List characters, + int? _extractNumberFromString( + String formattedDateTime, int index, bool throwOnError, ) { var parsed = tryParse( - characters, + formattedDateTime, _blocks.starts[index], _blocks.ends[index], ); if (parsed == null && throwOnError) { throw FormatException( - '${String.fromCharCodes(characters)} should only contain digits'); + "Expected digits at ${formattedDateTime.substring( + _blocks.starts[index], + _blocks.ends[index], + )}", + formattedDateTime, + _blocks.starts[index], + ); } return parsed; } - int? tryParse(List characters, int start, int end) { - int result = 0; + int? tryParse(String formattedDateTime, int start, int end) { + var result = 0; for (var i = start; i < end; i++) { - var digit = characters[i] ^ 0x30; + var digit = formattedDateTime.codeUnitAt(i) ^ 0x30; if (digit <= 9) { result = result * 10 + digit; } else { From a9d222e7fb87ec16193425a95f119bad81d5f1bc Mon Sep 17 00:00:00 2001 From: moritz Date: Wed, 5 Oct 2022 12:40:01 +0000 Subject: [PATCH 061/100] Add larger changes as per review --- .../lib/src/fixed_datetime_formatter.dart | 119 +++++++++++------- .../test/fixed_datetime_formatter_test.dart | 37 ++++-- 2 files changed, 105 insertions(+), 51 deletions(-) diff --git a/pkgs/convert/lib/src/fixed_datetime_formatter.dart b/pkgs/convert/lib/src/fixed_datetime_formatter.dart index f0c48fdc..995ab5bc 100644 --- a/pkgs/convert/lib/src/fixed_datetime_formatter.dart +++ b/pkgs/convert/lib/src/fixed_datetime_formatter.dart @@ -84,7 +84,7 @@ class FixedDateTimeFormatter { if (hasSeenBefore > -1) { throw FormatException( "Pattern contains more than one '$formatCharacter' block.\n" - "Previous occurrence at index ${_blocks.starts[hasSeenBefore]}", + 'Previous occurrence at index ${_blocks.starts[hasSeenBefore]}', pattern, i); } else { @@ -104,7 +104,7 @@ class FixedDateTimeFormatter { /// Throws a [FormatException] if trying to encode a negative year. String encode(DateTime dateTime) { if (dateTime.year < 0) { - throw FormatException("Cannot handle negative years."); + throw FormatException('Cannot handle negative years.'); } var buffer = StringBuffer(); for (var i = 0; i < _blocks.length; i++) { @@ -117,20 +117,12 @@ class FixedDateTimeFormatter { buffer.write(pattern.substring(previousEnd, start)); } var formatCharacter = _blocks.formatCharacters[i]; - var number = - _extractNumberFromDateTime(formatCharacter, dateTime).toString(); - if (formatCharacter == _fractionSecondCode) { - // Special case, as we want fractional seconds to be the leading - // digits. - if (6 > number.length) { - number = number.padLeft(6, '0'); - } - if (number.length > length) { - number = number.substring(0, length); - } else { - number = number.padRight(length, '0'); - } - } else if (number.length > length) { + var number = _extractNumberFromDateTime( + formatCharacter, + dateTime, + length, + ); + if (number.length > length) { number = number.substring(number.length - length); } else if (length > number.length) { number = number.padLeft(length, '0'); @@ -146,28 +138,67 @@ class FixedDateTimeFormatter { return buffer.toString(); } - int _extractNumberFromDateTime(int? formatChar, DateTime dateTime) { - switch (formatChar) { + String _extractNumberFromDateTime( + int? formatCharacter, + DateTime dateTime, + int length, + ) { + int value; + switch (formatCharacter) { case _yearCode: - return dateTime.year; + value = dateTime.year; + break; case _centuryCode: - return dateTime.year ~/ 100; + value = dateTime.year ~/ 100; + break; case _decadeCode: - return dateTime.year ~/ 10; + value = dateTime.year ~/ 10; + break; case _monthCode: - return dateTime.month; + value = dateTime.month; + break; case _dayCode: - return dateTime.day; + value = dateTime.day; + break; case _hourCode: - return dateTime.hour; + value = dateTime.hour; + break; case _minuteCode: - return dateTime.minute; + value = dateTime.minute; + break; case _secondCode: - return dateTime.second; + value = dateTime.second; + break; case _fractionSecondCode: - return dateTime.microsecond + dateTime.millisecond * 1000; + value = dateTime.millisecond; + switch (length) { + case 1: + value ~/= 100; + break; + case 2: + value ~/= 10; + break; + case 3: + break; + case 4: + value = value * 10 + dateTime.microsecond ~/ 100; + break; + case 5: + value = value * 100 + dateTime.microsecond ~/ 10; + break; + case 6: + value = value * 1000 + dateTime.microsecond; + break; + default: + throw AssertionError( + 'Unreachable, length is restricted to 6 in the constructor'); + } + break; + default: + throw AssertionError( + 'Unreachable, the key is checked in the constructor'); } - throw AssertionError("Unreachable, the key is checked in the constructor"); + return value.toString().padLeft(length, '0'); } /// Parses [formattedDateTime] to a [DateTime] as specified by the [pattern]. @@ -211,19 +242,7 @@ class FixedDateTimeFormatter { if (formatCharacter == _fractionSecondCode) { // Special case, as we want fractional seconds to be the leading // digits. - var numberLength = _blocks.ends[i] - _blocks.starts[i]; - if (numberLength > 6) { - if (throwOnError) { - throw FormatException( - 'Fractional seconds can only be specified up to microseconds', - pattern, - _blocks.starts[i], - ); - } else { - return null; - } - } - number *= _powersOfTen[6 - numberLength]; + number *= _powersOfTen[6 - (_blocks.ends[i] - _blocks.starts[i])]; } switch (formatCharacter) { case _yearCode: @@ -295,10 +314,10 @@ class FixedDateTimeFormatter { ); if (parsed == null && throwOnError) { throw FormatException( - "Expected digits at ${formattedDateTime.substring( + 'Expected digits at ${formattedDateTime.substring( _blocks.starts[index], _blocks.ends[index], - )}", + )}', formattedDateTime, _blocks.starts[index], ); @@ -331,6 +350,20 @@ class _ParsedFormatBlocks { void saveBlock(int? char, int start, int end) { if (char != null) { + if (char == FixedDateTimeFormatter._fractionSecondCode && + end - start > 6) { + throw FormatException( + 'Fractional seconds can only be specified up to microseconds', + char, + start, + ); + } else if (end - start > 9) { + throw FormatException( + 'Length of a format char block cannot be larger than 9', + char, + start, + ); + } formatCharacters.add(char); starts.add(start); ends.add(end); diff --git a/pkgs/convert/test/fixed_datetime_formatter_test.dart b/pkgs/convert/test/fixed_datetime_formatter_test.dart index 98505846..21784c60 100644 --- a/pkgs/convert/test/fixed_datetime_formatter_test.dart +++ b/pkgs/convert/test/fixed_datetime_formatter_test.dart @@ -87,9 +87,15 @@ void main() { microseconds: 1, ))); }, onPlatform: skipWeb); - test('Parse 7 S throws', () { + test('7 S throws', () { expect( - () => FixedDateTimeFormatter('SSSSSSS').decode('0000010'), + () => FixedDateTimeFormatter('S' * 7), + throwsFormatException, + ); + }); + test('10 Y throws', () { + expect( + () => FixedDateTimeFormatter('Y' * 10), throwsFormatException, ); }); @@ -132,6 +138,21 @@ void main() { var str = FixedDateTimeFormatter('XCCEY-MMX').encode(DateTime.utc(1996, 4)); expect(str, 'X1996-04X'); }); + test('Format S 1/10 of a second', () { + var str = FixedDateTimeFormatter('S') + .encode(noFractionalSeconds.add(Duration(milliseconds: 100))); + expect(str, '1'); + }); + test('Format SS 1/100 of a second', () { + var str = FixedDateTimeFormatter('SS') + .encode(noFractionalSeconds.add(Duration(milliseconds: 10))); + expect(str, '01'); + }); + test('Format SSS 1/100 of a second', () { + var str = FixedDateTimeFormatter('SSS') + .encode(noFractionalSeconds.add(Duration(milliseconds: 10))); + expect(str, '010'); + }); test('Format SSSS no fractions', () { var str = FixedDateTimeFormatter('SSSS').encode(noFractionalSeconds); expect(str, '0000'); @@ -168,13 +189,13 @@ void main() { var str = FixedDateTimeFormatter('SSSSSS').encode(dateTime); expect(str, '001001'); }, onPlatform: skipWeb); - test('Format SSSSSSS a microsecond', () { - var str = FixedDateTimeFormatter('SSSSSSS') + test('Format SSSSSS0 a microsecond', () { + var str = FixedDateTimeFormatter('SSSSSS0') .encode(noFractionalSeconds.add(Duration(microseconds: 1))); expect(str, '0000010'); }, onPlatform: skipWeb); - test('Format SSSSSSS 1/10 of a second', () { - var str = FixedDateTimeFormatter('SSSSSSS') + test('Format SSSSSS0 1/10 of a second', () { + var str = FixedDateTimeFormatter('SSSSSS0') .encode(noFractionalSeconds.add(Duration(milliseconds: 100))); expect(str, '1000000'); }); @@ -186,12 +207,12 @@ void main() { var str = FixedDateTimeFormatter('ssSSSSSS').encode(dateTime); expect(str, '01000001'); }, onPlatform: skipWeb); - test('Parse ssSSSSSSS a second and a microsecond', () { + test('Parse ssSSSSSS0 a second and a microsecond', () { var dateTime = noFractionalSeconds.add(Duration( seconds: 1, microseconds: 1, )); - var str = FixedDateTimeFormatter('ssSSSSSSS').encode(dateTime); + var str = FixedDateTimeFormatter('ssSSSSSS0').encode(dateTime); expect(str, '010000010'); }, onPlatform: skipWeb); test('Parse negative year throws', () { From 2b01eef1ae33ba8507db7f0b59618b003fa35bd8 Mon Sep 17 00:00:00 2001 From: moritz Date: Wed, 5 Oct 2022 12:40:45 +0000 Subject: [PATCH 062/100] Fix typo --- .../benchmark/fixed_datetime_formatter_benchmark.dart | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pkgs/convert/benchmark/fixed_datetime_formatter_benchmark.dart b/pkgs/convert/benchmark/fixed_datetime_formatter_benchmark.dart index eb2f9238..92c924b9 100644 --- a/pkgs/convert/benchmark/fixed_datetime_formatter_benchmark.dart +++ b/pkgs/convert/benchmark/fixed_datetime_formatter_benchmark.dart @@ -5,14 +5,14 @@ import 'package:benchmark_harness/benchmark_harness.dart'; import 'package:convert/convert.dart'; -/// test the performance of [FixedDateTimeFormatter.decode] +/// Test the performance of [FixedDateTimeFormatter.decode]. class DecodeBenchmark extends BenchmarkBase { final fixedDateTimeFormatter = FixedDateTimeFormatter("YYYYMMDDhhmmss"); - DecodeBenchmark() : super('Parse a million strings to DateTime'); + DecodeBenchmark() : super('Parse 10k strings to DateTime'); @override void run() { - for (var i = 0; i < 100000; i++) { + for (var i = 0; i < 10000; i++) { fixedDateTimeFormatter.decode('19960425050322'); } } From 0927dc2a33594c70cff61afbb03446bbc1658bfa Mon Sep 17 00:00:00 2001 From: moritz Date: Wed, 5 Oct 2022 13:54:43 +0000 Subject: [PATCH 063/100] Changes as per review --- .../lib/src/fixed_datetime_formatter.dart | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/pkgs/convert/lib/src/fixed_datetime_formatter.dart b/pkgs/convert/lib/src/fixed_datetime_formatter.dart index 995ab5bc..88df8414 100644 --- a/pkgs/convert/lib/src/fixed_datetime_formatter.dart +++ b/pkgs/convert/lib/src/fixed_datetime_formatter.dart @@ -26,9 +26,11 @@ /// `YYYY------MM`. When encoding a [DateTime], the non-format characters are in /// the output verbatim. /// -/// Note: this class differs from [DateFormat] in that here, the characters are -/// treated literally, i.e., the format string `YYY` matching `996` would result -/// in the same as calling `DateTime(996)`. +/// Note: this class differs from [DateFormat] in that here, the format +/// character count is interpreted literally. For example, using the format +/// string `YYY` to decode the string `996` would result in the same [DateTime] +/// as calling `DateTime(996)`, and the same format string used to encode the +/// `DateTime(1996)` would output only the three digits 996. class FixedDateTimeFormatter { static const _powersOfTen = [1, 10, 100, 1000, 10000, 100000]; static const _validFormatCharacters = [ @@ -52,7 +54,7 @@ class FixedDateTimeFormatter { static const _secondCode = 0x73; /*s*/ static const _fractionSecondCode = 0x53; /*S*/ - /// The format pattern string of this formatter + /// The format pattern string of this formatter. final String pattern; /// Whether to create UTC [DateTime] objects when parsing. @@ -101,10 +103,14 @@ class FixedDateTimeFormatter { /// Converts a [DateTime] to a [String] as specified by the [pattern]. /// - /// Throws a [FormatException] if trying to encode a negative year. + /// The [dateTime.year] must not be negative. String encode(DateTime dateTime) { if (dateTime.year < 0) { - throw FormatException('Cannot handle negative years.'); + throw ArgumentError.value( + dateTime, + 'dateTime', + 'Year must not be negative', + ); } var buffer = StringBuffer(); for (var i = 0; i < _blocks.length; i++) { From a17a3a54e92458ac10755b11d2d4e4f67ecb09fc Mon Sep 17 00:00:00 2001 From: moritz Date: Wed, 5 Oct 2022 14:07:56 +0000 Subject: [PATCH 064/100] Add changelog entry --- pkgs/convert/CHANGELOG.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pkgs/convert/CHANGELOG.md b/pkgs/convert/CHANGELOG.md index c4120a08..ea09f8e0 100644 --- a/pkgs/convert/CHANGELOG.md +++ b/pkgs/convert/CHANGELOG.md @@ -1,5 +1,6 @@ -## 3.0.3-dev +## 3.1.0-dev +* Add a fixed-pattern DateTime formatter. See [#210](https://github.com/dart-lang/intl/issues/210) in package:intl. ## 3.0.2 From 67c1c16f1e78774b350ac8384d967cb1c2bad494 Mon Sep 17 00:00:00 2001 From: moritz Date: Wed, 5 Oct 2022 14:15:28 +0000 Subject: [PATCH 065/100] Fix test --- pkgs/convert/test/fixed_datetime_formatter_test.dart | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/convert/test/fixed_datetime_formatter_test.dart b/pkgs/convert/test/fixed_datetime_formatter_test.dart index 21784c60..fdba7beb 100644 --- a/pkgs/convert/test/fixed_datetime_formatter_test.dart +++ b/pkgs/convert/test/fixed_datetime_formatter_test.dart @@ -215,10 +215,10 @@ void main() { var str = FixedDateTimeFormatter('ssSSSSSS0').encode(dateTime); expect(str, '010000010'); }, onPlatform: skipWeb); - test('Parse negative year throws', () { + test('Parse negative year throws Error', () { expect( () => FixedDateTimeFormatter('YYYY').encode(DateTime(-1)), - throwsFormatException, + throwsArgumentError, ); }); } From 20a0091c9bb6566813442bdc2e15da4628c2ef4b Mon Sep 17 00:00:00 2001 From: Devon Carew Date: Thu, 6 Oct 2022 04:21:33 -0700 Subject: [PATCH 066/100] update the CI configuration (dart-lang/convert#67) --- pkgs/convert/.github/dependabot.yaml | 8 ++++++++ pkgs/convert/.github/workflows/test-package.yml | 8 ++++---- 2 files changed, 12 insertions(+), 4 deletions(-) create mode 100644 pkgs/convert/.github/dependabot.yaml diff --git a/pkgs/convert/.github/dependabot.yaml b/pkgs/convert/.github/dependabot.yaml new file mode 100644 index 00000000..21448193 --- /dev/null +++ b/pkgs/convert/.github/dependabot.yaml @@ -0,0 +1,8 @@ +# Dependabot configuration file. +version: 2 + +updates: + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "monthly" diff --git a/pkgs/convert/.github/workflows/test-package.yml b/pkgs/convert/.github/workflows/test-package.yml index e3bd3c06..d8af0529 100644 --- a/pkgs/convert/.github/workflows/test-package.yml +++ b/pkgs/convert/.github/workflows/test-package.yml @@ -22,8 +22,8 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@v2 - - uses: dart-lang/setup-dart@v1.0 + - uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 + - uses: dart-lang/setup-dart@6a218f2413a3e78e9087f638a238f6b40893203d with: sdk: ${{ matrix.sdk }} - id: install @@ -49,8 +49,8 @@ jobs: os: [ubuntu-latest] sdk: [2.12.0, dev] steps: - - uses: actions/checkout@v2 - - uses: dart-lang/setup-dart@v1.0 + - uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 + - uses: dart-lang/setup-dart@6a218f2413a3e78e9087f638a238f6b40893203d with: sdk: ${{ matrix.sdk }} - id: install From 7c109a094e83ae0f27e45903dd63c255428f2b7d Mon Sep 17 00:00:00 2001 From: Moritz Date: Wed, 12 Oct 2022 07:33:55 -0400 Subject: [PATCH 067/100] Bump version for publication (dart-lang/convert#68) * Bump version for publication * Bump test dep to fix http_multi_server dep --- pkgs/convert/CHANGELOG.md | 2 +- pkgs/convert/pubspec.yaml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/pkgs/convert/CHANGELOG.md b/pkgs/convert/CHANGELOG.md index ea09f8e0..8bec43ab 100644 --- a/pkgs/convert/CHANGELOG.md +++ b/pkgs/convert/CHANGELOG.md @@ -1,4 +1,4 @@ -## 3.1.0-dev +## 3.1.0 * Add a fixed-pattern DateTime formatter. See [#210](https://github.com/dart-lang/intl/issues/210) in package:intl. diff --git a/pkgs/convert/pubspec.yaml b/pkgs/convert/pubspec.yaml index 4e92df0d..693dbc53 100644 --- a/pkgs/convert/pubspec.yaml +++ b/pkgs/convert/pubspec.yaml @@ -1,5 +1,5 @@ name: convert -version: 3.0.3-dev +version: 3.1.0 description: >- Utilities for converting between data representations. Provides a number of Sink, Codec, Decoder, and Encoder types. @@ -13,5 +13,5 @@ dependencies: dev_dependencies: lints: ^1.0.0 - test: ^1.16.0 + test: ^1.17.0 benchmark_harness: ^2.2.0 From c07669365081db9af5986f147da60b30793f1453 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Wed, 12 Oct 2022 14:46:11 -0700 Subject: [PATCH 068/100] Fix comment references, update lints, require latest Dart SDK (dart-lang/convert#69) Prepare to release v3.1.1 Also did cleanup to the markdown files --- .../.github/workflows/test-package.yml | 2 +- pkgs/convert/CHANGELOG.md | 43 ++-- pkgs/convert/README.md | 14 +- pkgs/convert/analysis_options.yaml | 67 ++++--- .../fixed_datetime_formatter_benchmark.dart | 2 +- pkgs/convert/lib/convert.dart | 2 - pkgs/convert/lib/src/accumulator_sink.dart | 1 + pkgs/convert/lib/src/codepage.dart | 189 +++++++++--------- .../lib/src/fixed_datetime_formatter.dart | 16 +- pkgs/convert/lib/src/hex.dart | 4 +- pkgs/convert/lib/src/hex/decoder.dart | 6 +- pkgs/convert/lib/src/hex/encoder.dart | 2 +- pkgs/convert/lib/src/percent.dart | 5 +- pkgs/convert/lib/src/percent/decoder.dart | 14 +- pkgs/convert/lib/src/percent/encoder.dart | 4 +- pkgs/convert/lib/src/utils.dart | 4 +- pkgs/convert/pubspec.yaml | 8 +- pkgs/convert/test/accumulator_sink_test.dart | 6 +- .../test/byte_accumulator_sink_test.dart | 8 +- pkgs/convert/test/codepage_test.dart | 29 +-- .../test/fixed_datetime_formatter_test.dart | 46 ++--- pkgs/convert/test/hex_test.dart | 106 +++++----- pkgs/convert/test/identity_codec_test.dart | 6 +- pkgs/convert/test/percent_test.dart | 164 +++++++-------- .../test/string_accumulator_sink_test.dart | 30 +-- 25 files changed, 387 insertions(+), 391 deletions(-) diff --git a/pkgs/convert/.github/workflows/test-package.yml b/pkgs/convert/.github/workflows/test-package.yml index d8af0529..2bba6c64 100644 --- a/pkgs/convert/.github/workflows/test-package.yml +++ b/pkgs/convert/.github/workflows/test-package.yml @@ -47,7 +47,7 @@ jobs: matrix: # Add macos-latest and/or windows-latest if relevant for this package. os: [ubuntu-latest] - sdk: [2.12.0, dev] + sdk: [2.18.0, dev] steps: - uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 - uses: dart-lang/setup-dart@6a218f2413a3e78e9087f638a238f6b40893203d diff --git a/pkgs/convert/CHANGELOG.md b/pkgs/convert/CHANGELOG.md index 8bec43ab..923d6dab 100644 --- a/pkgs/convert/CHANGELOG.md +++ b/pkgs/convert/CHANGELOG.md @@ -1,41 +1,44 @@ +## 3.1.1 + +- Require Dart 2.18 +- Fix a number of comment references. + ## 3.1.0 -* Add a fixed-pattern DateTime formatter. See [#210](https://github.com/dart-lang/intl/issues/210) in package:intl. +- Add a fixed-pattern DateTime formatter. See + [#210](https://github.com/dart-lang/intl/issues/210) in package:intl. ## 3.0.2 -* Fix bug in `CodePage` class. See issue [#47](https://github.com/dart-lang/convert/issues/47). +- Fix bug in `CodePage` class. See issue + [#47](https://github.com/dart-lang/convert/issues/47). ## 3.0.1 -* Dependency clean-up. +- Dependency clean-up. ## 3.0.0 -* Stable null safety release. - -## 3.0.0-nullsafety.0 - -Pre-release for the null safety migration of this package. - - * Added `CodePage` class for single-byte `Encoding` implementations. +- Stable null safety release. +- Added `CodePage` class for single-byte `Encoding` implementations. ## 2.1.1 - * Fixed a DDC compilation regression for consumers using the Dart 1.x SDK that was introduced in `2.1.0`. +- Fixed a DDC compilation regression for consumers using the Dart 1.x SDK that + was introduced in `2.1.0`. ## 2.1.0 - * Added an `IdentityCodec` which implements `Codec` for use as default - value for in functions accepting an optional `Codec` as parameter. +- Added an `IdentityCodec` which implements `Codec` for use as default + value for in functions accepting an optional `Codec` as parameter. ## 2.0.2 -* Set max SDK version to `<3.0.0`, and adjust other dependencies. +- Set max SDK version to `<3.0.0`, and adjust other dependencies. ## 2.0.1 -* `PercentEncoder` no longer encodes digits. This follows the specified +- `PercentEncoder` no longer encodes digits. This follows the specified behavior. ## 2.0.0 @@ -43,22 +46,22 @@ Pre-release for the null safety migration of this package. **Note**: No new APIs have been added in 2.0.0. Packages that would use 2.0.0 as a lower bound should use 1.0.0 instead—for example, `convert: ">=1.0.0 <3.0.0"`. -* `HexDecoder`, `HexEncoder`, `PercentDecoder`, and `PercentEncoder` no longer +- `HexDecoder`, `HexEncoder`, `PercentDecoder`, and `PercentEncoder` no longer extend `ChunkedConverter`. ## 1.1.1 -* Fix all strong-mode warnings. +- Fix all strong-mode warnings. ## 1.1.0 -* Add `AccumulatorSink`, `ByteAccumulatorSink`, and `StringAccumulatorSink` +- Add `AccumulatorSink`, `ByteAccumulatorSink`, and `StringAccumulatorSink` classes for providing synchronous access to the output of chunked converters. ## 1.0.1 -* Small improvement in percent decoder efficiency. +- Small improvement in percent decoder efficiency. ## 1.0.0 -* Initial version +- Initial version diff --git a/pkgs/convert/README.md b/pkgs/convert/README.md index 47392cb6..67e91aea 100644 --- a/pkgs/convert/README.md +++ b/pkgs/convert/README.md @@ -2,14 +2,8 @@ [![pub package](https://img.shields.io/pub/v/convert.svg)](https://pub.dev/packages/convert) [![package publisher](https://img.shields.io/pub/publisher/convert.svg)](https://pub.dev/packages/convert/publisher) -Utilities for converting between data representations. - -## Conversion utilities package - -This package contains encoders and decoders for converting between different -data representations. It's the external counterpart of the `dart:convert` core -library, and contains less-central APIs and APIs that need more flexible +Contains encoders and decoders for converting between different +data representations. It's the external counterpart of the +[`dart:convert`](https://api.dart.dev/dart-convert/dart-convert-library.html) +SDK library, and contains less-central APIs and APIs that need more flexible versioning. - -See also -[api.dart.dev/dart-convert](https://api.dart.dev/stable/dart-convert/dart-convert-library.html). diff --git a/pkgs/convert/analysis_options.yaml b/pkgs/convert/analysis_options.yaml index 162fc088..d624ccd3 100644 --- a/pkgs/convert/analysis_options.yaml +++ b/pkgs/convert/analysis_options.yaml @@ -1,45 +1,46 @@ +# https://dart.dev/guides/language/analysis-options include: package:lints/recommended.yaml analyzer: - strong-mode: - implicit-casts: false + language: + strict-casts: true + strict-raw-types: true linter: rules: - - avoid_empty_else - - avoid_init_to_null - - avoid_null_checks_in_equality_operators + - always_declare_return_types + - avoid_catching_errors + - avoid_dynamic_calls + - avoid_private_typedef_functions + - avoid_redundant_argument_values - avoid_unused_constructor_parameters - - await_only_futures - - camel_case_types + - avoid_void_async - cancel_subscriptions - - constant_identifier_names - - control_flow_in_finally + - comment_references - directives_ordering - - empty_catches - - empty_constructor_bodies - - empty_statements - - hash_and_equals - - implementation_imports - - iterable_contains_unrelated_type - - library_names - - library_prefixes - - list_remove_unrelated_type - - non_constant_identifier_names - - overridden_fields + - lines_longer_than_80_chars + - literal_only_boolean_expressions + - missing_whitespace_between_adjacent_strings + - no_adjacent_strings_in_list + - no_runtimeType_toString + - omit_local_variable_types + - only_throw_errors - package_api_docs - - package_names - - package_prefixed_library_names - - prefer_equal_for_default_values - - prefer_final_fields - - prefer_generic_function_type_aliases - - prefer_is_not_empty - - slash_for_doc_comments + - prefer_asserts_in_initializer_lists + - prefer_const_constructors + - prefer_const_declarations + - prefer_expression_function_bodies + - prefer_relative_imports + - prefer_single_quotes + - sort_pub_dependencies - test_types_in_equals - throw_in_finally - - type_init_formals - - unnecessary_brace_in_string_interps - - unnecessary_const - - unnecessary_new - - unrelated_type_equality_checks - - valid_regexps + - type_annotate_public_apis + - unawaited_futures + - unnecessary_await_in_return + - unnecessary_lambdas + - unnecessary_parenthesis + - unnecessary_statements + - use_is_even_rather_than_modulo + - use_string_buffers + - use_super_parameters diff --git a/pkgs/convert/benchmark/fixed_datetime_formatter_benchmark.dart b/pkgs/convert/benchmark/fixed_datetime_formatter_benchmark.dart index 92c924b9..6f35c015 100644 --- a/pkgs/convert/benchmark/fixed_datetime_formatter_benchmark.dart +++ b/pkgs/convert/benchmark/fixed_datetime_formatter_benchmark.dart @@ -7,7 +7,7 @@ import 'package:convert/convert.dart'; /// Test the performance of [FixedDateTimeFormatter.decode]. class DecodeBenchmark extends BenchmarkBase { - final fixedDateTimeFormatter = FixedDateTimeFormatter("YYYYMMDDhhmmss"); + final fixedDateTimeFormatter = FixedDateTimeFormatter('YYYYMMDDhhmmss'); DecodeBenchmark() : super('Parse 10k strings to DateTime'); @override diff --git a/pkgs/convert/lib/convert.dart b/pkgs/convert/lib/convert.dart index 4d869813..ec5c878f 100644 --- a/pkgs/convert/lib/convert.dart +++ b/pkgs/convert/lib/convert.dart @@ -2,8 +2,6 @@ // 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. -library convert; - export 'src/accumulator_sink.dart'; export 'src/byte_accumulator_sink.dart'; export 'src/codepage.dart'; diff --git a/pkgs/convert/lib/src/accumulator_sink.dart b/pkgs/convert/lib/src/accumulator_sink.dart index ef01a761..af55b10a 100644 --- a/pkgs/convert/lib/src/accumulator_sink.dart +++ b/pkgs/convert/lib/src/accumulator_sink.dart @@ -3,6 +3,7 @@ // BSD-style license that can be found in the LICENSE file. import 'dart:collection'; +import 'dart:convert'; /// A sink that provides access to all the [events] that have been passed to it. /// diff --git a/pkgs/convert/lib/src/codepage.dart b/pkgs/convert/lib/src/codepage.dart index cfc58db3..50941b49 100644 --- a/pkgs/convert/lib/src/codepage.dart +++ b/pkgs/convert/lib/src/codepage.dart @@ -2,160 +2,161 @@ // 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 "dart:convert"; -import "dart:typed_data"; +import 'dart:convert'; +import 'dart:typed_data'; /// The ISO-8859-2/Latin-2 (Eastern European) code page. final CodePage latin2 = - CodePage._bmp("latin-2", "$_ascii$_noControls$_top8859_2"); + CodePage._bmp('latin-2', '$_ascii$_noControls$_top8859_2'); /// The ISO-8859-3/Latin-3 (South European) code page. final CodePage latin3 = - CodePage._bmp("latin-3", "$_ascii$_noControls$_top8859_3"); + CodePage._bmp('latin-3', '$_ascii$_noControls$_top8859_3'); /// The ISO-8859-4/Latin-4 (North European) code page. final CodePage latin4 = - CodePage._bmp("latin-4", "$_ascii$_noControls$_top8859_4"); + CodePage._bmp('latin-4', '$_ascii$_noControls$_top8859_4'); /// The ISO-8859-5/Latin-Cyrillic code page. final CodePage latinCyrillic = - CodePage._bmp("cyrillic", "$_ascii$_noControls$_top8859_5"); + CodePage._bmp('cyrillic', '$_ascii$_noControls$_top8859_5'); /// The ISO-8859-6/Latin-Arabic code page. final CodePage latinArabic = - CodePage._bmp("arabic", "$_ascii$_noControls$_top8859_6"); + CodePage._bmp('arabic', '$_ascii$_noControls$_top8859_6'); /// The ISO-8859-7/Latin-Greek code page. final CodePage latinGreek = - CodePage._bmp("greek", "$_ascii$_noControls$_top8859_7"); + CodePage._bmp('greek', '$_ascii$_noControls$_top8859_7'); /// The ISO-8859-7/Latin-Hebrew code page. final CodePage latinHebrew = - CodePage._bmp("hebrew", "$_ascii$_noControls$_top8859_8"); + CodePage._bmp('hebrew', '$_ascii$_noControls$_top8859_8'); /// The ISO-8859-9/Latin-5 (Turkish) code page. final CodePage latin5 = - CodePage._bmp("latin-5", "$_ascii$_noControls$_top8859_9"); + CodePage._bmp('latin-5', '$_ascii$_noControls$_top8859_9'); /// The ISO-8859-10/Latin-6 (Nordic) code page. final CodePage latin6 = - CodePage._bmp("latin-6", "$_ascii$_noControls$_top8859_10"); + CodePage._bmp('latin-6', '$_ascii$_noControls$_top8859_10'); /// The ISO-8859-11/Latin-Thai code page. final CodePage latinThai = - CodePage._bmp("tis620", "$_ascii$_noControls$_top8859_11"); + CodePage._bmp('tis620', '$_ascii$_noControls$_top8859_11'); /// The ISO-8859-13/Latin-6 (Baltic Rim) code page. final CodePage latin7 = - CodePage._bmp("latin-7", "$_ascii$_noControls$_top8859_13"); + CodePage._bmp('latin-7', '$_ascii$_noControls$_top8859_13'); /// The ISO-8859-14/Latin-8 (Celtic) code page. final CodePage latin8 = - CodePage._bmp("latin-8", "$_ascii$_noControls$_top8859_14"); + CodePage._bmp('latin-8', '$_ascii$_noControls$_top8859_14'); /// The ISO-8859-15/Latin-9 (Western European revised) code page. final CodePage latin9 = - CodePage._bmp("latin-9", "$_ascii$_noControls$_top8859_15"); + CodePage._bmp('latin-9', '$_ascii$_noControls$_top8859_15'); /// The ISO-8859-16/Latin-10 (South Eastern European) code page. final CodePage latin10 = - CodePage._bmp("latin-10", "$_ascii$_noControls$_top8859_16"); + CodePage._bmp('latin-10', '$_ascii$_noControls$_top8859_16'); /// Characters in ISO-8859-2 above the ASCII and top control characters. -const _top8859_2 = "\xa0Ą˘Ł¤ĽŚ§¨ŠŞŤŹ\xadŽŻ°ą˛ł´ľśˇ¸šşťź˝žż" - "ŔÁÂĂÄĹĆÇČÉĘËĚÍÎĎĐŃŇÓÔŐÖ×ŘŮÚŰÜÝŢß" - "ŕáâăäĺćçčéęëěíîďđńňóôőö÷řůúűüýţ˙"; +const _top8859_2 = '\xa0Ą˘Ł¤ĽŚ§¨ŠŞŤŹ\xadŽŻ°ą˛ł´ľśˇ¸šşťź˝žż' + 'ŔÁÂĂÄĹĆÇČÉĘËĚÍÎĎĐŃŇÓÔŐÖ×ŘŮÚŰÜÝŢß' + 'ŕáâăäĺćçčéęëěíîďđńňóôőö÷řůúűüýţ˙'; /// Characters in ISO-8859-3 above the ASCII and top control characters. -const _top8859_3 = "\xa0Ħ˘£\uFFFD¤Ĥ§¨İŞĞĴ\xad\uFFFDŻ°ħ²³´µĥ·¸ışğĵ½\uFFFDż" - "ÀÁÂ\uFFFDÄĊĈÇÈÉÊËÌÍÎÏ\uFFFDÑÒÓÔĠÖ×ĜÙÚÛÜŬŜß" - "àáâ\uFFFDäċĉçèéêëìíîï\uFFFDñòóôġö÷ĝùúûüŭŝ˙"; +const _top8859_3 = '\xa0Ħ˘£\uFFFD¤Ĥ§¨İŞĞĴ\xad\uFFFDŻ°ħ²³´µĥ·¸ışğĵ½\uFFFDż' + 'ÀÁÂ\uFFFDÄĊĈÇÈÉÊËÌÍÎÏ\uFFFDÑÒÓÔĠÖ×ĜÙÚÛÜŬŜß' + 'àáâ\uFFFDäċĉçèéêëìíîï\uFFFDñòóôġö÷ĝùúûüŭŝ˙'; /// Characters in ISO-8859-4 above the ASCII and top control characters. -const _top8859_4 = "\xa0ĄĸŖ¤ĨĻ§¨ŠĒĢŦ\xadŽ¯°ą˛ŗ´ĩļˇ¸šēģŧŊžŋ" - "ĀÁÂÃÄÅÆĮČÉĘËĖÍÎĪĐŅŌĶÔÕÖ×ØŲÚÛÜŨŪß" - "āáâãäåæįčéęëėíîīđņōķôõö÷øųúûüũū˙"; +const _top8859_4 = '\xa0ĄĸŖ¤ĨĻ§¨ŠĒĢŦ\xadŽ¯°ą˛ŗ´ĩļˇ¸šēģŧŊžŋ' + 'ĀÁÂÃÄÅÆĮČÉĘËĖÍÎĪĐŅŌĶÔÕÖ×ØŲÚÛÜŨŪß' + 'āáâãäåæįčéęëėíîīđņōķôõö÷øųúûüũū˙'; /// Characters in ISO-8859-5 above the ASCII and top control characters. -const _top8859_5 = "\xa0ЁЂЃЄЅІЇЈЉЊЋЌ\xadЎЏАБВГДЕЖЗИЙКЛМНОП" - "РСТУФХЦЧШЩЪЫЬЭЮЯабвгдежзийклмноп" - "рстуфхцчшщъыьэюя№ёђѓєѕіїјљњћќ§ўџ"; +const _top8859_5 = '\xa0ЁЂЃЄЅІЇЈЉЊЋЌ\xadЎЏАБВГДЕЖЗИЙКЛМНОП' + 'РСТУФХЦЧШЩЪЫЬЭЮЯабвгдежзийклмноп' + 'рстуфхцчшщъыьэюя№ёђѓєѕіїјљњћќ§ўџ'; /// Characters in ISO-8859-6 above the ASCII and top control characters. -const _top8859_6 = "\xa0\uFFFD\uFFFD\uFFFD¤\uFFFD\uFFFD\uFFFD" - "\uFFFD\uFFFD\uFFFD\uFFFD\u060c\xad\uFFFD\uFFFD" - "\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD" - "\uFFFD\uFFFD\uFFFD\u061b\uFFFD\uFFFD\uFFFD\u061f" - "\uFFFD\u0621\u0622\u0623\u0624\u0625\u0626\u0627" - "\u0628\u0629\u062a\u062b\u062c\u062d\u062e\u062f" - "\u0630\u0631\u0632\u0633\u0634\u0635\u0636\u0637" - "\u0638\u0639\u063a\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD" - "\u0640\u0641\u0642\u0643\u0644\u0645\u0646\u0647" - "\u0648\u0649\u064a\u064b\u064c\u064d\u064e\u064f" - "\u0650\u0651\u0652\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD" - "\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD"; +const _top8859_6 = '\xa0\uFFFD\uFFFD\uFFFD¤\uFFFD\uFFFD\uFFFD' + '\uFFFD\uFFFD\uFFFD\uFFFD\u060c\xad\uFFFD\uFFFD' + '\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD' + '\uFFFD\uFFFD\uFFFD\u061b\uFFFD\uFFFD\uFFFD\u061f' + '\uFFFD\u0621\u0622\u0623\u0624\u0625\u0626\u0627' + '\u0628\u0629\u062a\u062b\u062c\u062d\u062e\u062f' + '\u0630\u0631\u0632\u0633\u0634\u0635\u0636\u0637' + '\u0638\u0639\u063a\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD' + '\u0640\u0641\u0642\u0643\u0644\u0645\u0646\u0647' + '\u0648\u0649\u064a\u064b\u064c\u064d\u064e\u064f' + '\u0650\u0651\u0652\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD' + '\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD'; /// Characters in ISO-8859-7 above the ASCII and top control characters. -const _top8859_7 = "\xa0‘’£€₯¦§¨©ͺ«¬\xad\uFFFD―°±²³΄΅Ά·ΈΉΊ»Ό½ΎΏ" - "ΐΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡ\uFFFDΣΤΥΦΧΨΩΪΫάέήί" - "ΰαβγδεζηθικλμνξοπρςστυφχψωϊϋόύώ\uFFFD"; +const _top8859_7 = '\xa0‘’£€₯¦§¨©ͺ«¬\xad\uFFFD―°±²³΄΅Ά·ΈΉΊ»Ό½ΎΏ' + 'ΐΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡ\uFFFDΣΤΥΦΧΨΩΪΫάέήί' + 'ΰαβγδεζηθικλμνξοπρςστυφχψωϊϋόύώ\uFFFD'; /// Characters in ISO-8859-8 above the ASCII and top control characters. -const _top8859_8 = "\xa0\uFFFD¢£¤¥¦§¨©×«¬\xad®¯°±²³´µ¶·¸¹÷»¼½¾\uFFFD" - "\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD" - "\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD" - "\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD" - "\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD‗" - "\u05d0\u05d1\u05d2\u05d3\u05d4\u05d5\u05d6\u05d7" - "\u05d8\u05d9\u05da\u05db\u05dc\u05dd\u05de\u05df" - "\u05e0\u05e1\u05e2\u05e3\u05e4\u05e5\u05e6\u05e7" - "\u05e8\u05e9\u05ea\uFFFD\uFFFD\u200e\u200f\uFFFD"; +const _top8859_8 = '\xa0\uFFFD¢£¤¥¦§¨©×«¬\xad®¯°±²³´µ¶·¸¹÷»¼½¾\uFFFD' + '\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD' + '\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD' + '\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD' + '\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD‗' + '\u05d0\u05d1\u05d2\u05d3\u05d4\u05d5\u05d6\u05d7' + '\u05d8\u05d9\u05da\u05db\u05dc\u05dd\u05de\u05df' + '\u05e0\u05e1\u05e2\u05e3\u05e4\u05e5\u05e6\u05e7' + '\u05e8\u05e9\u05ea\uFFFD\uFFFD\u200e\u200f\uFFFD'; /// Characters in ISO-8859-9 above the ASCII and top control characters. -const _top8859_9 = "\xa0¡¢£¤¥¦§¨©ª«¬\xad®¯°±²³´µ¶·¸¹º»¼½¾¿" - "ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏĞÑÒÓÔÕÖ×ØÙÚÛÜİŞß" - "àáâãäåæçèéêëìíîïğñòóôõö÷øùúûüışÿ"; +const _top8859_9 = '\xa0¡¢£¤¥¦§¨©ª«¬\xad®¯°±²³´µ¶·¸¹º»¼½¾¿' + 'ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏĞÑÒÓÔÕÖ×ØÙÚÛÜİŞß' + 'àáâãäåæçèéêëìíîïğñòóôõö÷øùúûüışÿ'; /// Characters in ISO-8859-10 above the ASCII and top control characters. -const _top8859_10 = "\xa0ĄĒĢĪĨĶ§ĻĐŠŦŽ\xadŪŊ°ąēģīĩķ·ļđšŧž―ūŋ" - "ĀÁÂÃÄÅÆĮČÉĘËĖÍÎÏÐŅŌÓÔÕÖŨØŲÚÛÜÝÞß" - "āáâãäåæįčéęëėíîïðņōóôõöũøųúûüýþĸ"; +const _top8859_10 = '\xa0ĄĒĢĪĨĶ§ĻĐŠŦŽ\xadŪŊ°ąēģīĩķ·ļđšŧž―ūŋ' + 'ĀÁÂÃÄÅÆĮČÉĘËĖÍÎÏÐŅŌÓÔÕÖŨØŲÚÛÜÝÞß' + 'āáâãäåæįčéęëėíîïðņōóôõöũøųúûüýþĸ'; /// Characters in ISO-8859-11 above the ASCII and top control characters. -const _top8859_11 = "\xa0กขฃคฅฆงจฉชซฌญฎฏฐฑฒณดตถทธนบปผฝพฟ" - "ภมยรฤลฦวศษสหฬอฮฯะัาำิีึืฺุู\uFFFD\uFFFD\uFFFD\uFFFD฿" - "เแโใไๅๆ็่้๊๋์ํ๎๏๐๑๒๓๔๕๖๗๘๙๚๛\uFFFD\uFFFD\uFFFD\uFFFD"; +const _top8859_11 = '\xa0กขฃคฅฆงจฉชซฌญฎฏฐฑฒณดตถทธนบปผฝพฟ' + 'ภมยรฤลฦวศษสหฬอฮฯะัาำิีึืฺุู\uFFFD\uFFFD\uFFFD\uFFFD฿' + 'เแโใไๅๆ็่้๊๋์ํ๎๏๐๑๒๓๔๕๖๗๘๙๚๛\uFFFD\uFFFD\uFFFD\uFFFD'; /// Characters in ISO-8859-13 above the ASCII and top control characters. -const _top8859_13 = "\xa0”¢£¤„¦§Ø©Ŗ«¬\xad®Æ°±²³“µ¶·ø¹ŗ»¼½¾æ" - "ĄĮĀĆÄÅĘĒČÉŹĖĢĶĪĻŠŃŅÓŌÕÖ×ŲŁŚŪÜŻŽß" - "ąįāćäåęēčéźėģķīļšńņóōõö÷ųłśūüżž’"; +const _top8859_13 = '\xa0”¢£¤„¦§Ø©Ŗ«¬\xad®Æ°±²³“µ¶·ø¹ŗ»¼½¾æ' + 'ĄĮĀĆÄÅĘĒČÉŹĖĢĶĪĻŠŃŅÓŌÕÖ×ŲŁŚŪÜŻŽß' + 'ąįāćäåęēčéźėģķīļšńņóōõö÷ųłśūüżž’'; /// Characters in ISO-8859-14 above the ASCII and top control characters. -const _top8859_14 = "\xa0Ḃḃ£ĊċḊ§Ẁ©ẂḋỲ\xad®ŸḞḟĠġṀṁ¶ṖẁṗẃṠỳẄẅṡ" - "ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏŴÑÒÓÔÕÖṪØÙÚÛÜÝŶß" - "àáâãäåæçèéêëìíîïŵñòóôõöṫøùúûüýŷÿ"; +const _top8859_14 = '\xa0Ḃḃ£ĊċḊ§Ẁ©ẂḋỲ\xad®ŸḞḟĠġṀṁ¶ṖẁṗẃṠỳẄẅṡ' + 'ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏŴÑÒÓÔÕÖṪØÙÚÛÜÝŶß' + 'àáâãäåæçèéêëìíîïŵñòóôõöṫøùúûüýŷÿ'; /// Characters in ISO-8859-15 above the ASCII and top control characters. -const _top8859_15 = "\xa0¡¢£€¥Š§š©ª«¬\xad®¯°±²³Žµ¶·ž¹º»ŒœŸ¿" - "ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞß" - "àáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ"; +const _top8859_15 = '\xa0¡¢£€¥Š§š©ª«¬\xad®¯°±²³Žµ¶·ž¹º»ŒœŸ¿' + 'ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞß' + 'àáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ'; /// Characters in ISO-8859-16 above the ASCII and top control characters. -const _top8859_16 = "\xa0ĄąŁ€„Š§š©Ș«Ź\xadźŻ°±ČłŽ”¶·žčș»ŒœŸż" - "ÀÁÂĂÄĆÆÇÈÉÊËÌÍÎÏĐŃÒÓÔŐÖŚŰÙÚÛÜĘȚß" - "àáâăäćæçèéêëìíîïđńòóôőöśűùúûüęțÿ"; +const _top8859_16 = '\xa0ĄąŁ€„Š§š©Ș«Ź\xadźŻ°±ČłŽ”¶·žčș»ŒœŸż' + 'ÀÁÂĂÄĆÆÇÈÉÊËÌÍÎÏĐŃÒÓÔŐÖŚŰÙÚÛÜĘȚß' + 'àáâăäćæçèéêëìíîïđńòóôőöśűùúûüęțÿ'; -const _noControls = "\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD" - "\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD" - "\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD" - "\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD"; +const _noControls = '\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD' + '\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD' + '\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD' + '\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD'; /// ASCII characters without control characters. Shared by many code pages. -const _ascii = "$_noControls" +const _ascii = '$_noControls' + // ignore: missing_whitespace_between_adjacent_strings r""" !"#$%&'()*+,-./0123456789:;<=>?""" - r"@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_" - "`abcdefghijklmnopqrstuvwxyz{|}~\uFFFD"; + r'@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_' + '`abcdefghijklmnopqrstuvwxyz{|}~\uFFFD'; /// A mapping between bytes and characters. /// @@ -184,7 +185,7 @@ class CodePage extends Encoding { /// /// The [characters] must contain precisely 256 characters (code points). /// - /// A U+FFFD (invalid character) entry in [character] means that the + /// A U+FFFD (invalid character) entry in [characters] means that the /// corresponding byte does not have a definition in this code page. CodePage._general(this.name, String characters) : decoder = _createDecoder(characters); @@ -198,7 +199,7 @@ class CodePage extends Encoding { /// The [characters] must contain precisely 256 code points from the BMP /// which means that it should have length 256 and not contain any surrogates. /// - /// A U+FFFD (invalid character) entry in [character] means that the + /// A U+FFFD (invalid character) entry in [characters] means that the /// corresponding byte does not have a definition in this code page. CodePage._bmp(this.name, String characters) : decoder = _BmpCodePageDecoder(characters); @@ -252,7 +253,7 @@ abstract class CodePageDecoder implements Converter, String> { /// Creates a decoder from [characters]. /// /// Recognizes if [characters] contains only characters in the BMP, -/// and creates a [BmpCodePageDecoder] in that case. +/// and creates a [_BmpCodePageDecoder] in that case. CodePageDecoder _createDecoder(String characters) { var result = Uint32List(256); var i = 0; @@ -260,14 +261,14 @@ CodePageDecoder _createDecoder(String characters) { for (var char in characters.runes) { if (i >= 256) { throw ArgumentError.value( - characters, "characters", "Must contain 256 characters"); + characters, 'characters', 'Must contain 256 characters'); } result[i++] = char; allChars |= char; } if (i < 256) { throw ArgumentError.value( - characters, "characters", "Must contain 256 characters"); + characters, 'characters', 'Must contain 256 characters'); } if (allChars <= 0xFFFF) { // It's in the BMP. @@ -292,13 +293,13 @@ class _NonBmpCodePageDecoder extends Converter, String> for (var char in characters.runes) { if (i >= 256) { throw ArgumentError.value( - characters, "characters", "Must contain 256 characters"); + characters, 'characters', 'Must contain 256 characters'); } result[i++] = char; } if (i < 256) { throw ArgumentError.value( - characters, "characters", "Must contain 256 characters"); + characters, 'characters', 'Must contain 256 characters'); } return result; } @@ -320,7 +321,7 @@ class _NonBmpCodePageDecoder extends Converter, String> var buffer = Uint32List(input.length); for (var i = 0; i < input.length; i++) { var byte = input[i]; - if (byte & 0xff != byte) throw FormatException("Not a byte", input, i); + if (byte & 0xff != byte) throw FormatException('Not a byte', input, i); buffer[i] = _characters[byte]; } return String.fromCharCodes(buffer); @@ -332,8 +333,8 @@ class _BmpCodePageDecoder extends Converter, String> final String _characters; _BmpCodePageDecoder(String characters) : _characters = characters { if (characters.length != 256) { - throw ArgumentError.value(characters, "characters", - "Must contain 256 characters. Was ${characters.length}"); + throw ArgumentError.value(characters, 'characters', + 'Must contain 256 characters. Was ${characters.length}'); } } @@ -348,11 +349,11 @@ class _BmpCodePageDecoder extends Converter, String> for (var i = 0; i < count; i++) { var byte = bytes[i]; if (byte != byte & 0xff) { - throw FormatException("Not a byte value", bytes, i); + throw FormatException('Not a byte value', bytes, i); } var character = _characters.codeUnitAt(byte); if (character == 0xFFFD) { - throw FormatException("Not defined in this code page", bytes, i); + throw FormatException('Not defined in this code page', bytes, i); } codeUnits[i] = character; } @@ -412,7 +413,7 @@ class CodePageEncoder extends Converter> { Uint8List convert(String input, {int? invalidCharacter}) { if (invalidCharacter != null) { RangeError.checkValueInInterval( - invalidCharacter, 0, 255, "invalidCharacter"); + invalidCharacter, 0, 255, 'invalidCharacter'); } var count = input.length; var result = Uint8List(count); @@ -435,7 +436,7 @@ class CodePageEncoder extends Converter> { } byte = invalidCharacter ?? (throw FormatException( - "Not a character in this code page", input, offset)); + 'Not a character in this code page', input, offset)); } result[j++] = byte; } diff --git a/pkgs/convert/lib/src/fixed_datetime_formatter.dart b/pkgs/convert/lib/src/fixed_datetime_formatter.dart index 88df8414..fc0a58aa 100644 --- a/pkgs/convert/lib/src/fixed_datetime_formatter.dart +++ b/pkgs/convert/lib/src/fixed_datetime_formatter.dart @@ -26,7 +26,9 @@ /// `YYYY------MM`. When encoding a [DateTime], the non-format characters are in /// the output verbatim. /// -/// Note: this class differs from [DateFormat] in that here, the format +/// Note: this class differs from +/// [DateFormat](https://pub.dev/documentation/intl/latest/intl/DateFormat-class.html) +/// from [package:intl](https://pub.dev/packages/intl) in that here, the format /// character count is interpreted literally. For example, using the format /// string `YYY` to decode the string `996` would result in the same [DateTime] /// as calling `DateTime(996)`, and the same format string used to encode the @@ -103,7 +105,7 @@ class FixedDateTimeFormatter { /// Converts a [DateTime] to a [String] as specified by the [pattern]. /// - /// The [dateTime.year] must not be negative. + /// The [DateTime.year] must not be negative. String encode(DateTime dateTime) { if (dateTime.year < 0) { throw ArgumentError.value( @@ -214,9 +216,8 @@ class FixedDateTimeFormatter { /// /// Throws a [FormatException] if the [formattedDateTime] does not match the /// [pattern]. - DateTime decode(String formattedDateTime) { - return _decode(formattedDateTime, isUtc, true)!; - } + DateTime decode(String formattedDateTime) => + _decode(formattedDateTime, isUtc, true)!; /// Parses [formattedDateTime] to a [DateTime] as specified by the [pattern]. /// @@ -225,9 +226,8 @@ class FixedDateTimeFormatter { /// /// Returns the parsed value, or `null` if the [formattedDateTime] does not /// match the [pattern]. - DateTime? tryDecode(String formattedDateTime) { - return _decode(formattedDateTime, isUtc, false); - } + DateTime? tryDecode(String formattedDateTime) => + _decode(formattedDateTime, isUtc, false); DateTime? _decode( String formattedDateTime, diff --git a/pkgs/convert/lib/src/hex.dart b/pkgs/convert/lib/src/hex.dart index 9de28edb..78aa588d 100644 --- a/pkgs/convert/lib/src/hex.dart +++ b/pkgs/convert/lib/src/hex.dart @@ -16,9 +16,7 @@ export 'hex/encoder.dart' hide hexEncoder; const hex = HexCodec._(); /// A codec that converts byte arrays to and from hexadecimal strings, following -/// [the Base16 spec][rfc]. -/// -/// [rfc]: https://tools.ietf.org/html/rfc4648#section-8 +/// [the Base16 spec](https://tools.ietf.org/html/rfc4648#section-8). /// /// This should be used via the [hex] field. class HexCodec extends Codec, String> { diff --git a/pkgs/convert/lib/src/hex/decoder.dart b/pkgs/convert/lib/src/hex/decoder.dart index 0a65f45b..466ae5c3 100644 --- a/pkgs/convert/lib/src/hex/decoder.dart +++ b/pkgs/convert/lib/src/hex/decoder.dart @@ -24,7 +24,7 @@ class HexDecoder extends Converter> { List convert(String input) { if (!input.length.isEven) { throw FormatException( - "Invalid input length, must be even.", input, input.length); + 'Invalid input length, must be even.', input, input.length); } var bytes = Uint8List(input.length ~/ 2); @@ -92,7 +92,7 @@ class _HexDecoderSink extends StringConversionSinkBase { void _close([String? string, int? index]) { if (_lastDigit != null) { throw FormatException( - "Input ended with incomplete encoded byte.", string, index); + 'Input ended with incomplete encoded byte.', string, index); } _sink.close(); @@ -152,7 +152,7 @@ class _HexDecoderByteSink extends ByteConversionSinkBase { void _close([List? chunk, int? index]) { if (_lastDigit != null) { throw FormatException( - "Input ended with incomplete encoded byte.", chunk, index); + 'Input ended with incomplete encoded byte.', chunk, index); } _sink.close(); diff --git a/pkgs/convert/lib/src/hex/encoder.dart b/pkgs/convert/lib/src/hex/encoder.dart index c45884f1..57a02a2d 100644 --- a/pkgs/convert/lib/src/hex/encoder.dart +++ b/pkgs/convert/lib/src/hex/encoder.dart @@ -86,7 +86,7 @@ String _convert(List bytes, int start, int end) { i); } - throw 'unreachable'; + throw StateError('unreachable'); } /// Returns the ASCII/Unicode code unit corresponding to the hexadecimal digit diff --git a/pkgs/convert/lib/src/percent.dart b/pkgs/convert/lib/src/percent.dart index 4a2f3770..2828b5cf 100644 --- a/pkgs/convert/lib/src/percent.dart +++ b/pkgs/convert/lib/src/percent.dart @@ -18,9 +18,8 @@ const percent = PercentCodec._(); // TODO(nweiz): Add flags to support generating and interpreting "+" as a space // character. Also add an option for custom sets of unreserved characters. /// A codec that converts byte arrays to and from percent-encoded (also known as -/// URL-encoded) strings according to [RFC 3986][rfc]. -/// -/// [rfc]: https://tools.ietf.org/html/rfc3986#section-2.1 +/// URL-encoded) strings according to +/// [RFC 3986](https://tools.ietf.org/html/rfc3986#section-2.1). /// /// [encoder] encodes all bytes other than ASCII letters, decimal digits, or one /// of `-._~`. This matches the behavior of [Uri.encodeQueryComponent] except diff --git a/pkgs/convert/lib/src/percent/decoder.dart b/pkgs/convert/lib/src/percent/decoder.dart index d74ae9ce..1a4b0e89 100644 --- a/pkgs/convert/lib/src/percent/decoder.dart +++ b/pkgs/convert/lib/src/percent/decoder.dart @@ -35,7 +35,7 @@ class PercentDecoder extends Converter> { if (lastDigit != null) { throw FormatException( - "Input ended with incomplete encoded byte.", input, input.length); + 'Input ended with incomplete encoded byte.', input, input.length); } return buffer.buffer.asUint8List(0, buffer.length); @@ -106,7 +106,7 @@ class _PercentDecoderSink extends StringConversionSinkBase { void _close([String? string, int? index]) { if (_lastDigit != null) { throw FormatException( - "Input ended with incomplete encoded byte.", string, index); + 'Input ended with incomplete encoded byte.', string, index); } _sink.close(); @@ -171,17 +171,17 @@ class _PercentDecoderByteSink extends ByteConversionSinkBase { void _close([List? chunk, int? index]) { if (_lastDigit != null) { throw FormatException( - "Input ended with incomplete encoded byte.", chunk, index); + 'Input ended with incomplete encoded byte.', chunk, index); } _sink.close(); } } -/// Decodes [codeUnits] and writes the result into [destination]. +/// Decodes [codeUnits] and writes the result into [buffer]. /// -/// This reads from [codeUnits] between [sourceStart] and [sourceEnd]. It writes -/// the result into [destination] starting at [destinationStart]. +/// This reads from [codeUnits] between [start] and [end]. It writes +/// the result into [buffer] starting at [end]. /// /// If there's a leftover digit at the end of the decoding, this returns that /// digit. Otherwise it returns `null`. @@ -244,7 +244,7 @@ void _checkForInvalidCodeUnit( var codeUnit = codeUnits[i]; if (codeUnit >= 0 && codeUnit <= 0x7f) continue; throw FormatException( - "Non-ASCII code unit " + 'Non-ASCII code unit ' "U+${codeUnit.toRadixString(16).padLeft(4, '0')}", codeUnits, i); diff --git a/pkgs/convert/lib/src/percent/encoder.dart b/pkgs/convert/lib/src/percent/encoder.dart index 7f14fc93..382e7703 100644 --- a/pkgs/convert/lib/src/percent/encoder.dart +++ b/pkgs/convert/lib/src/percent/encoder.dart @@ -13,7 +13,7 @@ const percentEncoder = PercentEncoder._(); /// A converter that encodes byte arrays into percent-encoded strings. /// -/// [encoder] encodes all bytes other than ASCII letters, decimal digits, or one +/// Encodes all bytes other than ASCII letters, decimal digits, or one /// of `-._~`. This matches the behavior of [Uri.encodeQueryComponent] except /// that it doesn't encode `0x20` bytes to the `+` character. /// @@ -103,7 +103,7 @@ String _convert(List bytes, int start, int end) { i); } - throw 'unreachable'; + throw StateError('unreachable'); } /// Returns the ASCII/Unicode code unit corresponding to the hexadecimal digit diff --git a/pkgs/convert/lib/src/utils.dart b/pkgs/convert/lib/src/utils.dart index ff2c2957..c70aebe7 100644 --- a/pkgs/convert/lib/src/utils.dart +++ b/pkgs/convert/lib/src/utils.dart @@ -7,7 +7,7 @@ library convert.utils; import 'charcodes.dart'; /// Returns the digit (0 through 15) corresponding to the hexadecimal code unit -/// at index [i] in [codeUnits]. +/// at index [index] in [codeUnits]. /// /// If the given code unit isn't valid hexadecimal, throws a [FormatException]. int digitForCodeUnit(List codeUnits, int index) { @@ -32,7 +32,7 @@ int digitForCodeUnit(List codeUnits, int index) { } throw FormatException( - "Invalid hexadecimal code unit " + 'Invalid hexadecimal code unit ' "U+${codeUnit.toRadixString(16).padLeft(4, '0')}.", codeUnits, index); diff --git a/pkgs/convert/pubspec.yaml b/pkgs/convert/pubspec.yaml index 693dbc53..e4e2d3dd 100644 --- a/pkgs/convert/pubspec.yaml +++ b/pkgs/convert/pubspec.yaml @@ -1,17 +1,17 @@ name: convert -version: 3.1.0 +version: 3.1.1 description: >- Utilities for converting between data representations. Provides a number of Sink, Codec, Decoder, and Encoder types. repository: https://github.com/dart-lang/convert environment: - sdk: '>=2.12.0 <3.0.0' + sdk: '>=2.18.0 <3.0.0' dependencies: typed_data: ^1.3.0 dev_dependencies: - lints: ^1.0.0 - test: ^1.17.0 benchmark_harness: ^2.2.0 + lints: ^2.0.0 + test: ^1.17.0 diff --git a/pkgs/convert/test/accumulator_sink_test.dart b/pkgs/convert/test/accumulator_sink_test.dart index 1f0b2041..6842d1c9 100644 --- a/pkgs/convert/test/accumulator_sink_test.dart +++ b/pkgs/convert/test/accumulator_sink_test.dart @@ -6,7 +6,7 @@ import 'package:convert/convert.dart'; import 'package:test/test.dart'; void main() { - late AccumulatorSink sink; + late AccumulatorSink sink; setUp(() { sink = AccumulatorSink(); }); @@ -24,7 +24,7 @@ void main() { expect(sink.events, equals([1, 2, 3])); }); - test("clear() clears the events", () { + test('clear() clears the events', () { sink ..add(1) ..add(2) @@ -41,7 +41,7 @@ void main() { expect(sink.events, equals([4, 5, 6])); }); - test("indicates whether the sink is closed", () { + test('indicates whether the sink is closed', () { expect(sink.isClosed, isFalse); sink.close(); expect(sink.isClosed, isTrue); diff --git a/pkgs/convert/test/byte_accumulator_sink_test.dart b/pkgs/convert/test/byte_accumulator_sink_test.dart index 773a0bed..8398ae24 100644 --- a/pkgs/convert/test/byte_accumulator_sink_test.dart +++ b/pkgs/convert/test/byte_accumulator_sink_test.dart @@ -11,7 +11,7 @@ void main() { sink = ByteAccumulatorSink(); }); - test("provides access to the concatenated bytes", () { + test('provides access to the concatenated bytes', () { expect(sink.bytes, isEmpty); sink.add([1, 2, 3]); @@ -21,7 +21,7 @@ void main() { expect(sink.bytes, equals([1, 2, 3, 5, 6, 7])); }); - test("clear() clears the bytes", () { + test('clear() clears the bytes', () { sink.add([1, 2, 3]); expect(sink.bytes, equals([1, 2, 3])); @@ -32,13 +32,13 @@ void main() { expect(sink.bytes, equals([4, 5, 6])); }); - test("indicates whether the sink is closed", () { + test('indicates whether the sink is closed', () { expect(sink.isClosed, isFalse); sink.close(); expect(sink.isClosed, isTrue); }); - test("indicates whether the sink is closed via addSlice", () { + test('indicates whether the sink is closed via addSlice', () { expect(sink.isClosed, isFalse); sink.addSlice([], 0, 0, true); expect(sink.isClosed, isTrue); diff --git a/pkgs/convert/test/codepage_test.dart b/pkgs/convert/test/codepage_test.dart index e93ef30b..c0fa45f0 100644 --- a/pkgs/convert/test/codepage_test.dart +++ b/pkgs/convert/test/codepage_test.dart @@ -25,7 +25,7 @@ void main() { latinThai, latinArabic ]) { - test("${cp.name} codepage", () { + test('${cp.name} codepage', () { // All ASCII compatible. for (var byte = 0x20; byte < 0x7f; byte++) { expect(cp[byte], byte); @@ -45,30 +45,31 @@ void main() { String.fromCharCodes([for (var i = 0; i < 256; i++) cp[i]])); }); } - test("latin-2 roundtrip", () { + test('latin-2 roundtrip', () { // Data from http://www.columbia.edu/kermit/latin2.html - var latin2text = - "\xa0Ą˘Ł¤ĽŚ§¨ŠŞŤŹ\xadŽŻ°ą˛ł´ľśˇ¸šşťź˝žżŔÁÂĂÄĹĆÇČÉĘËĚÍÎĎĐŃŇÓÔŐÖ×ŘŮÚŰÜÝŢßŕáâăäĺćçčéęëěíîďđńňóôőö÷řůúűüýţ˙"; + var latin2text = '\xa0Ą˘Ł¤ĽŚ§¨ŠŞŤŹ\xadŽŻ°ą˛ł´ľśˇ¸šşťź˝žżŔÁÂĂÄĹĆÇČÉĘËĚÍÎĎĐŃŇ' + 'ÓÔŐÖ×ŘŮÚŰÜÝŢßŕáâăäĺćçčéęëěíîďđńňóôőö÷řůúűüýţ˙'; expect(latin2.decode(latin2.encode(latin2text)), latin2text); }); - test("latin-3 roundtrip", () { + test('latin-3 roundtrip', () { // Data from http://www.columbia.edu/kermit/latin3.html - var latin2text = - "\xa0Ħ˘£¤\u{FFFD}Ĥ§¨İŞĞĴ\xad\u{FFFD}Ż°ħ²³´µĥ·¸ışğĵ½\u{FFFD}żÀÁÂ\u{FFFD}ÄĊĈÇÈÉÊËÌÍÎÏ\u{FFFD}ÑÒÓÔĠÖ×ĜÙÚÛÜŬŜßàáâ\u{FFFD}äċĉçèéêëìíîï\u{FFFD}ñòóôġö÷ĝùúûüŭŝ˙"; + var latin2text = '\xa0Ħ˘£¤\u{FFFD}Ĥ§¨İŞĞĴ\xad\u{FFFD}Ż°ħ²³´µĥ·¸ışğĵ½' + '\u{FFFD}żÀÁÂ\u{FFFD}ÄĊĈÇÈÉÊËÌÍÎÏ\u{FFFD}ÑÒÓÔĠÖ×ĜÙÚÛÜŬŜßàáâ' + '\u{FFFD}äċĉçèéêëìíîï\u{FFFD}ñòóôġö÷ĝùúûüŭŝ˙'; var encoded = latin3.encode(latin2text, invalidCharacter: 0); var decoded = latin3.decode(encoded, allowInvalid: true); expect(decoded, latin2text); }); - test("Custom code page", () { - var cp = CodePage("custom", "ABCDEF" + "\uFFFD" * 250); - var result = cp.encode("BADCAFE"); + test('Custom code page', () { + var cp = CodePage('custom', "ABCDEF${"\uFFFD" * 250}"); + var result = cp.encode('BADCAFE'); expect(result, [1, 0, 3, 2, 0, 5, 4]); - expect(() => cp.encode("GAD"), throwsFormatException); - expect(cp.encode("GAD", invalidCharacter: 0x3F), [0x3F, 0, 3]); - expect(cp.decode([1, 0, 3, 2, 0, 5, 4]), "BADCAFE"); + expect(() => cp.encode('GAD'), throwsFormatException); + expect(cp.encode('GAD', invalidCharacter: 0x3F), [0x3F, 0, 3]); + expect(cp.decode([1, 0, 3, 2, 0, 5, 4]), 'BADCAFE'); expect(() => cp.decode([6, 1, 255]), throwsFormatException); - expect(cp.decode([6, 1, 255], allowInvalid: true), "\u{FFFD}B\u{FFFD}"); + expect(cp.decode([6, 1, 255], allowInvalid: true), '\u{FFFD}B\u{FFFD}'); }); } diff --git a/pkgs/convert/test/fixed_datetime_formatter_test.dart b/pkgs/convert/test/fixed_datetime_formatter_test.dart index fdba7beb..30e7ca91 100644 --- a/pkgs/convert/test/fixed_datetime_formatter_test.dart +++ b/pkgs/convert/test/fixed_datetime_formatter_test.dart @@ -6,9 +6,9 @@ import 'package:convert/src/fixed_datetime_formatter.dart'; import 'package:test/test.dart'; void main() { - DateTime noFractionalSeconds = DateTime.utc(0, 1, 1, 0, 0, 0); - Map skipWeb = { - 'js': Skip( + var noFractionalSeconds = DateTime.utc(0); + var skipWeb = { + 'js': const Skip( 'Web does not support microseconds (see https://github.com/dart-lang/sdk/issues/44876)') }; // Testing `decode`. @@ -18,7 +18,7 @@ void main() { }); test('Escaped chars are ignored', () { var time = FixedDateTimeFormatter('YYYY kiwi MM').decode('1996 rnad 01'); - expect(time, DateTime.utc(1996, 1)); + expect(time, DateTime.utc(1996)); }); test('Parse two years throws', () { expect(() => FixedDateTimeFormatter('YYYY YYYY'), throwsException); @@ -51,29 +51,29 @@ void main() { }); test('Parse S 1/10 of a second', () { var time = FixedDateTimeFormatter('S').decode('1'); - expect(time, noFractionalSeconds.add(Duration(milliseconds: 100))); + expect(time, noFractionalSeconds.add(const Duration(milliseconds: 100))); }); test('Parse SS 1/100 of a second', () { var time = FixedDateTimeFormatter('SS').decode('01'); - expect(time, noFractionalSeconds.add(Duration(milliseconds: 10))); + expect(time, noFractionalSeconds.add(const Duration(milliseconds: 10))); }); test('Parse SSS a millisecond', () { var time = FixedDateTimeFormatter('SSS').decode('001'); - expect(time, noFractionalSeconds.add(Duration(milliseconds: 1))); + expect(time, noFractionalSeconds.add(const Duration(milliseconds: 1))); }); test('Parse SSSSSS a microsecond', () { var time = FixedDateTimeFormatter('SSSSSS').decode('000001'); - expect(time, noFractionalSeconds.add(Duration(microseconds: 1))); + expect(time, noFractionalSeconds.add(const Duration(microseconds: 1))); }, onPlatform: skipWeb); test('Parse SSSSSS a millisecond', () { var time = FixedDateTimeFormatter('SSSSSS').decode('001000'); - expect(time, noFractionalSeconds.add(Duration(milliseconds: 1))); + expect(time, noFractionalSeconds.add(const Duration(milliseconds: 1))); }); test('Parse SSSSSS a millisecond and a microsecond', () { var time = FixedDateTimeFormatter('SSSSSS').decode('001001'); expect( time, - noFractionalSeconds.add(Duration( + noFractionalSeconds.add(const Duration( milliseconds: 1, microseconds: 1, ))); @@ -82,7 +82,7 @@ void main() { var time = FixedDateTimeFormatter('ssSSSSSS').decode('01000001'); expect( time, - noFractionalSeconds.add(Duration( + noFractionalSeconds.add(const Duration( seconds: 1, microseconds: 1, ))); @@ -120,7 +120,7 @@ void main() { }); // Testing `encode`. test('Format simple', () { - var time = DateTime.utc(1996, 1); + var time = DateTime.utc(1996); expect(FixedDateTimeFormatter('YYYY kiwi MM').encode(time), '1996 kiwi 01'); }); test('Format YYYYMMDDhhmmss', () { @@ -140,17 +140,17 @@ void main() { }); test('Format S 1/10 of a second', () { var str = FixedDateTimeFormatter('S') - .encode(noFractionalSeconds.add(Duration(milliseconds: 100))); + .encode(noFractionalSeconds.add(const Duration(milliseconds: 100))); expect(str, '1'); }); test('Format SS 1/100 of a second', () { var str = FixedDateTimeFormatter('SS') - .encode(noFractionalSeconds.add(Duration(milliseconds: 10))); + .encode(noFractionalSeconds.add(const Duration(milliseconds: 10))); expect(str, '01'); }); test('Format SSS 1/100 of a second', () { var str = FixedDateTimeFormatter('SSS') - .encode(noFractionalSeconds.add(Duration(milliseconds: 10))); + .encode(noFractionalSeconds.add(const Duration(milliseconds: 10))); expect(str, '010'); }); test('Format SSSS no fractions', () { @@ -163,17 +163,17 @@ void main() { }); test('Format SSSS 1/10 of a second', () { var str = FixedDateTimeFormatter('SSSS') - .encode(noFractionalSeconds.add(Duration(milliseconds: 100))); + .encode(noFractionalSeconds.add(const Duration(milliseconds: 100))); expect(str, '1000'); }); test('Format SSSS 1/100 of a second', () { var str = FixedDateTimeFormatter('SSSS') - .encode(noFractionalSeconds.add(Duration(milliseconds: 10))); + .encode(noFractionalSeconds.add(const Duration(milliseconds: 10))); expect(str, '0100'); }); test('Format SSSS a millisecond', () { var str = FixedDateTimeFormatter('SSSS') - .encode(noFractionalSeconds.add(Duration(milliseconds: 1))); + .encode(noFractionalSeconds.add(const Duration(milliseconds: 1))); expect(str, '0010'); }); test('Format SSSSSS a microsecond', () { @@ -182,7 +182,7 @@ void main() { expect(str, '000001'); }, onPlatform: skipWeb); test('Format SSSSSS a millisecond and a microsecond', () { - var dateTime = noFractionalSeconds.add(Duration( + var dateTime = noFractionalSeconds.add(const Duration( milliseconds: 1, microseconds: 1, )); @@ -191,16 +191,16 @@ void main() { }, onPlatform: skipWeb); test('Format SSSSSS0 a microsecond', () { var str = FixedDateTimeFormatter('SSSSSS0') - .encode(noFractionalSeconds.add(Duration(microseconds: 1))); + .encode(noFractionalSeconds.add(const Duration(microseconds: 1))); expect(str, '0000010'); }, onPlatform: skipWeb); test('Format SSSSSS0 1/10 of a second', () { var str = FixedDateTimeFormatter('SSSSSS0') - .encode(noFractionalSeconds.add(Duration(milliseconds: 100))); + .encode(noFractionalSeconds.add(const Duration(milliseconds: 100))); expect(str, '1000000'); }); test('Parse ssSSSSSS a second and a microsecond', () { - var dateTime = noFractionalSeconds.add(Duration( + var dateTime = noFractionalSeconds.add(const Duration( seconds: 1, microseconds: 1, )); @@ -208,7 +208,7 @@ void main() { expect(str, '01000001'); }, onPlatform: skipWeb); test('Parse ssSSSSSS0 a second and a microsecond', () { - var dateTime = noFractionalSeconds.add(Duration( + var dateTime = noFractionalSeconds.add(const Duration( seconds: 1, microseconds: 1, )); diff --git a/pkgs/convert/test/hex_test.dart b/pkgs/convert/test/hex_test.dart index 5e8fa28e..7632cb18 100644 --- a/pkgs/convert/test/hex_test.dart +++ b/pkgs/convert/test/hex_test.dart @@ -9,44 +9,44 @@ import 'package:convert/convert.dart'; import 'package:test/test.dart'; void main() { - group("encoder", () { - test("converts byte arrays to hex", () { - expect(hex.encode([0x1a, 0xb2, 0x3c, 0xd4]), equals("1ab23cd4")); - expect(hex.encode([0x00, 0x01, 0xfe, 0xff]), equals("0001feff")); + group('encoder', () { + test('converts byte arrays to hex', () { + expect(hex.encode([0x1a, 0xb2, 0x3c, 0xd4]), equals('1ab23cd4')); + expect(hex.encode([0x00, 0x01, 0xfe, 0xff]), equals('0001feff')); }); - group("with chunked conversion", () { - test("converts byte arrays to hex", () { + group('with chunked conversion', () { + test('converts byte arrays to hex', () { var results = []; var controller = StreamController(sync: true); controller.stream.listen(results.add); var sink = hex.encoder.startChunkedConversion(controller.sink); sink.add([0x1a, 0xb2, 0x3c, 0xd4]); - expect(results, equals(["1ab23cd4"])); + expect(results, equals(['1ab23cd4'])); sink.add([0x00, 0x01, 0xfe, 0xff]); - expect(results, equals(["1ab23cd4", "0001feff"])); + expect(results, equals(['1ab23cd4', '0001feff'])); }); - test("handles empty and single-byte lists", () { + test('handles empty and single-byte lists', () { var results = []; var controller = StreamController(sync: true); controller.stream.listen(results.add); var sink = hex.encoder.startChunkedConversion(controller.sink); sink.add([]); - expect(results, equals([""])); + expect(results, equals([''])); sink.add([0x00]); - expect(results, equals(["", "00"])); + expect(results, equals(['', '00'])); sink.add([]); - expect(results, equals(["", "00", ""])); + expect(results, equals(['', '00', ''])); }); }); - test("rejects non-bytes", () { + test('rejects non-bytes', () { expect(() => hex.encode([0x100]), throwsFormatException); var sink = @@ -55,15 +55,15 @@ void main() { }); }); - group("decoder", () { - test("converts hex to byte arrays", () { - expect(hex.decode("1ab23cd4"), equals([0x1a, 0xb2, 0x3c, 0xd4])); - expect(hex.decode("0001feff"), equals([0x00, 0x01, 0xfe, 0xff])); + group('decoder', () { + test('converts hex to byte arrays', () { + expect(hex.decode('1ab23cd4'), equals([0x1a, 0xb2, 0x3c, 0xd4])); + expect(hex.decode('0001feff'), equals([0x00, 0x01, 0xfe, 0xff])); }); - test("supports uppercase letters", () { + test('supports uppercase letters', () { expect( - hex.decode("0123456789ABCDEFabcdef"), + hex.decode('0123456789ABCDEFabcdef'), equals([ 0x01, 0x23, @@ -79,7 +79,7 @@ void main() { ])); }); - group("with chunked conversion", () { + group('with chunked conversion', () { late List> results; late StringConversionSink sink; setUp(() { @@ -89,15 +89,15 @@ void main() { sink = hex.decoder.startChunkedConversion(controller.sink); }); - test("converts hex to byte arrays", () { - sink.add("1ab23cd4"); + test('converts hex to byte arrays', () { + sink.add('1ab23cd4'); expect( results, equals([ [0x1a, 0xb2, 0x3c, 0xd4] ])); - sink.add("0001feff"); + sink.add('0001feff'); expect( results, equals([ @@ -106,15 +106,15 @@ void main() { ])); }); - test("supports trailing digits split across chunks", () { - sink.add("1ab23"); + test('supports trailing digits split across chunks', () { + sink.add('1ab23'); expect( results, equals([ [0x1a, 0xb2] ])); - sink.add("cd"); + sink.add('cd'); expect( results, equals([ @@ -122,7 +122,7 @@ void main() { [0x3c] ])); - sink.add("40001"); + sink.add('40001'); expect( results, equals([ @@ -131,7 +131,7 @@ void main() { [0xd4, 0x00, 0x01] ])); - sink.add("feff"); + sink.add('feff'); expect( results, equals([ @@ -142,17 +142,17 @@ void main() { ])); }); - test("supports empty strings", () { - sink.add(""); + test('supports empty strings', () { + sink.add(''); expect(results, isEmpty); - sink.add("0"); + sink.add('0'); expect(results, equals([[]])); - sink.add(""); + sink.add(''); expect(results, equals([[]])); - sink.add("0"); + sink.add('0'); expect( results, equals([ @@ -160,7 +160,7 @@ void main() { [0x00] ])); - sink.add(""); + sink.add(''); expect( results, equals([ @@ -169,8 +169,8 @@ void main() { ])); }); - test("rejects odd length detected in close()", () { - sink.add("1ab23"); + test('rejects odd length detected in close()', () { + sink.add('1ab23'); expect( results, equals([ @@ -179,8 +179,8 @@ void main() { expect(() => sink.close(), throwsFormatException); }); - test("rejects odd length detected in addSlice()", () { - sink.addSlice("1ab23cd", 0, 5, false); + test('rejects odd length detected in addSlice()', () { + sink.addSlice('1ab23cd', 0, 5, false); expect( results, equals([ @@ -188,25 +188,25 @@ void main() { ])); expect( - () => sink.addSlice("1ab23cd", 5, 7, true), throwsFormatException); + () => sink.addSlice('1ab23cd', 5, 7, true), throwsFormatException); }); }); - group("rejects non-hex character", () { + group('rejects non-hex character', () { for (var char in [ - "g", - "G", - "/", - ":", - "@", - "`", - "\x00", - "\u0141", - "\u{10041}" + 'g', + 'G', + '/', + ':', + '@', + '`', + '\x00', + '\u0141', + '\u{10041}' ]) { test('"$char"', () { - expect(() => hex.decode("a$char"), throwsFormatException); - expect(() => hex.decode("${char}a"), throwsFormatException); + expect(() => hex.decode('a$char'), throwsFormatException); + expect(() => hex.decode('${char}a'), throwsFormatException); var sink = hex.decoder.startChunkedConversion(StreamController(sync: true)); @@ -215,8 +215,8 @@ void main() { } }); - test("rejects odd length detected in convert()", () { - expect(() => hex.decode("1ab23cd"), throwsFormatException); + test('rejects odd length detected in convert()', () { + expect(() => hex.decode('1ab23cd'), throwsFormatException); }); }); } diff --git a/pkgs/convert/test/identity_codec_test.dart b/pkgs/convert/test/identity_codec_test.dart index 658027a5..51a3a21b 100644 --- a/pkgs/convert/test/identity_codec_test.dart +++ b/pkgs/convert/test/identity_codec_test.dart @@ -5,17 +5,17 @@ import 'package:test/test.dart'; void main() { group('IdentityCodec', () { test('encode', () { - final codec = IdentityCodec(); + const codec = IdentityCodec(); expect(codec.encode('hello-world'), equals('hello-world')); }); test('decode', () { - final codec = IdentityCodec(); + const codec = IdentityCodec(); expect(codec.decode('hello-world'), equals('hello-world')); }); test('fuse', () { - final stringCodec = IdentityCodec(); + const stringCodec = IdentityCodec(); final utf8Strings = stringCodec.fuse(utf8); expect(utf8Strings, equals(utf8)); }); diff --git a/pkgs/convert/test/percent_test.dart b/pkgs/convert/test/percent_test.dart index 9075ea11..cc74a69e 100644 --- a/pkgs/convert/test/percent_test.dart +++ b/pkgs/convert/test/percent_test.dart @@ -9,59 +9,59 @@ import 'package:convert/convert.dart'; import 'package:test/test.dart'; void main() { - group("encoder", () { + group('encoder', () { test("doesn't percent-encode unreserved characters", () { - var safeChars = "abcdefghijklmnopqrstuvwxyz" - "ABCDEFGHIJKLMNOPQRSTUVWXYZ" - "0123456789-._~"; + var safeChars = 'abcdefghijklmnopqrstuvwxyz' + 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' + '0123456789-._~'; expect(percent.encode([...safeChars.codeUnits]), equals(safeChars)); }); - test("percent-encodes reserved ASCII characters", () { - expect(percent.encode([..." `{@[,/^}\x7f\x00%".codeUnits]), - equals("%20%60%7B%40%5B%2C%2F%5E%7D%7F%00%25")); + test('percent-encodes reserved ASCII characters', () { + expect(percent.encode([...' `{@[,/^}\x7f\x00%'.codeUnits]), + equals('%20%60%7B%40%5B%2C%2F%5E%7D%7F%00%25')); }); - test("percent-encodes non-ASCII characters", () { - expect(percent.encode([0x80, 0xFF]), equals("%80%FF")); + test('percent-encodes non-ASCII characters', () { + expect(percent.encode([0x80, 0xFF]), equals('%80%FF')); }); - test("mixes encoded and unencoded characters", () { - expect(percent.encode([..."a+b=\x80".codeUnits]), equals("a%2Bb%3D%80")); + test('mixes encoded and unencoded characters', () { + expect(percent.encode([...'a+b=\x80'.codeUnits]), equals('a%2Bb%3D%80')); }); - group("with chunked conversion", () { - test("percent-encodes byte arrays", () { + group('with chunked conversion', () { + test('percent-encodes byte arrays', () { var results = []; var controller = StreamController(sync: true); controller.stream.listen(results.add); var sink = percent.encoder.startChunkedConversion(controller.sink); - sink.add([..."a+b=\x80".codeUnits]); - expect(results, equals(["a%2Bb%3D%80"])); + sink.add([...'a+b=\x80'.codeUnits]); + expect(results, equals(['a%2Bb%3D%80'])); sink.add([0x00, 0x01, 0xfe, 0xff]); - expect(results, equals(["a%2Bb%3D%80", "%00%01%FE%FF"])); + expect(results, equals(['a%2Bb%3D%80', '%00%01%FE%FF'])); }); - test("handles empty and single-byte lists", () { + test('handles empty and single-byte lists', () { var results = []; var controller = StreamController(sync: true); controller.stream.listen(results.add); var sink = percent.encoder.startChunkedConversion(controller.sink); sink.add([]); - expect(results, equals([""])); + expect(results, equals([''])); sink.add([0x00]); - expect(results, equals(["", "%00"])); + expect(results, equals(['', '%00'])); sink.add([]); - expect(results, equals(["", "%00", ""])); + expect(results, equals(['', '%00', ''])); }); }); - test("rejects non-bytes", () { + test('rejects non-bytes', () { expect(() => percent.encode([0x100]), throwsFormatException); var sink = @@ -70,26 +70,26 @@ void main() { }); }); - group("decoder", () { - test("converts percent-encoded strings to byte arrays", () { + group('decoder', () { + test('converts percent-encoded strings to byte arrays', () { expect( - percent.decode("a%2Bb%3D%801"), equals([..."a+b=\x801".codeUnits])); + percent.decode('a%2Bb%3D%801'), equals([...'a+b=\x801'.codeUnits])); }); - test("supports lowercase letters", () { - expect(percent.decode("a%2bb%3d%80"), equals([..."a+b=\x80".codeUnits])); + test('supports lowercase letters', () { + expect(percent.decode('a%2bb%3d%80'), equals([...'a+b=\x80'.codeUnits])); }); - test("supports more aggressive encoding", () { - expect(percent.decode("%61%2E%5A"), equals([..."a.Z".codeUnits])); + test('supports more aggressive encoding', () { + expect(percent.decode('%61%2E%5A'), equals([...'a.Z'.codeUnits])); }); - test("supports less aggressive encoding", () { - var chars = " `{@[,/^}\x7F\x00"; + test('supports less aggressive encoding', () { + var chars = ' `{@[,/^}\x7F\x00'; expect(percent.decode(chars), equals([...chars.codeUnits])); }); - group("with chunked conversion", () { + group('with chunked conversion', () { late List> results; late StringConversionSink sink; setUp(() { @@ -99,73 +99,73 @@ void main() { sink = percent.decoder.startChunkedConversion(controller.sink); }); - test("converts percent to byte arrays", () { - sink.add("a%2Bb%3D%801"); + test('converts percent to byte arrays', () { + sink.add('a%2Bb%3D%801'); expect( results, equals([ - [..."a+b=\x801".codeUnits] + [...'a+b=\x801'.codeUnits] ])); - sink.add("%00%01%FE%FF"); + sink.add('%00%01%FE%FF'); expect( results, equals([ - [..."a+b=\x801".codeUnits], + [...'a+b=\x801'.codeUnits], [0x00, 0x01, 0xfe, 0xff] ])); }); - test("supports trailing percents and digits split across chunks", () { - sink.add("ab%"); + test('supports trailing percents and digits split across chunks', () { + sink.add('ab%'); expect( results, equals([ - [..."ab".codeUnits] + [...'ab'.codeUnits] ])); - sink.add("2"); + sink.add('2'); expect( results, equals([ - [..."ab".codeUnits] + [...'ab'.codeUnits] ])); - sink.add("0cd%2"); + sink.add('0cd%2'); expect( results, equals([ - [..."ab".codeUnits], - [..." cd".codeUnits] + [...'ab'.codeUnits], + [...' cd'.codeUnits] ])); - sink.add("0"); + sink.add('0'); expect( results, - equals(([ - [..."ab".codeUnits], - [..." cd".codeUnits], - [..." ".codeUnits] - ]))); + equals([ + [...'ab'.codeUnits], + [...' cd'.codeUnits], + [...' '.codeUnits] + ])); }); - test("supports empty strings", () { - sink.add(""); + test('supports empty strings', () { + sink.add(''); expect(results, isEmpty); - sink.add("%"); + sink.add('%'); expect(results, equals([[]])); - sink.add(""); + sink.add(''); expect(results, equals([[]])); - sink.add("2"); + sink.add('2'); expect(results, equals([[]])); - sink.add(""); + sink.add(''); expect(results, equals([[]])); - sink.add("0"); + sink.add('0'); expect( results, equals([ @@ -174,54 +174,54 @@ void main() { ])); }); - test("rejects dangling % detected in close()", () { - sink.add("ab%"); + test('rejects dangling % detected in close()', () { + sink.add('ab%'); expect( results, equals([ - [..."ab".codeUnits] + [...'ab'.codeUnits] ])); expect(() => sink.close(), throwsFormatException); }); - test("rejects dangling digit detected in close()", () { - sink.add("ab%2"); + test('rejects dangling digit detected in close()', () { + sink.add('ab%2'); expect( results, equals([ - [..."ab".codeUnits] + [...'ab'.codeUnits] ])); expect(() => sink.close(), throwsFormatException); }); - test("rejects danging % detected in addSlice()", () { - sink.addSlice("ab%", 0, 3, false); + test('rejects danging % detected in addSlice()', () { + sink.addSlice('ab%', 0, 3, false); expect( results, equals([ - [..."ab".codeUnits] + [...'ab'.codeUnits] ])); - expect(() => sink.addSlice("ab%", 0, 3, true), throwsFormatException); + expect(() => sink.addSlice('ab%', 0, 3, true), throwsFormatException); }); - test("rejects danging digit detected in addSlice()", () { - sink.addSlice("ab%2", 0, 3, false); + test('rejects danging digit detected in addSlice()', () { + sink.addSlice('ab%2', 0, 3, false); expect( results, equals([ - [..."ab".codeUnits] + [...'ab'.codeUnits] ])); - expect(() => sink.addSlice("ab%2", 0, 3, true), throwsFormatException); + expect(() => sink.addSlice('ab%2', 0, 3, true), throwsFormatException); }); }); - group("rejects non-ASCII character", () { - for (var char in ["\u0141", "\u{10041}"]) { + group('rejects non-ASCII character', () { + for (var char in ['\u0141', '\u{10041}']) { test('"$char"', () { - expect(() => percent.decode("a$char"), throwsFormatException); - expect(() => percent.decode("${char}a"), throwsFormatException); + expect(() => percent.decode('a$char'), throwsFormatException); + expect(() => percent.decode('${char}a'), throwsFormatException); var sink = percent.decoder .startChunkedConversion(StreamController(sync: true)); @@ -230,17 +230,17 @@ void main() { } }); - test("rejects % followed by non-hex", () { - expect(() => percent.decode("%z2"), throwsFormatException); - expect(() => percent.decode("%2z"), throwsFormatException); + test('rejects % followed by non-hex', () { + expect(() => percent.decode('%z2'), throwsFormatException); + expect(() => percent.decode('%2z'), throwsFormatException); }); - test("rejects dangling % detected in convert()", () { - expect(() => percent.decode("ab%"), throwsFormatException); + test('rejects dangling % detected in convert()', () { + expect(() => percent.decode('ab%'), throwsFormatException); }); - test("rejects dangling digit detected in convert()", () { - expect(() => percent.decode("ab%2"), throwsFormatException); + test('rejects dangling digit detected in convert()', () { + expect(() => percent.decode('ab%2'), throwsFormatException); }); }); } diff --git a/pkgs/convert/test/string_accumulator_sink_test.dart b/pkgs/convert/test/string_accumulator_sink_test.dart index 6c5b9faa..8e3b7cb5 100644 --- a/pkgs/convert/test/string_accumulator_sink_test.dart +++ b/pkgs/convert/test/string_accumulator_sink_test.dart @@ -11,46 +11,46 @@ void main() { sink = StringAccumulatorSink(); }); - test("provides access to the concatenated string", () { + test('provides access to the concatenated string', () { expect(sink.string, isEmpty); - sink.add("foo"); - expect(sink.string, equals("foo")); + sink.add('foo'); + expect(sink.string, equals('foo')); - sink.addSlice(" bar baz", 1, 4, false); - expect(sink.string, equals("foobar")); + sink.addSlice(' bar baz', 1, 4, false); + expect(sink.string, equals('foobar')); }); - test("clear() clears the string", () { - sink.add("foo"); - expect(sink.string, equals("foo")); + test('clear() clears the string', () { + sink.add('foo'); + expect(sink.string, equals('foo')); sink.clear(); expect(sink.string, isEmpty); - sink.add("bar"); - expect(sink.string, equals("bar")); + sink.add('bar'); + expect(sink.string, equals('bar')); }); - test("indicates whether the sink is closed", () { + test('indicates whether the sink is closed', () { expect(sink.isClosed, isFalse); sink.close(); expect(sink.isClosed, isTrue); }); - test("indicates whether the sink is closed via addSlice", () { + test('indicates whether the sink is closed via addSlice', () { expect(sink.isClosed, isFalse); - sink.addSlice("", 0, 0, true); + sink.addSlice('', 0, 0, true); expect(sink.isClosed, isTrue); }); test("doesn't allow add() to be called after close()", () { sink.close(); - expect(() => sink.add("x"), throwsStateError); + expect(() => sink.add('x'), throwsStateError); }); test("doesn't allow addSlice() to be called after close()", () { sink.close(); - expect(() => sink.addSlice("", 0, 0, false), throwsStateError); + expect(() => sink.addSlice('', 0, 0, false), throwsStateError); }); } From b0c31464c113e36f5127884555198b5ebef61603 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 3 Jan 2023 09:28:03 -0800 Subject: [PATCH 069/100] Bump actions/checkout from 3.1.0 to 3.2.0 (dart-lang/convert#73) Bumps [actions/checkout](https://github.com/actions/checkout) from 3.1.0 to 3.2.0. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8...755da8c3cf115ac066823e79a1e1788f8940201b) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pkgs/convert/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/convert/.github/workflows/test-package.yml b/pkgs/convert/.github/workflows/test-package.yml index 2bba6c64..f03c6d5c 100644 --- a/pkgs/convert/.github/workflows/test-package.yml +++ b/pkgs/convert/.github/workflows/test-package.yml @@ -22,7 +22,7 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 + - uses: actions/checkout@755da8c3cf115ac066823e79a1e1788f8940201b - uses: dart-lang/setup-dart@6a218f2413a3e78e9087f638a238f6b40893203d with: sdk: ${{ matrix.sdk }} @@ -49,7 +49,7 @@ jobs: os: [ubuntu-latest] sdk: [2.18.0, dev] steps: - - uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 + - uses: actions/checkout@755da8c3cf115ac066823e79a1e1788f8940201b - uses: dart-lang/setup-dart@6a218f2413a3e78e9087f638a238f6b40893203d with: sdk: ${{ matrix.sdk }} From 597c82b566fecbd089d4b323f45ee975476498fc Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 31 Jan 2023 23:31:55 -0800 Subject: [PATCH 070/100] Bump dart-lang/setup-dart from 1.3 to 1.4 (dart-lang/convert#74) Bumps [dart-lang/setup-dart](https://github.com/dart-lang/setup-dart) from 1.3 to 1.4. - [Release notes](https://github.com/dart-lang/setup-dart/releases) - [Changelog](https://github.com/dart-lang/setup-dart/blob/main/CHANGELOG.md) - [Commits](https://github.com/dart-lang/setup-dart/compare/6a218f2413a3e78e9087f638a238f6b40893203d...a57a6c04cf7d4840e88432aad6281d1e125f0d46) --- updated-dependencies: - dependency-name: dart-lang/setup-dart dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pkgs/convert/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/convert/.github/workflows/test-package.yml b/pkgs/convert/.github/workflows/test-package.yml index f03c6d5c..951d985f 100644 --- a/pkgs/convert/.github/workflows/test-package.yml +++ b/pkgs/convert/.github/workflows/test-package.yml @@ -23,7 +23,7 @@ jobs: sdk: [dev] steps: - uses: actions/checkout@755da8c3cf115ac066823e79a1e1788f8940201b - - uses: dart-lang/setup-dart@6a218f2413a3e78e9087f638a238f6b40893203d + - uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46 with: sdk: ${{ matrix.sdk }} - id: install @@ -50,7 +50,7 @@ jobs: sdk: [2.18.0, dev] steps: - uses: actions/checkout@755da8c3cf115ac066823e79a1e1788f8940201b - - uses: dart-lang/setup-dart@6a218f2413a3e78e9087f638a238f6b40893203d + - uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46 with: sdk: ${{ matrix.sdk }} - id: install From 43b787f8e4a7144d7c1cbe7b165edd6b0e900694 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 1 Feb 2023 07:32:44 +0000 Subject: [PATCH 071/100] Bump actions/checkout from 3.2.0 to 3.3.0 (dart-lang/convert#75) Bumps [actions/checkout](https://github.com/actions/checkout) from 3.2.0 to 3.3.0. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/755da8c3cf115ac066823e79a1e1788f8940201b...ac593985615ec2ede58e132d2e21d2b1cbd6127c) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pkgs/convert/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/convert/.github/workflows/test-package.yml b/pkgs/convert/.github/workflows/test-package.yml index 951d985f..bdf6b461 100644 --- a/pkgs/convert/.github/workflows/test-package.yml +++ b/pkgs/convert/.github/workflows/test-package.yml @@ -22,7 +22,7 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@755da8c3cf115ac066823e79a1e1788f8940201b + - uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c - uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46 with: sdk: ${{ matrix.sdk }} @@ -49,7 +49,7 @@ jobs: os: [ubuntu-latest] sdk: [2.18.0, dev] steps: - - uses: actions/checkout@755da8c3cf115ac066823e79a1e1788f8940201b + - uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c - uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46 with: sdk: ${{ matrix.sdk }} From ab9c1302c6d0f7e7a3aff486126d029e1dd6b636 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 3 Apr 2023 15:40:25 -0700 Subject: [PATCH 072/100] Bump actions/checkout from 3.3.0 to 3.5.0 (dart-lang/convert#80) Bumps [actions/checkout](https://github.com/actions/checkout) from 3.3.0 to 3.5.0. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/ac593985615ec2ede58e132d2e21d2b1cbd6127c...8f4b7f84864484a7bf31766abe9204da3cbe65b3) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pkgs/convert/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/convert/.github/workflows/test-package.yml b/pkgs/convert/.github/workflows/test-package.yml index bdf6b461..82ea6fad 100644 --- a/pkgs/convert/.github/workflows/test-package.yml +++ b/pkgs/convert/.github/workflows/test-package.yml @@ -22,7 +22,7 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c + - uses: actions/checkout@8f4b7f84864484a7bf31766abe9204da3cbe65b3 - uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46 with: sdk: ${{ matrix.sdk }} @@ -49,7 +49,7 @@ jobs: os: [ubuntu-latest] sdk: [2.18.0, dev] steps: - - uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c + - uses: actions/checkout@8f4b7f84864484a7bf31766abe9204da3cbe65b3 - uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46 with: sdk: ${{ matrix.sdk }} From 51007ee04cd8257e24ec9b2b6433924954555cbf Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 3 Apr 2023 15:57:22 -0700 Subject: [PATCH 073/100] Bump dart-lang/setup-dart from 1.4.0 to 1.5.0 (dart-lang/convert#79) Bumps [dart-lang/setup-dart](https://github.com/dart-lang/setup-dart) from 1.4.0 to 1.5.0. - [Release notes](https://github.com/dart-lang/setup-dart/releases) - [Changelog](https://github.com/dart-lang/setup-dart/blob/main/CHANGELOG.md) - [Commits](https://github.com/dart-lang/setup-dart/compare/a57a6c04cf7d4840e88432aad6281d1e125f0d46...d6a63dab3335f427404425de0fbfed4686d93c4f) --- updated-dependencies: - dependency-name: dart-lang/setup-dart dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pkgs/convert/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/convert/.github/workflows/test-package.yml b/pkgs/convert/.github/workflows/test-package.yml index 82ea6fad..fbe72cd5 100644 --- a/pkgs/convert/.github/workflows/test-package.yml +++ b/pkgs/convert/.github/workflows/test-package.yml @@ -23,7 +23,7 @@ jobs: sdk: [dev] steps: - uses: actions/checkout@8f4b7f84864484a7bf31766abe9204da3cbe65b3 - - uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46 + - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f with: sdk: ${{ matrix.sdk }} - id: install @@ -50,7 +50,7 @@ jobs: sdk: [2.18.0, dev] steps: - uses: actions/checkout@8f4b7f84864484a7bf31766abe9204da3cbe65b3 - - uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46 + - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f with: sdk: ${{ matrix.sdk }} - id: install From 90abcef549b4f1ad7804ecfe97b42f0664724b64 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Mon, 10 Apr 2023 12:37:40 -0700 Subject: [PATCH 074/100] Require Dart 2.19, fix override param name, update lints (dart-lang/convert#81) --- .../.github/workflows/test-package.yml | 2 +- pkgs/convert/CHANGELOG.md | 4 ++++ pkgs/convert/analysis_options.yaml | 19 +------------------ pkgs/convert/lib/src/hex.dart | 2 -- pkgs/convert/lib/src/hex/decoder.dart | 2 -- pkgs/convert/lib/src/hex/encoder.dart | 2 -- pkgs/convert/lib/src/percent.dart | 2 -- pkgs/convert/lib/src/percent/decoder.dart | 2 -- pkgs/convert/lib/src/percent/encoder.dart | 2 -- .../lib/src/string_accumulator_sink.dart | 4 ++-- pkgs/convert/lib/src/utils.dart | 2 -- pkgs/convert/pubspec.yaml | 6 +++--- 12 files changed, 11 insertions(+), 38 deletions(-) diff --git a/pkgs/convert/.github/workflows/test-package.yml b/pkgs/convert/.github/workflows/test-package.yml index fbe72cd5..0876594e 100644 --- a/pkgs/convert/.github/workflows/test-package.yml +++ b/pkgs/convert/.github/workflows/test-package.yml @@ -47,7 +47,7 @@ jobs: matrix: # Add macos-latest and/or windows-latest if relevant for this package. os: [ubuntu-latest] - sdk: [2.18.0, dev] + sdk: [2.19.0, dev] steps: - uses: actions/checkout@8f4b7f84864484a7bf31766abe9204da3cbe65b3 - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f diff --git a/pkgs/convert/CHANGELOG.md b/pkgs/convert/CHANGELOG.md index 923d6dab..415ade50 100644 --- a/pkgs/convert/CHANGELOG.md +++ b/pkgs/convert/CHANGELOG.md @@ -1,3 +1,7 @@ +## 3.1.2-dev + +- Require Dart 2.19 + ## 3.1.1 - Require Dart 2.18 diff --git a/pkgs/convert/analysis_options.yaml b/pkgs/convert/analysis_options.yaml index d624ccd3..6c58fa83 100644 --- a/pkgs/convert/analysis_options.yaml +++ b/pkgs/convert/analysis_options.yaml @@ -1,5 +1,5 @@ # https://dart.dev/guides/language/analysis-options -include: package:lints/recommended.yaml +include: package:dart_flutter_team_lints/analysis_options.yaml analyzer: language: @@ -8,39 +8,22 @@ analyzer: linter: rules: - - always_declare_return_types - - avoid_catching_errors - - avoid_dynamic_calls - avoid_private_typedef_functions - avoid_redundant_argument_values - avoid_unused_constructor_parameters - avoid_void_async - cancel_subscriptions - comment_references - - directives_ordering - - lines_longer_than_80_chars - literal_only_boolean_expressions - missing_whitespace_between_adjacent_strings - no_adjacent_strings_in_list - no_runtimeType_toString - - omit_local_variable_types - - only_throw_errors - package_api_docs - - prefer_asserts_in_initializer_lists - prefer_const_constructors - prefer_const_declarations - prefer_expression_function_bodies - prefer_relative_imports - - prefer_single_quotes - - sort_pub_dependencies - test_types_in_equals - - throw_in_finally - - type_annotate_public_apis - - unawaited_futures - unnecessary_await_in_return - - unnecessary_lambdas - - unnecessary_parenthesis - - unnecessary_statements - - use_is_even_rather_than_modulo - use_string_buffers - use_super_parameters diff --git a/pkgs/convert/lib/src/hex.dart b/pkgs/convert/lib/src/hex.dart index 78aa588d..f3832406 100644 --- a/pkgs/convert/lib/src/hex.dart +++ b/pkgs/convert/lib/src/hex.dart @@ -2,8 +2,6 @@ // 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. -library convert.hex; - import 'dart:convert'; import 'hex/decoder.dart'; diff --git a/pkgs/convert/lib/src/hex/decoder.dart b/pkgs/convert/lib/src/hex/decoder.dart index 466ae5c3..848a4ae4 100644 --- a/pkgs/convert/lib/src/hex/decoder.dart +++ b/pkgs/convert/lib/src/hex/decoder.dart @@ -2,8 +2,6 @@ // 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. -library convert.hex.decoder; - import 'dart:convert'; import 'dart:typed_data'; diff --git a/pkgs/convert/lib/src/hex/encoder.dart b/pkgs/convert/lib/src/hex/encoder.dart index 57a02a2d..36d6c226 100644 --- a/pkgs/convert/lib/src/hex/encoder.dart +++ b/pkgs/convert/lib/src/hex/encoder.dart @@ -2,8 +2,6 @@ // 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. -library convert.hex.encoder; - import 'dart:convert'; import 'dart:typed_data'; diff --git a/pkgs/convert/lib/src/percent.dart b/pkgs/convert/lib/src/percent.dart index 2828b5cf..ecf28670 100644 --- a/pkgs/convert/lib/src/percent.dart +++ b/pkgs/convert/lib/src/percent.dart @@ -2,8 +2,6 @@ // 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. -library convert.percent; - import 'dart:convert'; import 'percent/decoder.dart'; diff --git a/pkgs/convert/lib/src/percent/decoder.dart b/pkgs/convert/lib/src/percent/decoder.dart index 1a4b0e89..ef9c8a8d 100644 --- a/pkgs/convert/lib/src/percent/decoder.dart +++ b/pkgs/convert/lib/src/percent/decoder.dart @@ -2,8 +2,6 @@ // 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. -library convert.percent.decoder; - import 'dart:convert'; import 'package:typed_data/typed_data.dart'; diff --git a/pkgs/convert/lib/src/percent/encoder.dart b/pkgs/convert/lib/src/percent/encoder.dart index 382e7703..b087b7a8 100644 --- a/pkgs/convert/lib/src/percent/encoder.dart +++ b/pkgs/convert/lib/src/percent/encoder.dart @@ -2,8 +2,6 @@ // 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. -library convert.percent.encoder; - import 'dart:convert'; import '../charcodes.dart'; diff --git a/pkgs/convert/lib/src/string_accumulator_sink.dart b/pkgs/convert/lib/src/string_accumulator_sink.dart index 98b476eb..9b07593f 100644 --- a/pkgs/convert/lib/src/string_accumulator_sink.dart +++ b/pkgs/convert/lib/src/string_accumulator_sink.dart @@ -33,12 +33,12 @@ class StringAccumulatorSink extends StringConversionSinkBase { } @override - void addSlice(String str, int start, int end, bool isLast) { + void addSlice(String chunk, int start, int end, bool isLast) { if (_isClosed) { throw StateError("Can't add to a closed sink."); } - _buffer.write(str.substring(start, end)); + _buffer.write(chunk.substring(start, end)); if (isLast) _isClosed = true; } diff --git a/pkgs/convert/lib/src/utils.dart b/pkgs/convert/lib/src/utils.dart index c70aebe7..cfcc1273 100644 --- a/pkgs/convert/lib/src/utils.dart +++ b/pkgs/convert/lib/src/utils.dart @@ -2,8 +2,6 @@ // 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. -library convert.utils; - import 'charcodes.dart'; /// Returns the digit (0 through 15) corresponding to the hexadecimal code unit diff --git a/pkgs/convert/pubspec.yaml b/pkgs/convert/pubspec.yaml index e4e2d3dd..5756232f 100644 --- a/pkgs/convert/pubspec.yaml +++ b/pkgs/convert/pubspec.yaml @@ -1,17 +1,17 @@ name: convert -version: 3.1.1 +version: 3.1.2-dev description: >- Utilities for converting between data representations. Provides a number of Sink, Codec, Decoder, and Encoder types. repository: https://github.com/dart-lang/convert environment: - sdk: '>=2.18.0 <3.0.0' + sdk: '>=2.19.0 <3.0.0' dependencies: typed_data: ^1.3.0 dev_dependencies: benchmark_harness: ^2.2.0 - lints: ^2.0.0 + dart_flutter_team_lints: ^1.0.0 test: ^1.17.0 From d0bc125fe83d9db4d1be585d6610c717cd14aa33 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 8 May 2023 12:27:39 -0700 Subject: [PATCH 075/100] Bump actions/checkout from 3.5.0 to 3.5.2 (dart-lang/convert#82) Bumps [actions/checkout](https://github.com/actions/checkout) from 3.5.0 to 3.5.2. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/8f4b7f84864484a7bf31766abe9204da3cbe65b3...8e5e7e5ab8b370d6c329ec480221332ada57f0ab) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pkgs/convert/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/convert/.github/workflows/test-package.yml b/pkgs/convert/.github/workflows/test-package.yml index 0876594e..c7073ce8 100644 --- a/pkgs/convert/.github/workflows/test-package.yml +++ b/pkgs/convert/.github/workflows/test-package.yml @@ -22,7 +22,7 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@8f4b7f84864484a7bf31766abe9204da3cbe65b3 + - uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f with: sdk: ${{ matrix.sdk }} @@ -49,7 +49,7 @@ jobs: os: [ubuntu-latest] sdk: [2.19.0, dev] steps: - - uses: actions/checkout@8f4b7f84864484a7bf31766abe9204da3cbe65b3 + - uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f with: sdk: ${{ matrix.sdk }} From 3a7d656f47d1cd90e0842e91fd7cafe48e5aac16 Mon Sep 17 00:00:00 2001 From: Devon Carew Date: Tue, 16 May 2023 15:29:36 -0700 Subject: [PATCH 076/100] blast_repo fixes (dart-lang/convert#83) dependabot --- pkgs/convert/.github/dependabot.yaml | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/pkgs/convert/.github/dependabot.yaml b/pkgs/convert/.github/dependabot.yaml index 21448193..439e796b 100644 --- a/pkgs/convert/.github/dependabot.yaml +++ b/pkgs/convert/.github/dependabot.yaml @@ -2,7 +2,9 @@ version: 2 updates: - - package-ecosystem: "github-actions" - directory: "/" + - package-ecosystem: github-actions + directory: / schedule: - interval: "monthly" + interval: monthly + labels: + - autosubmit From e1b88790cd2407695666ad07570293018efc1e10 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 1 Jul 2023 07:29:22 +0000 Subject: [PATCH 077/100] Bump actions/checkout from 3.5.2 to 3.5.3 (dart-lang/convert#84) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [actions/checkout](https://github.com/actions/checkout) from 3.5.2 to 3.5.3.
Release notes

Sourced from actions/checkout's releases.

v3.5.3

What's Changed

New Contributors

Full Changelog: https://github.com/actions/checkout/compare/v3...v3.5.3

Changelog

Sourced from actions/checkout's changelog.

Changelog

v3.5.3

v3.5.2

v3.5.1

v3.5.0

v3.4.0

v3.3.0

v3.2.0

v3.1.0

v3.0.2

v3.0.1

v3.0.0

v2.3.1

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/checkout&package-manager=github_actions&previous-version=3.5.2&new-version=3.5.3)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
--- pkgs/convert/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/convert/.github/workflows/test-package.yml b/pkgs/convert/.github/workflows/test-package.yml index c7073ce8..0eefce02 100644 --- a/pkgs/convert/.github/workflows/test-package.yml +++ b/pkgs/convert/.github/workflows/test-package.yml @@ -22,7 +22,7 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab + - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f with: sdk: ${{ matrix.sdk }} @@ -49,7 +49,7 @@ jobs: os: [ubuntu-latest] sdk: [2.19.0, dev] steps: - - uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab + - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f with: sdk: ${{ matrix.sdk }} From 14db20292d8cccd1902fbeabf93a4f1065e5a874 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 1 Sep 2023 07:14:00 +0000 Subject: [PATCH 078/100] Bump actions/checkout from 3.5.3 to 3.6.0 (dart-lang/convert#86) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [actions/checkout](https://github.com/actions/checkout) from 3.5.3 to 3.6.0.
Release notes

Sourced from actions/checkout's releases.

v3.6.0

What's Changed

New Contributors

Full Changelog: https://github.com/actions/checkout/compare/v3.5.3...v3.6.0

Changelog

Sourced from actions/checkout's changelog.

Changelog

v3.6.0

v3.5.3

v3.5.2

v3.5.1

v3.5.0

v3.4.0

v3.3.0

v3.2.0

v3.1.0

v3.0.2

v3.0.1

v3.0.0

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/checkout&package-manager=github_actions&previous-version=3.5.3&new-version=3.6.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
--- pkgs/convert/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/convert/.github/workflows/test-package.yml b/pkgs/convert/.github/workflows/test-package.yml index 0eefce02..9cfac49a 100644 --- a/pkgs/convert/.github/workflows/test-package.yml +++ b/pkgs/convert/.github/workflows/test-package.yml @@ -22,7 +22,7 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 + - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f with: sdk: ${{ matrix.sdk }} @@ -49,7 +49,7 @@ jobs: os: [ubuntu-latest] sdk: [2.19.0, dev] steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 + - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f with: sdk: ${{ matrix.sdk }} From 2032999913e7c8895a9f196b80644310ac48a8ad Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 1 Oct 2023 07:19:18 +0000 Subject: [PATCH 079/100] Bump actions/checkout from 3.6.0 to 4.1.0 (dart-lang/convert#87) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [actions/checkout](https://github.com/actions/checkout) from 3.6.0 to 4.1.0.
Release notes

Sourced from actions/checkout's releases.

v4.1.0

What's Changed

New Contributors

Full Changelog: https://github.com/actions/checkout/compare/v4.0.0...v4.1.0

v4.0.0

What's Changed

New Contributors

Full Changelog: https://github.com/actions/checkout/compare/v3...v4.0.0

Changelog

Sourced from actions/checkout's changelog.

Changelog

v4.1.0

v4.0.0

v3.6.0

v3.5.3

v3.5.2

v3.5.1

v3.5.0

v3.4.0

v3.3.0

v3.2.0

v3.1.0

v3.0.2

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/checkout&package-manager=github_actions&previous-version=3.6.0&new-version=4.1.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
--- pkgs/convert/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/convert/.github/workflows/test-package.yml b/pkgs/convert/.github/workflows/test-package.yml index 9cfac49a..157dc073 100644 --- a/pkgs/convert/.github/workflows/test-package.yml +++ b/pkgs/convert/.github/workflows/test-package.yml @@ -22,7 +22,7 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 + - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f with: sdk: ${{ matrix.sdk }} @@ -49,7 +49,7 @@ jobs: os: [ubuntu-latest] sdk: [2.19.0, dev] steps: - - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 + - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f with: sdk: ${{ matrix.sdk }} From 2d32c7ed595eeb175870fbc04fc0b1c8265fecb7 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 3 Oct 2023 07:12:43 -0700 Subject: [PATCH 080/100] Bump dart-lang/setup-dart from 1.5.0 to 1.5.1 (dart-lang/convert#88) Bumps [dart-lang/setup-dart](https://github.com/dart-lang/setup-dart) from 1.5.0 to 1.5.1. - [Release notes](https://github.com/dart-lang/setup-dart/releases) - [Changelog](https://github.com/dart-lang/setup-dart/blob/main/CHANGELOG.md) - [Commits](https://github.com/dart-lang/setup-dart/compare/d6a63dab3335f427404425de0fbfed4686d93c4f...8a4b97ea2017cc079571daec46542f76189836b1) --- updated-dependencies: - dependency-name: dart-lang/setup-dart dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pkgs/convert/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/convert/.github/workflows/test-package.yml b/pkgs/convert/.github/workflows/test-package.yml index 157dc073..582d9b84 100644 --- a/pkgs/convert/.github/workflows/test-package.yml +++ b/pkgs/convert/.github/workflows/test-package.yml @@ -23,7 +23,7 @@ jobs: sdk: [dev] steps: - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 - - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f + - uses: dart-lang/setup-dart@8a4b97ea2017cc079571daec46542f76189836b1 with: sdk: ${{ matrix.sdk }} - id: install @@ -50,7 +50,7 @@ jobs: sdk: [2.19.0, dev] steps: - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 - - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f + - uses: dart-lang/setup-dart@8a4b97ea2017cc079571daec46542f76189836b1 with: sdk: ${{ matrix.sdk }} - id: install From c9678d96ad474d58550f131bf8bb783aa02b7448 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 1 Nov 2023 07:06:03 +0000 Subject: [PATCH 081/100] Bump actions/checkout from 4.1.0 to 4.1.1 (dart-lang/convert#90) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [actions/checkout](https://github.com/actions/checkout) from 4.1.0 to 4.1.1.
Release notes

Sourced from actions/checkout's releases.

v4.1.1

What's Changed

New Contributors

Full Changelog: https://github.com/actions/checkout/compare/v4.1.0...v4.1.1

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/checkout&package-manager=github_actions&previous-version=4.1.0&new-version=4.1.1)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
--- pkgs/convert/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/convert/.github/workflows/test-package.yml b/pkgs/convert/.github/workflows/test-package.yml index 582d9b84..3e0b1648 100644 --- a/pkgs/convert/.github/workflows/test-package.yml +++ b/pkgs/convert/.github/workflows/test-package.yml @@ -22,7 +22,7 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 + - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 - uses: dart-lang/setup-dart@8a4b97ea2017cc079571daec46542f76189836b1 with: sdk: ${{ matrix.sdk }} @@ -49,7 +49,7 @@ jobs: os: [ubuntu-latest] sdk: [2.19.0, dev] steps: - - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 + - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 - uses: dart-lang/setup-dart@8a4b97ea2017cc079571daec46542f76189836b1 with: sdk: ${{ matrix.sdk }} From 0e3ac1ec66733268b7a5c4b622ffd37564491be7 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 1 Nov 2023 14:57:59 +0000 Subject: [PATCH 082/100] Bump dart-lang/setup-dart from 1.5.1 to 1.6.0 (dart-lang/convert#89) Bumps [dart-lang/setup-dart](https://github.com/dart-lang/setup-dart) from 1.5.1 to 1.6.0.
Release notes

Sourced from dart-lang/setup-dart's releases.

v1.6.0

  • Enable provisioning of the latest Dart SDK patch release by specifying just the major and minor version (e.g. 3.2).
Changelog

Sourced from dart-lang/setup-dart's changelog.

v1.6.0

  • Enable provisioning of the latest Dart SDK patch release by specifying just the major and minor version (e.g. 3.2).

v1.5.1

  • No longer test the setup-dart action on pre-2.12 SDKs.
  • Upgrade JS interop code to use extension types (the new name for inline classes).
  • The upcoming rename of the be channel to main is now supported with forward compatibility that switches when the rename happens.

v1.5.0

  • Re-wrote the implementation of the action into Dart.
  • Auto-detect the platform architecture (x64, ia32, arm, arm64).
  • Improved the caching and download resilience of the sdk.
  • Added a new action output: dart-version - the installed version of the sdk.

v1.4.0

  • Automatically create OIDC token for pub.dev.
  • Add a reusable workflow for publishing.

v1.3.0

  • The install location of the Dart SDK is now available in an environment variable, DART_HOME (dart-lang/convert#43).
  • Fixed an issue where cached downloads could lead to unzip issues on self-hosted runners (dart-lang/convert#35).

v1.2.0

  • Fixed a path issue impacting git dependencies on Windows.

v1.1.0

  • Added a flavor option setup.sh to allow downloading unpublished builds.

v1.0.0

  • Promoted to 1.0 stable.

v0.5

  • Fixed a Windows pub global activate path issue.

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=dart-lang/setup-dart&package-manager=github_actions&previous-version=1.5.1&new-version=1.6.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
--- pkgs/convert/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/convert/.github/workflows/test-package.yml b/pkgs/convert/.github/workflows/test-package.yml index 3e0b1648..f464e927 100644 --- a/pkgs/convert/.github/workflows/test-package.yml +++ b/pkgs/convert/.github/workflows/test-package.yml @@ -23,7 +23,7 @@ jobs: sdk: [dev] steps: - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 - - uses: dart-lang/setup-dart@8a4b97ea2017cc079571daec46542f76189836b1 + - uses: dart-lang/setup-dart@b64355ae6ca0b5d484f0106a033dd1388965d06d with: sdk: ${{ matrix.sdk }} - id: install @@ -50,7 +50,7 @@ jobs: sdk: [2.19.0, dev] steps: - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 - - uses: dart-lang/setup-dart@8a4b97ea2017cc079571daec46542f76189836b1 + - uses: dart-lang/setup-dart@b64355ae6ca0b5d484f0106a033dd1388965d06d with: sdk: ${{ matrix.sdk }} - id: install From 37c9ad95ea97ca31f5d18ded1df74ff8132278d2 Mon Sep 17 00:00:00 2001 From: Brian Quinlan Date: Mon, 6 Nov 2023 08:46:10 -0800 Subject: [PATCH 083/100] Add chunked decoding support to CodePage (dart-lang/convert#91) --- .../.github/workflows/test-package.yml | 2 +- pkgs/convert/CHANGELOG.md | 4 +- pkgs/convert/lib/src/codepage.dart | 27 ++++ pkgs/convert/pubspec.yaml | 2 +- pkgs/convert/test/codepage_test.dart | 131 ++++++++++++++---- 5 files changed, 137 insertions(+), 29 deletions(-) diff --git a/pkgs/convert/.github/workflows/test-package.yml b/pkgs/convert/.github/workflows/test-package.yml index f464e927..081bfb72 100644 --- a/pkgs/convert/.github/workflows/test-package.yml +++ b/pkgs/convert/.github/workflows/test-package.yml @@ -47,7 +47,7 @@ jobs: matrix: # Add macos-latest and/or windows-latest if relevant for this package. os: [ubuntu-latest] - sdk: [2.19.0, dev] + sdk: [3.0.0, dev] steps: - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 - uses: dart-lang/setup-dart@b64355ae6ca0b5d484f0106a033dd1388965d06d diff --git a/pkgs/convert/CHANGELOG.md b/pkgs/convert/CHANGELOG.md index 415ade50..925b1d67 100644 --- a/pkgs/convert/CHANGELOG.md +++ b/pkgs/convert/CHANGELOG.md @@ -1,6 +1,8 @@ ## 3.1.2-dev -- Require Dart 2.19 +- Require Dart 3.0 +- Add chunked decoding support (`startChunkedConversion`) for `CodePage` + encodings. ## 3.1.1 diff --git a/pkgs/convert/lib/src/codepage.dart b/pkgs/convert/lib/src/codepage.dart index 50941b49..c298ff5a 100644 --- a/pkgs/convert/lib/src/codepage.dart +++ b/pkgs/convert/lib/src/codepage.dart @@ -277,6 +277,25 @@ CodePageDecoder _createDecoder(String characters) { return _NonBmpCodePageDecoder._(result); } +/// An input [ByteConversionSink] for decoders where each input byte can be be +/// considered independantly. +class _CodePageDecoderSink extends ByteConversionSink { + final Sink _output; + final Converter, String> _decoder; + + _CodePageDecoderSink(this._output, this._decoder); + + @override + void add(List chunk) { + _output.add(_decoder.convert(chunk)); + } + + @override + void close() { + _output.close(); + } +} + /// Code page with non-BMP characters. class _NonBmpCodePageDecoder extends Converter, String> implements CodePageDecoder { @@ -326,6 +345,10 @@ class _NonBmpCodePageDecoder extends Converter, String> } return String.fromCharCodes(buffer); } + + @override + Sink> startChunkedConversion(Sink sink) => + _CodePageDecoderSink(sink, this); } class _BmpCodePageDecoder extends Converter, String> @@ -360,6 +383,10 @@ class _BmpCodePageDecoder extends Converter, String> return String.fromCharCodes(codeUnits); } + @override + Sink> startChunkedConversion(Sink sink) => + _CodePageDecoderSink(sink, this); + String _convertAllowInvalid(List bytes) { var count = bytes.length; var codeUnits = Uint16List(count); diff --git a/pkgs/convert/pubspec.yaml b/pkgs/convert/pubspec.yaml index 5756232f..77a7edb1 100644 --- a/pkgs/convert/pubspec.yaml +++ b/pkgs/convert/pubspec.yaml @@ -6,7 +6,7 @@ description: >- repository: https://github.com/dart-lang/convert environment: - sdk: '>=2.19.0 <3.0.0' + sdk: '^3.0.0' dependencies: typed_data: ^1.3.0 diff --git a/pkgs/convert/test/codepage_test.dart b/pkgs/convert/test/codepage_test.dart index c0fa45f0..cca75e7b 100644 --- a/pkgs/convert/test/codepage_test.dart +++ b/pkgs/convert/test/codepage_test.dart @@ -2,6 +2,8 @@ // 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 'dart:convert'; +import 'dart:core'; import 'dart:typed_data'; import 'package:convert/convert.dart'; @@ -25,24 +27,52 @@ void main() { latinThai, latinArabic ]) { - test('${cp.name} codepage', () { - // All ASCII compatible. - for (var byte = 0x20; byte < 0x7f; byte++) { - expect(cp[byte], byte); - } - // Maps both directions. - for (var byte = 0; byte < 256; byte++) { - var char = cp[byte]; - if (char != 0xFFFD) { - var string = String.fromCharCode(char); - expect(cp.encode(string), [byte]); - expect(cp.decode([byte]), string); + group('${cp.name} codepage', () { + test('ascii compatible', () { + for (var byte = 0x20; byte < 0x7f; byte++) { + expect(cp[byte], byte); } - } - expect(() => cp.decode([0xfffd]), throwsA(isA())); - // Decode works like operator[]. - expect(cp.decode(bytes, allowInvalid: true), - String.fromCharCodes([for (var i = 0; i < 256; i++) cp[i]])); + }); + + test('bidirectional mapping', () { + // Maps both directions. + for (var byte = 0; byte < 256; byte++) { + var char = cp[byte]; + if (char != 0xFFFD) { + var string = String.fromCharCode(char); + expect(cp.encode(string), [byte]); + expect(cp.decode([byte]), string); + } + } + }); + + test('decode invalid characters not allowed', () { + expect(() => cp.decode([0xfffd]), throwsA(isA())); + }); + + test('decode invalid characters allowed', () { + // Decode works like operator[]. + expect(cp.decode(bytes, allowInvalid: true), + String.fromCharCodes([for (var i = 0; i < 256; i++) cp[i]])); + }); + + test('chunked conversion', () { + late final String decodedString; + final outputSink = StringConversionSink.withCallback( + (accumulated) => decodedString = accumulated); + final inputSink = cp.decoder.startChunkedConversion(outputSink); + final expected = StringBuffer(); + + for (var byte = 0; byte < 256; byte++) { + var char = cp[byte]; + if (char != 0xFFFD) { + inputSink.add([byte]); + expected.writeCharCode(char); + } + } + inputSink.close(); + expect(decodedString, expected.toString()); + }); }); } test('latin-2 roundtrip', () { @@ -62,14 +92,63 @@ void main() { expect(decoded, latin2text); }); - test('Custom code page', () { - var cp = CodePage('custom', "ABCDEF${"\uFFFD" * 250}"); - var result = cp.encode('BADCAFE'); - expect(result, [1, 0, 3, 2, 0, 5, 4]); - expect(() => cp.encode('GAD'), throwsFormatException); - expect(cp.encode('GAD', invalidCharacter: 0x3F), [0x3F, 0, 3]); - expect(cp.decode([1, 0, 3, 2, 0, 5, 4]), 'BADCAFE'); - expect(() => cp.decode([6, 1, 255]), throwsFormatException); - expect(cp.decode([6, 1, 255], allowInvalid: true), '\u{FFFD}B\u{FFFD}'); + group('Custom code page', () { + late final cp = CodePage('custom', "ABCDEF${"\uFFFD" * 250}"); + + test('simple encode', () { + var result = cp.encode('BADCAFE'); + expect(result, [1, 0, 3, 2, 0, 5, 4]); + }); + + test('unencodable character', () { + expect(() => cp.encode('GAD'), throwsFormatException); + }); + + test('unencodable character with invalidCharacter', () { + expect(cp.encode('GAD', invalidCharacter: 0x3F), [0x3F, 0, 3]); + }); + + test('simple decode', () { + expect(cp.decode([1, 0, 3, 2, 0, 5, 4]), 'BADCAFE'); + }); + + test('undecodable byte', () { + expect(() => cp.decode([6, 1, 255]), throwsFormatException); + }); + + test('undecodable byte with allowInvalid', () { + expect(cp.decode([6, 1, 255], allowInvalid: true), '\u{FFFD}B\u{FFFD}'); + }); + + test('chunked conversion', () { + late final String decodedString; + final outputSink = StringConversionSink.withCallback( + (accumulated) => decodedString = accumulated); + final inputSink = cp.decoder.startChunkedConversion(outputSink); + + inputSink + ..add([1]) + ..add([0]) + ..add([3]) + ..close(); + expect(decodedString, 'BAD'); + }); + + test('chunked conversion - byte conversion sink', () { + late final String decodedString; + final outputSink = StringConversionSink.withCallback( + (accumulated) => decodedString = accumulated); + final bytes = [1, 0, 3, 2, 0, 5, 4]; + + final inputSink = cp.decoder.startChunkedConversion(outputSink); + expect(inputSink, isA()); + + (inputSink as ByteConversionSink) + ..addSlice(bytes, 1, 3, false) + ..addSlice(bytes, 4, 5, false) + ..addSlice(bytes, 6, 6, true); + + expect(decodedString, 'ADA'); + }); }); } From 41149d297bc006f2166eaa42ef0650b6d7094882 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Mon, 18 Dec 2023 16:38:05 -0800 Subject: [PATCH 084/100] blast_repo fixes (dart-lang/convert#96) auto-publish, no-response --- .../convert/.github/workflows/no-response.yml | 37 +++++++++++++++++++ pkgs/convert/.github/workflows/publish.yaml | 17 +++++++++ 2 files changed, 54 insertions(+) create mode 100644 pkgs/convert/.github/workflows/no-response.yml create mode 100644 pkgs/convert/.github/workflows/publish.yaml diff --git a/pkgs/convert/.github/workflows/no-response.yml b/pkgs/convert/.github/workflows/no-response.yml new file mode 100644 index 00000000..8e5ed57c --- /dev/null +++ b/pkgs/convert/.github/workflows/no-response.yml @@ -0,0 +1,37 @@ +# A workflow to close issues where the author hasn't responded to a request for +# more information; see https://github.com/actions/stale. + +name: No Response + +# Run as a daily cron. +on: + schedule: + # Every day at 8am + - cron: '0 8 * * *' + +# All permissions not specified are set to 'none'. +permissions: + issues: write + pull-requests: write + +jobs: + no-response: + runs-on: ubuntu-latest + if: ${{ github.repository_owner == 'dart-lang' }} + steps: + - uses: actions/stale@1160a2240286f5da8ec72b1c0816ce2481aabf84 + with: + # Don't automatically mark inactive issues+PRs as stale. + days-before-stale: -1 + # Close needs-info issues and PRs after 14 days of inactivity. + days-before-close: 14 + stale-issue-label: "needs-info" + close-issue-message: > + Without additional information we're not able to resolve this issue. + Feel free to add more info or respond to any questions above and we + can reopen the case. Thanks for your contribution! + stale-pr-label: "needs-info" + close-pr-message: > + Without additional information we're not able to resolve this PR. + Feel free to add more info or respond to any questions above. + Thanks for your contribution! diff --git a/pkgs/convert/.github/workflows/publish.yaml b/pkgs/convert/.github/workflows/publish.yaml new file mode 100644 index 00000000..27157a04 --- /dev/null +++ b/pkgs/convert/.github/workflows/publish.yaml @@ -0,0 +1,17 @@ +# A CI configuration to auto-publish pub packages. + +name: Publish + +on: + pull_request: + branches: [ master ] + push: + tags: [ 'v[0-9]+.[0-9]+.[0-9]+' ] + +jobs: + publish: + if: ${{ github.repository_owner == 'dart-lang' }} + uses: dart-lang/ecosystem/.github/workflows/publish.yaml@main + permissions: + id-token: write # Required for authentication using OIDC + pull-requests: write # Required for writing the pull request note From ba4040026e06b376a7a7f1f234011e9609c6d5ca Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Mon, 18 Dec 2023 16:38:49 -0800 Subject: [PATCH 085/100] Enable and fix new lints (dart-lang/convert#97) --- pkgs/convert/CHANGELOG.md | 2 +- pkgs/convert/analysis_options.yaml | 5 ----- pkgs/convert/pubspec.yaml | 6 +++--- pkgs/convert/test/hex_test.dart | 8 ++++---- pkgs/convert/test/percent_test.dart | 10 +++++----- 5 files changed, 13 insertions(+), 18 deletions(-) diff --git a/pkgs/convert/CHANGELOG.md b/pkgs/convert/CHANGELOG.md index 925b1d67..00b795de 100644 --- a/pkgs/convert/CHANGELOG.md +++ b/pkgs/convert/CHANGELOG.md @@ -1,4 +1,4 @@ -## 3.1.2-dev +## 3.1.2-wip - Require Dart 3.0 - Add chunked decoding support (`startChunkedConversion`) for `CodePage` diff --git a/pkgs/convert/analysis_options.yaml b/pkgs/convert/analysis_options.yaml index 6c58fa83..20982383 100644 --- a/pkgs/convert/analysis_options.yaml +++ b/pkgs/convert/analysis_options.yaml @@ -13,17 +13,12 @@ linter: - avoid_unused_constructor_parameters - avoid_void_async - cancel_subscriptions - - comment_references - literal_only_boolean_expressions - missing_whitespace_between_adjacent_strings - no_adjacent_strings_in_list - no_runtimeType_toString - package_api_docs - - prefer_const_constructors - prefer_const_declarations - prefer_expression_function_bodies - - prefer_relative_imports - - test_types_in_equals - unnecessary_await_in_return - use_string_buffers - - use_super_parameters diff --git a/pkgs/convert/pubspec.yaml b/pkgs/convert/pubspec.yaml index 77a7edb1..59d6f9df 100644 --- a/pkgs/convert/pubspec.yaml +++ b/pkgs/convert/pubspec.yaml @@ -1,17 +1,17 @@ name: convert -version: 3.1.2-dev +version: 3.1.2-wip description: >- Utilities for converting between data representations. Provides a number of Sink, Codec, Decoder, and Encoder types. repository: https://github.com/dart-lang/convert environment: - sdk: '^3.0.0' + sdk: ^3.0.0 dependencies: typed_data: ^1.3.0 dev_dependencies: benchmark_harness: ^2.2.0 - dart_flutter_team_lints: ^1.0.0 + dart_flutter_team_lints: ^2.0.0 test: ^1.17.0 diff --git a/pkgs/convert/test/hex_test.dart b/pkgs/convert/test/hex_test.dart index 7632cb18..abd940f6 100644 --- a/pkgs/convert/test/hex_test.dart +++ b/pkgs/convert/test/hex_test.dart @@ -147,16 +147,16 @@ void main() { expect(results, isEmpty); sink.add('0'); - expect(results, equals([[]])); + expect(results, equals([[]])); sink.add(''); - expect(results, equals([[]])); + expect(results, equals([[]])); sink.add('0'); expect( results, equals([ - [], + [], [0x00] ])); @@ -164,7 +164,7 @@ void main() { expect( results, equals([ - [], + [], [0x00] ])); }); diff --git a/pkgs/convert/test/percent_test.dart b/pkgs/convert/test/percent_test.dart index cc74a69e..4e0f605d 100644 --- a/pkgs/convert/test/percent_test.dart +++ b/pkgs/convert/test/percent_test.dart @@ -154,22 +154,22 @@ void main() { expect(results, isEmpty); sink.add('%'); - expect(results, equals([[]])); + expect(results, equals([[]])); sink.add(''); - expect(results, equals([[]])); + expect(results, equals([[]])); sink.add('2'); - expect(results, equals([[]])); + expect(results, equals([[]])); sink.add(''); - expect(results, equals([[]])); + expect(results, equals([[]])); sink.add('0'); expect( results, equals([ - [], + [], [0x20] ])); }); From 014be9e7ef4e7ad7778dffa74d764afef461d5f5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 1 Jan 2024 07:13:21 +0000 Subject: [PATCH 086/100] Bump actions/stale from 8.0.0 to 9.0.0 (dart-lang/convert#98) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [actions/stale](https://github.com/actions/stale) from 8.0.0 to 9.0.0.
Release notes

Sourced from actions/stale's releases.

v9.0.0

Breaking Changes

  1. Action is now stateful: If the action ends because of operations-per-run then the next run will start from the first unprocessed issue skipping the issues processed during the previous run(s). The state is reset when all the issues are processed. This should be considered for scheduling workflow runs.
  2. Version 9 of this action updated the runtime to Node.js 20. All scripts are now run with Node.js 20 instead of Node.js 16 and are affected by any breaking changes between Node.js 16 and 20.

What Else Changed

  1. Performance optimization that removes unnecessary API calls by @​dsame dart-lang/convert#1033 fixes dart-lang/convert#792
  2. Logs displaying current github API rate limit by @​dsame dart-lang/convert#1032 addresses dart-lang/convert#1029

For more information, please read the action documentation and its section about statefulness

New Contributors

Full Changelog: https://github.com/actions/stale/compare/v8...v9.0.0

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/stale&package-manager=github_actions&previous-version=8.0.0&new-version=9.0.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
--- pkgs/convert/.github/workflows/no-response.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/convert/.github/workflows/no-response.yml b/pkgs/convert/.github/workflows/no-response.yml index 8e5ed57c..ab1ac498 100644 --- a/pkgs/convert/.github/workflows/no-response.yml +++ b/pkgs/convert/.github/workflows/no-response.yml @@ -19,7 +19,7 @@ jobs: runs-on: ubuntu-latest if: ${{ github.repository_owner == 'dart-lang' }} steps: - - uses: actions/stale@1160a2240286f5da8ec72b1c0816ce2481aabf84 + - uses: actions/stale@28ca1036281a5e5922ead5184a1bbf96e5fc984e with: # Don't automatically mark inactive issues+PRs as stale. days-before-stale: -1 From 652605ea5f336320f209a78aba9d0c4a26f116fc Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 1 Feb 2024 07:23:18 +0000 Subject: [PATCH 087/100] Bump dart-lang/setup-dart from 1.6.0 to 1.6.2 (dart-lang/convert#100) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [dart-lang/setup-dart](https://github.com/dart-lang/setup-dart) from 1.6.0 to 1.6.2.
Release notes

Sourced from dart-lang/setup-dart's releases.

v1.6.2

v1.6.1

  • Updated the google storage url for main channel releases.
Changelog

Sourced from dart-lang/setup-dart's changelog.

v1.6.2

v1.6.1

  • Updated the google storage url for main channel releases.

v1.6.0

  • Enable provisioning of the latest Dart SDK patch release by specifying just the major and minor version (e.g. 3.2).

v1.5.1

  • No longer test the setup-dart action on pre-2.12 SDKs.
  • Upgrade JS interop code to use extension types (the new name for inline classes).
  • The upcoming rename of the be channel to main is now supported with forward compatibility that switches when the rename happens.

v1.5.0

  • Re-wrote the implementation of the action into Dart.
  • Auto-detect the platform architecture (x64, ia32, arm, arm64).
  • Improved the caching and download resilience of the sdk.
  • Added a new action output: dart-version - the installed version of the sdk.

v1.4.0

  • Automatically create OIDC token for pub.dev.
  • Add a reusable workflow for publishing.

v1.3.0

  • The install location of the Dart SDK is now available in an environment variable, DART_HOME (dart-lang/convert#43).
  • Fixed an issue where cached downloads could lead to unzip issues on self-hosted runners (dart-lang/convert#35).

v1.2.0

  • Fixed a path issue impacting git dependencies on Windows.

v1.1.0

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=dart-lang/setup-dart&package-manager=github_actions&previous-version=1.6.0&new-version=1.6.2)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
--- pkgs/convert/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/convert/.github/workflows/test-package.yml b/pkgs/convert/.github/workflows/test-package.yml index 081bfb72..f92efd34 100644 --- a/pkgs/convert/.github/workflows/test-package.yml +++ b/pkgs/convert/.github/workflows/test-package.yml @@ -23,7 +23,7 @@ jobs: sdk: [dev] steps: - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 - - uses: dart-lang/setup-dart@b64355ae6ca0b5d484f0106a033dd1388965d06d + - uses: dart-lang/setup-dart@fedb1266e91cf51be2fdb382869461a434b920a3 with: sdk: ${{ matrix.sdk }} - id: install @@ -50,7 +50,7 @@ jobs: sdk: [3.0.0, dev] steps: - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 - - uses: dart-lang/setup-dart@b64355ae6ca0b5d484f0106a033dd1388965d06d + - uses: dart-lang/setup-dart@fedb1266e91cf51be2fdb382869461a434b920a3 with: sdk: ${{ matrix.sdk }} - id: install From 0b54670c328c23ce1b006bfc3c918f01b302fc55 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Thu, 1 Feb 2024 12:14:53 -0800 Subject: [PATCH 088/100] Test dart2wasm (dart-lang/convert#101) --- pkgs/convert/.github/workflows/test-package.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/pkgs/convert/.github/workflows/test-package.yml b/pkgs/convert/.github/workflows/test-package.yml index f92efd34..16cc580e 100644 --- a/pkgs/convert/.github/workflows/test-package.yml +++ b/pkgs/convert/.github/workflows/test-package.yml @@ -62,3 +62,7 @@ jobs: - name: Run Chrome tests run: dart test --platform chrome if: always() && steps.install.outcome == 'success' + - name: Run Chrome tests - wasm + run: dart test --platform chrome --compiler dart2wasm + # TODO: drop `dev` filter when dart2wasm is working on stable + if: always() && steps.install.outcome == 'success' && matrix.sdk == 'dev' From e702bb65a45d2c791645b68658bd9482736d04d1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 1 Apr 2024 07:29:55 +0000 Subject: [PATCH 089/100] Bump actions/checkout from 4.1.1 to 4.1.2 (dart-lang/convert#102) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [actions/checkout](https://github.com/actions/checkout) from 4.1.1 to 4.1.2.
Release notes

Sourced from actions/checkout's releases.

v4.1.2

We are investigating the following issue with this release and have rolled-back the v4 tag to point to v4.1.1

What's Changed

New Contributors

Full Changelog: https://github.com/actions/checkout/compare/v4.1.1...v4.1.2

Changelog

Sourced from actions/checkout's changelog.

Changelog

v4.1.2

v4.1.1

v4.1.0

v4.0.0

v3.6.0

v3.5.3

v3.5.2

v3.5.1

v3.5.0

v3.4.0

v3.3.0

v3.2.0

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/checkout&package-manager=github_actions&previous-version=4.1.1&new-version=4.1.2)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
--- pkgs/convert/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/convert/.github/workflows/test-package.yml b/pkgs/convert/.github/workflows/test-package.yml index 16cc580e..1074a822 100644 --- a/pkgs/convert/.github/workflows/test-package.yml +++ b/pkgs/convert/.github/workflows/test-package.yml @@ -22,7 +22,7 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 + - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 - uses: dart-lang/setup-dart@fedb1266e91cf51be2fdb382869461a434b920a3 with: sdk: ${{ matrix.sdk }} @@ -49,7 +49,7 @@ jobs: os: [ubuntu-latest] sdk: [3.0.0, dev] steps: - - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 + - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 - uses: dart-lang/setup-dart@fedb1266e91cf51be2fdb382869461a434b920a3 with: sdk: ${{ matrix.sdk }} From 4b526c4d91c11a5e811de98daa51f4d88411d97b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 1 May 2024 07:41:52 +0000 Subject: [PATCH 090/100] Bump dart-lang/setup-dart from 1.6.2 to 1.6.4 (dart-lang/convert#104) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [dart-lang/setup-dart](https://github.com/dart-lang/setup-dart) from 1.6.2 to 1.6.4.
Release notes

Sourced from dart-lang/setup-dart's releases.

v1.6.4

  • Rebuild JS code to include changes from v1.6.3

v1.6.3

Changelog

Sourced from dart-lang/setup-dart's changelog.

v1.6.4

  • Rebuild JS code.

v1.6.3

v1.6.2

v1.6.1

  • Updated the google storage url for main channel releases.

v1.6.0

  • Enable provisioning of the latest Dart SDK patch release by specifying just the major and minor version (e.g. 3.2).

v1.5.1

  • No longer test the setup-dart action on pre-2.12 SDKs.
  • Upgrade JS interop code to use extension types (the new name for inline classes).
  • The upcoming rename of the be channel to main is now supported with forward compatibility that switches when the rename happens.

v1.5.0

  • Re-wrote the implementation of the action into Dart.
  • Auto-detect the platform architecture (x64, ia32, arm, arm64).
  • Improved the caching and download resilience of the sdk.
  • Added a new action output: dart-version - the installed version of the sdk.

v1.4.0

  • Automatically create OIDC token for pub.dev.
  • Add a reusable workflow for publishing.

v1.3.0

  • The install location of the Dart SDK is now available

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=dart-lang/setup-dart&package-manager=github_actions&previous-version=1.6.2&new-version=1.6.4)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
--- pkgs/convert/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/convert/.github/workflows/test-package.yml b/pkgs/convert/.github/workflows/test-package.yml index 1074a822..2ef35ddc 100644 --- a/pkgs/convert/.github/workflows/test-package.yml +++ b/pkgs/convert/.github/workflows/test-package.yml @@ -23,7 +23,7 @@ jobs: sdk: [dev] steps: - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 - - uses: dart-lang/setup-dart@fedb1266e91cf51be2fdb382869461a434b920a3 + - uses: dart-lang/setup-dart@f0ead981b4d9a35b37f30d36160575d60931ec30 with: sdk: ${{ matrix.sdk }} - id: install @@ -50,7 +50,7 @@ jobs: sdk: [3.0.0, dev] steps: - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 - - uses: dart-lang/setup-dart@fedb1266e91cf51be2fdb382869461a434b920a3 + - uses: dart-lang/setup-dart@f0ead981b4d9a35b37f30d36160575d60931ec30 with: sdk: ${{ matrix.sdk }} - id: install From 3066dc880a457c6857ec5ea7ec71892f52f55f33 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 1 May 2024 07:46:14 +0000 Subject: [PATCH 091/100] Bump actions/checkout from 4.1.2 to 4.1.4 (dart-lang/convert#103) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ⚠️ **Dependabot is rebasing this PR** ⚠️ Rebasing might not happen immediately, so don't worry if this takes some time. Note: if you make any changes to this PR yourself, they will take precedence over the rebase. --- Bumps [actions/checkout](https://github.com/actions/checkout) from 4.1.2 to 4.1.4.
Release notes

Sourced from actions/checkout's releases.

v4.1.4

What's Changed

Full Changelog: https://github.com/actions/checkout/compare/v4.1.3...v4.1.4

v4.1.3

What's Changed

Full Changelog: https://github.com/actions/checkout/compare/v4.1.2...v4.1.3

Changelog

Sourced from actions/checkout's changelog.

Changelog

v4.1.4

v4.1.3

v4.1.2

v4.1.1

v4.1.0

v4.0.0

v3.6.0

v3.5.3

v3.5.2

v3.5.1

v3.5.0

v3.4.0

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/checkout&package-manager=github_actions&previous-version=4.1.2&new-version=4.1.4)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
--- pkgs/convert/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/convert/.github/workflows/test-package.yml b/pkgs/convert/.github/workflows/test-package.yml index 2ef35ddc..e359011e 100644 --- a/pkgs/convert/.github/workflows/test-package.yml +++ b/pkgs/convert/.github/workflows/test-package.yml @@ -22,7 +22,7 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 + - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b - uses: dart-lang/setup-dart@f0ead981b4d9a35b37f30d36160575d60931ec30 with: sdk: ${{ matrix.sdk }} @@ -49,7 +49,7 @@ jobs: os: [ubuntu-latest] sdk: [3.0.0, dev] steps: - - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 + - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b - uses: dart-lang/setup-dart@f0ead981b4d9a35b37f30d36160575d60931ec30 with: sdk: ${{ matrix.sdk }} From 488c42dedcd3cec49aac57278237f5fec7908b37 Mon Sep 17 00:00:00 2001 From: Devon Carew Date: Fri, 3 May 2024 15:07:15 -0700 Subject: [PATCH 092/100] blast_repo fixes (dart-lang/convert#105) dependabot --- pkgs/convert/.github/dependabot.yaml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/pkgs/convert/.github/dependabot.yaml b/pkgs/convert/.github/dependabot.yaml index 439e796b..bf6b38a4 100644 --- a/pkgs/convert/.github/dependabot.yaml +++ b/pkgs/convert/.github/dependabot.yaml @@ -8,3 +8,7 @@ updates: interval: monthly labels: - autosubmit + groups: + github-actions: + patterns: + - "*" From 449efc9aefbe6a76bca50a6c9cf8889dd2128081 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 2 Jun 2024 17:18:45 +0000 Subject: [PATCH 093/100] Bump actions/checkout from 4.1.4 to 4.1.6 in the github-actions group (dart-lang/convert#106) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps the github-actions group with 1 update: [actions/checkout](https://github.com/actions/checkout). Updates `actions/checkout` from 4.1.4 to 4.1.6
Release notes

Sourced from actions/checkout's releases.

v4.1.6

What's Changed

Full Changelog: https://github.com/actions/checkout/compare/v4.1.5...v4.1.6

v4.1.5

What's Changed

Full Changelog: https://github.com/actions/checkout/compare/v4.1.4...v4.1.5

Changelog

Sourced from actions/checkout's changelog.

Changelog

v4.1.6

v4.1.5

v4.1.4

v4.1.3

v4.1.2

v4.1.1

v4.1.0

v4.0.0

v3.6.0

v3.5.3

v3.5.2

v3.5.1

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/checkout&package-manager=github_actions&previous-version=4.1.4&new-version=4.1.6)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore major version` will close this group update PR and stop Dependabot creating any more for the specific dependency's major version (unless you unignore this specific dependency's major version or upgrade to it yourself) - `@dependabot ignore minor version` will close this group update PR and stop Dependabot creating any more for the specific dependency's minor version (unless you unignore this specific dependency's minor version or upgrade to it yourself) - `@dependabot ignore ` will close this group update PR and stop Dependabot creating any more for the specific dependency (unless you unignore this specific dependency or upgrade to it yourself) - `@dependabot unignore ` will remove all of the ignore conditions of the specified dependency - `@dependabot unignore ` will remove the ignore condition of the specified dependency and ignore conditions
--- pkgs/convert/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/convert/.github/workflows/test-package.yml b/pkgs/convert/.github/workflows/test-package.yml index e359011e..891c9161 100644 --- a/pkgs/convert/.github/workflows/test-package.yml +++ b/pkgs/convert/.github/workflows/test-package.yml @@ -22,7 +22,7 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b + - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 - uses: dart-lang/setup-dart@f0ead981b4d9a35b37f30d36160575d60931ec30 with: sdk: ${{ matrix.sdk }} @@ -49,7 +49,7 @@ jobs: os: [ubuntu-latest] sdk: [3.0.0, dev] steps: - - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b + - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 - uses: dart-lang/setup-dart@f0ead981b4d9a35b37f30d36160575d60931ec30 with: sdk: ${{ matrix.sdk }} From 4dbbc6c354e9ca498563bfbac33f25dc5358325d Mon Sep 17 00:00:00 2001 From: Alex Li Date: Mon, 10 Jun 2024 05:11:46 +0800 Subject: [PATCH 094/100] =?UTF-8?q?=E2=9A=A1=20Upper-cast=20the=20return?= =?UTF-8?q?=20type=20of=20the=20decoder=20(dart-lang/convert#99)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pkgs/convert/CHANGELOG.md | 1 + pkgs/convert/lib/src/hex/decoder.dart | 7 +++++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/pkgs/convert/CHANGELOG.md b/pkgs/convert/CHANGELOG.md index 00b795de..616223a6 100644 --- a/pkgs/convert/CHANGELOG.md +++ b/pkgs/convert/CHANGELOG.md @@ -3,6 +3,7 @@ - Require Dart 3.0 - Add chunked decoding support (`startChunkedConversion`) for `CodePage` encodings. +- Upper-cast the return type of the decoder from `List` to `Uint8List`. ## 3.1.1 diff --git a/pkgs/convert/lib/src/hex/decoder.dart b/pkgs/convert/lib/src/hex/decoder.dart index 848a4ae4..3696d4d9 100644 --- a/pkgs/convert/lib/src/hex/decoder.dart +++ b/pkgs/convert/lib/src/hex/decoder.dart @@ -19,10 +19,13 @@ class HexDecoder extends Converter> { const HexDecoder._(); @override - List convert(String input) { + Uint8List convert(String input) { if (!input.length.isEven) { throw FormatException( - 'Invalid input length, must be even.', input, input.length); + 'Invalid input length, must be even.', + input, + input.length, + ); } var bytes = Uint8List(input.length ~/ 2); From 1bd5f63c3673882be1e98afd0546c0981d239c7c Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Mon, 10 Jun 2024 09:30:24 -0700 Subject: [PATCH 095/100] latest lints, require Dart 3.4 (dart-lang/convert#107) --- pkgs/convert/.github/workflows/test-package.yml | 5 ++--- pkgs/convert/CHANGELOG.md | 2 +- pkgs/convert/pubspec.yaml | 4 ++-- 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/pkgs/convert/.github/workflows/test-package.yml b/pkgs/convert/.github/workflows/test-package.yml index 891c9161..d43d1403 100644 --- a/pkgs/convert/.github/workflows/test-package.yml +++ b/pkgs/convert/.github/workflows/test-package.yml @@ -47,7 +47,7 @@ jobs: matrix: # Add macos-latest and/or windows-latest if relevant for this package. os: [ubuntu-latest] - sdk: [3.0.0, dev] + sdk: [3.4, dev] steps: - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 - uses: dart-lang/setup-dart@f0ead981b4d9a35b37f30d36160575d60931ec30 @@ -64,5 +64,4 @@ jobs: if: always() && steps.install.outcome == 'success' - name: Run Chrome tests - wasm run: dart test --platform chrome --compiler dart2wasm - # TODO: drop `dev` filter when dart2wasm is working on stable - if: always() && steps.install.outcome == 'success' && matrix.sdk == 'dev' + if: always() && steps.install.outcome == 'success' diff --git a/pkgs/convert/CHANGELOG.md b/pkgs/convert/CHANGELOG.md index 616223a6..f7890683 100644 --- a/pkgs/convert/CHANGELOG.md +++ b/pkgs/convert/CHANGELOG.md @@ -1,6 +1,6 @@ ## 3.1.2-wip -- Require Dart 3.0 +- Require Dart 3.4 - Add chunked decoding support (`startChunkedConversion`) for `CodePage` encodings. - Upper-cast the return type of the decoder from `List` to `Uint8List`. diff --git a/pkgs/convert/pubspec.yaml b/pkgs/convert/pubspec.yaml index 59d6f9df..9f0b1099 100644 --- a/pkgs/convert/pubspec.yaml +++ b/pkgs/convert/pubspec.yaml @@ -6,12 +6,12 @@ description: >- repository: https://github.com/dart-lang/convert environment: - sdk: ^3.0.0 + sdk: ^3.4.0 dependencies: typed_data: ^1.3.0 dev_dependencies: benchmark_harness: ^2.2.0 - dart_flutter_team_lints: ^2.0.0 + dart_flutter_team_lints: ^3.0.0 test: ^1.17.0 From 8d94c6437f30a0bb3ed24c20a04433c55820d2e2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 1 Jul 2024 07:52:03 +0000 Subject: [PATCH 096/100] Bump the github-actions group with 2 updates (dart-lang/convert#108) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps the github-actions group with 2 updates: [actions/checkout](https://github.com/actions/checkout) and [dart-lang/setup-dart](https://github.com/dart-lang/setup-dart). Updates `actions/checkout` from 4.1.6 to 4.1.7
Release notes

Sourced from actions/checkout's releases.

v4.1.7

What's Changed

New Contributors

Full Changelog: https://github.com/actions/checkout/compare/v4.1.6...v4.1.7

Changelog

Sourced from actions/checkout's changelog.

Changelog

v4.1.7

v4.1.6

v4.1.5

v4.1.4

v4.1.3

v4.1.2

v4.1.1

v4.1.0

v4.0.0

v3.6.0

v3.5.3

... (truncated)

Commits

Updates `dart-lang/setup-dart` from 1.6.4 to 1.6.5
Release notes

Sourced from dart-lang/setup-dart's releases.

v1.6.5

dart-lang/convert#118: dart-lang/setup-dartdart-lang/convert#118

Changelog

Sourced from dart-lang/setup-dart's changelog.

v1.6.5

dart-lang/convert#118: dart-lang/setup-dartdart-lang/convert#118

v1.6.4

  • Rebuild JS code.

v1.6.3

v1.6.2

v1.6.1

  • Updated the google storage url for main channel releases.

v1.6.0

  • Enable provisioning of the latest Dart SDK patch release by specifying just the major and minor version (e.g. 3.2).

v1.5.1

  • No longer test the setup-dart action on pre-2.12 SDKs.
  • Upgrade JS interop code to use extension types (the new name for inline classes).
  • The upcoming rename of the be channel to main is now supported with forward compatibility that switches when the rename happens.

v1.5.0

  • Re-wrote the implementation of the action into Dart.
  • Auto-detect the platform architecture (x64, ia32, arm, arm64).
  • Improved the caching and download resilience of the sdk.
  • Added a new action output: dart-version - the installed version of the sdk.

v1.4.0

... (truncated)

Commits

Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore major version` will close this group update PR and stop Dependabot creating any more for the specific dependency's major version (unless you unignore this specific dependency's major version or upgrade to it yourself) - `@dependabot ignore minor version` will close this group update PR and stop Dependabot creating any more for the specific dependency's minor version (unless you unignore this specific dependency's minor version or upgrade to it yourself) - `@dependabot ignore ` will close this group update PR and stop Dependabot creating any more for the specific dependency (unless you unignore this specific dependency or upgrade to it yourself) - `@dependabot unignore ` will remove all of the ignore conditions of the specified dependency - `@dependabot unignore ` will remove the ignore condition of the specified dependency and ignore conditions
--- pkgs/convert/.github/workflows/test-package.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pkgs/convert/.github/workflows/test-package.yml b/pkgs/convert/.github/workflows/test-package.yml index d43d1403..3e4eee61 100644 --- a/pkgs/convert/.github/workflows/test-package.yml +++ b/pkgs/convert/.github/workflows/test-package.yml @@ -22,8 +22,8 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 - - uses: dart-lang/setup-dart@f0ead981b4d9a35b37f30d36160575d60931ec30 + - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 + - uses: dart-lang/setup-dart@0a8a0fc875eb934c15d08629302413c671d3f672 with: sdk: ${{ matrix.sdk }} - id: install @@ -49,8 +49,8 @@ jobs: os: [ubuntu-latest] sdk: [3.4, dev] steps: - - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 - - uses: dart-lang/setup-dart@f0ead981b4d9a35b37f30d36160575d60931ec30 + - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 + - uses: dart-lang/setup-dart@0a8a0fc875eb934c15d08629302413c671d3f672 with: sdk: ${{ matrix.sdk }} - id: install From 30ce9ee235c9a9a124ddef21646f5391c2babcaf Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 4 Oct 2024 22:21:51 +0000 Subject: [PATCH 097/100] Bump actions/checkout from 4.1.7 to 4.2.0 in the github-actions group (dart-lang/convert#109) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps the github-actions group with 1 update: [actions/checkout](https://github.com/actions/checkout). Updates `actions/checkout` from 4.1.7 to 4.2.0
Release notes

Sourced from actions/checkout's releases.

v4.2.0

What's Changed

New Contributors

Full Changelog: https://github.com/actions/checkout/compare/v4.1.7...v4.2.0

Changelog

Sourced from actions/checkout's changelog.

Changelog

v4.2.0

v4.1.7

v4.1.6

v4.1.5

v4.1.4

v4.1.3

v4.1.2

v4.1.1

v4.1.0

v4.0.0

v3.6.0

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/checkout&package-manager=github_actions&previous-version=4.1.7&new-version=4.2.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore major version` will close this group update PR and stop Dependabot creating any more for the specific dependency's major version (unless you unignore this specific dependency's major version or upgrade to it yourself) - `@dependabot ignore minor version` will close this group update PR and stop Dependabot creating any more for the specific dependency's minor version (unless you unignore this specific dependency's minor version or upgrade to it yourself) - `@dependabot ignore ` will close this group update PR and stop Dependabot creating any more for the specific dependency (unless you unignore this specific dependency or upgrade to it yourself) - `@dependabot unignore ` will remove all of the ignore conditions of the specified dependency - `@dependabot unignore ` will remove the ignore condition of the specified dependency and ignore conditions
--- pkgs/convert/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/convert/.github/workflows/test-package.yml b/pkgs/convert/.github/workflows/test-package.yml index 3e4eee61..24df98db 100644 --- a/pkgs/convert/.github/workflows/test-package.yml +++ b/pkgs/convert/.github/workflows/test-package.yml @@ -22,7 +22,7 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 + - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 - uses: dart-lang/setup-dart@0a8a0fc875eb934c15d08629302413c671d3f672 with: sdk: ${{ matrix.sdk }} @@ -49,7 +49,7 @@ jobs: os: [ubuntu-latest] sdk: [3.4, dev] steps: - - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 + - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 - uses: dart-lang/setup-dart@0a8a0fc875eb934c15d08629302413c671d3f672 with: sdk: ${{ matrix.sdk }} From df1ee69fd80988822b89d3b9d8ade4d5ef52e9a2 Mon Sep 17 00:00:00 2001 From: Moritz Date: Tue, 15 Oct 2024 12:07:20 +0200 Subject: [PATCH 098/100] Moving fixes --- .github/labeler.yml | 4 ++ .../workflows/convert.yaml | 17 +++++++-- README.md | 1 + pkgs/convert/.github/dependabot.yaml | 14 ------- .../convert/.github/workflows/no-response.yml | 37 ------------------- pkgs/convert/.github/workflows/publish.yaml | 17 --------- pkgs/convert/CHANGELOG.md | 3 +- pkgs/convert/README.md | 2 +- pkgs/convert/pubspec.yaml | 4 +- 9 files changed, 23 insertions(+), 76 deletions(-) rename pkgs/convert/.github/workflows/test-package.yml => .github/workflows/convert.yaml (85%) delete mode 100644 pkgs/convert/.github/dependabot.yaml delete mode 100644 pkgs/convert/.github/workflows/no-response.yml delete mode 100644 pkgs/convert/.github/workflows/publish.yaml diff --git a/.github/labeler.yml b/.github/labeler.yml index 62e1bfae..cc876daf 100644 --- a/.github/labeler.yml +++ b/.github/labeler.yml @@ -3,3 +3,7 @@ "package-args": - changed-files: - any-glob-to-any-file: 'pkgs/args/**' + +"package-convert": + - changed-files: + - any-glob-to-any-file: 'pkgs/convert/**' diff --git a/pkgs/convert/.github/workflows/test-package.yml b/.github/workflows/convert.yaml similarity index 85% rename from pkgs/convert/.github/workflows/test-package.yml rename to .github/workflows/convert.yaml index 24df98db..5ad0deb2 100644 --- a/pkgs/convert/.github/workflows/test-package.yml +++ b/.github/workflows/convert.yaml @@ -1,17 +1,26 @@ name: Dart CI on: - # Run on PRs and pushes to the default branch. + # Run CI on pushes to the main branch, and on PRs against main. push: - branches: [ master ] + branches: [ main ] + paths: + - '.github/workflows/convert.yaml' + - 'pkgs/convert/**' pull_request: - branches: [ master ] + branches: [ main ] + paths: + - '.github/workflows/convert.yaml' + - 'pkgs/convert/**' schedule: - cron: "0 0 * * 0" - env: PUB_ENVIRONMENT: bot.github +defaults: + run: + working-directory: pkgs/convert/ + jobs: # Check code formatting and static analysis on a single OS (linux) # against Dart dev. diff --git a/README.md b/README.md index 1205554f..5e76e7be 100644 --- a/README.md +++ b/README.md @@ -9,6 +9,7 @@ This repository is home to various Dart packages under the [dart.dev](https://pu | Package | Description | Version | |---|---|---| | [args](pkgs/args/) | Library for defining parsers for parsing raw command-line arguments into a set of options and values. | [![pub package](https://img.shields.io/pub/v/args.svg)](https://pub.dev/packages/args) | +| [convert](pkgs/convert/) | Utilities for converting between data representations. | [![pub package](https://img.shields.io/pub/v/convert.svg)](https://pub.dev/packages/convert) | ## Publishing automation diff --git a/pkgs/convert/.github/dependabot.yaml b/pkgs/convert/.github/dependabot.yaml deleted file mode 100644 index bf6b38a4..00000000 --- a/pkgs/convert/.github/dependabot.yaml +++ /dev/null @@ -1,14 +0,0 @@ -# Dependabot configuration file. -version: 2 - -updates: - - package-ecosystem: github-actions - directory: / - schedule: - interval: monthly - labels: - - autosubmit - groups: - github-actions: - patterns: - - "*" diff --git a/pkgs/convert/.github/workflows/no-response.yml b/pkgs/convert/.github/workflows/no-response.yml deleted file mode 100644 index ab1ac498..00000000 --- a/pkgs/convert/.github/workflows/no-response.yml +++ /dev/null @@ -1,37 +0,0 @@ -# A workflow to close issues where the author hasn't responded to a request for -# more information; see https://github.com/actions/stale. - -name: No Response - -# Run as a daily cron. -on: - schedule: - # Every day at 8am - - cron: '0 8 * * *' - -# All permissions not specified are set to 'none'. -permissions: - issues: write - pull-requests: write - -jobs: - no-response: - runs-on: ubuntu-latest - if: ${{ github.repository_owner == 'dart-lang' }} - steps: - - uses: actions/stale@28ca1036281a5e5922ead5184a1bbf96e5fc984e - with: - # Don't automatically mark inactive issues+PRs as stale. - days-before-stale: -1 - # Close needs-info issues and PRs after 14 days of inactivity. - days-before-close: 14 - stale-issue-label: "needs-info" - close-issue-message: > - Without additional information we're not able to resolve this issue. - Feel free to add more info or respond to any questions above and we - can reopen the case. Thanks for your contribution! - stale-pr-label: "needs-info" - close-pr-message: > - Without additional information we're not able to resolve this PR. - Feel free to add more info or respond to any questions above. - Thanks for your contribution! diff --git a/pkgs/convert/.github/workflows/publish.yaml b/pkgs/convert/.github/workflows/publish.yaml deleted file mode 100644 index 27157a04..00000000 --- a/pkgs/convert/.github/workflows/publish.yaml +++ /dev/null @@ -1,17 +0,0 @@ -# A CI configuration to auto-publish pub packages. - -name: Publish - -on: - pull_request: - branches: [ master ] - push: - tags: [ 'v[0-9]+.[0-9]+.[0-9]+' ] - -jobs: - publish: - if: ${{ github.repository_owner == 'dart-lang' }} - uses: dart-lang/ecosystem/.github/workflows/publish.yaml@main - permissions: - id-token: write # Required for authentication using OIDC - pull-requests: write # Required for writing the pull request note diff --git a/pkgs/convert/CHANGELOG.md b/pkgs/convert/CHANGELOG.md index f7890683..8fc7ff5b 100644 --- a/pkgs/convert/CHANGELOG.md +++ b/pkgs/convert/CHANGELOG.md @@ -1,9 +1,10 @@ -## 3.1.2-wip +## 3.1.2 - Require Dart 3.4 - Add chunked decoding support (`startChunkedConversion`) for `CodePage` encodings. - Upper-cast the return type of the decoder from `List` to `Uint8List`. +- Move to `dart-lang/core` monorepo. ## 3.1.1 diff --git a/pkgs/convert/README.md b/pkgs/convert/README.md index 67e91aea..4efd4b0b 100644 --- a/pkgs/convert/README.md +++ b/pkgs/convert/README.md @@ -1,4 +1,4 @@ -[![Dart CI](https://github.com/dart-lang/convert/actions/workflows/test-package.yml/badge.svg)](https://github.com/dart-lang/convert/actions/workflows/test-package.yml) +[![Dart CI](https://github.com/dart-lang/core/actions/workflows/convert.yaml/badge.svg)](https://github.com/dart-lang/core/actions/workflows/convert.yaml) [![pub package](https://img.shields.io/pub/v/convert.svg)](https://pub.dev/packages/convert) [![package publisher](https://img.shields.io/pub/publisher/convert.svg)](https://pub.dev/packages/convert/publisher) diff --git a/pkgs/convert/pubspec.yaml b/pkgs/convert/pubspec.yaml index 9f0b1099..9050f995 100644 --- a/pkgs/convert/pubspec.yaml +++ b/pkgs/convert/pubspec.yaml @@ -1,9 +1,9 @@ name: convert -version: 3.1.2-wip +version: 3.1.2 description: >- Utilities for converting between data representations. Provides a number of Sink, Codec, Decoder, and Encoder types. -repository: https://github.com/dart-lang/convert +repository: https://github.com/dart-lang/core/main/pkgs/convert environment: sdk: ^3.4.0 From b0e5899a2045aee917f35ec3f70c8633a089ee6a Mon Sep 17 00:00:00 2001 From: Moritz Date: Tue, 15 Oct 2024 12:09:28 +0200 Subject: [PATCH 099/100] Add license to file --- pkgs/convert/test/identity_codec_test.dart | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/pkgs/convert/test/identity_codec_test.dart b/pkgs/convert/test/identity_codec_test.dart index 51a3a21b..1fb841f3 100644 --- a/pkgs/convert/test/identity_codec_test.dart +++ b/pkgs/convert/test/identity_codec_test.dart @@ -1,3 +1,7 @@ +// Copyright (c) 2024, 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 'dart:convert'; import 'package:convert/convert.dart'; import 'package:test/test.dart'; From 3303cceb19775f958bf377ecd378602a8cdfbbd3 Mon Sep 17 00:00:00 2001 From: Moritz Date: Wed, 16 Oct 2024 10:08:02 +0200 Subject: [PATCH 100/100] Changes as per review --- .github/labeler.yml | 2 +- .github/workflows/convert.yaml | 2 +- pkgs/convert/CONTRIBUTING.md | 33 --------------------------------- pkgs/convert/pubspec.yaml | 2 +- 4 files changed, 3 insertions(+), 36 deletions(-) delete mode 100644 pkgs/convert/CONTRIBUTING.md diff --git a/.github/labeler.yml b/.github/labeler.yml index cc876daf..10f8ca14 100644 --- a/.github/labeler.yml +++ b/.github/labeler.yml @@ -4,6 +4,6 @@ - changed-files: - any-glob-to-any-file: 'pkgs/args/**' -"package-convert": +"package:convert": - changed-files: - any-glob-to-any-file: 'pkgs/convert/**' diff --git a/.github/workflows/convert.yaml b/.github/workflows/convert.yaml index 5ad0deb2..3422c179 100644 --- a/.github/workflows/convert.yaml +++ b/.github/workflows/convert.yaml @@ -1,4 +1,4 @@ -name: Dart CI +name: package:convert on: # Run CI on pushes to the main branch, and on PRs against main. diff --git a/pkgs/convert/CONTRIBUTING.md b/pkgs/convert/CONTRIBUTING.md deleted file mode 100644 index 6f5e0ea6..00000000 --- a/pkgs/convert/CONTRIBUTING.md +++ /dev/null @@ -1,33 +0,0 @@ -Want to contribute? Great! First, read this page (including the small print at -the end). - -### Before you contribute -Before we can use your code, you must sign the -[Google Individual Contributor License Agreement](https://cla.developers.google.com/about/google-individual) -(CLA), which you can do online. The CLA is necessary mainly because you own the -copyright to your changes, even after your contribution becomes part of our -codebase, so we need your permission to use and distribute your code. We also -need to be sure of various other things—for instance that you'll tell us if you -know that your code infringes on other people's patents. You don't have to sign -the CLA until after you've submitted your code for review and a member has -approved it, but you must do it before we can put your code into our codebase. - -Before you start working on a larger contribution, you should get in touch with -us first through the issue tracker with your idea so that we can help out and -possibly guide you. Coordinating up front makes it much easier to avoid -frustration later on. - -### Code reviews -All submissions, including submissions by project members, require review. - -### File headers -All files in the project must start with the following header. - - // Copyright (c) 2015, 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. - -### The small print -Contributions made by corporations are covered by a different agreement than the -one above, the -[Software Grant and Corporate Contributor License Agreement](https://developers.google.com/open-source/cla/corporate). diff --git a/pkgs/convert/pubspec.yaml b/pkgs/convert/pubspec.yaml index 9050f995..97685ff3 100644 --- a/pkgs/convert/pubspec.yaml +++ b/pkgs/convert/pubspec.yaml @@ -3,7 +3,7 @@ version: 3.1.2 description: >- Utilities for converting between data representations. Provides a number of Sink, Codec, Decoder, and Encoder types. -repository: https://github.com/dart-lang/core/main/pkgs/convert +repository: https://github.com/dart-lang/core/tree/main/pkgs/convert environment: sdk: ^3.4.0